vickirk's solution wasn't so bad, but has timezone issues, which results in the one hour less you observed.
I suppose, BST means British Summer Time, which is GMT +0100. Now, java.util.Date and its descendants internally work with numbers of milliseconds since midnight Jan 01, 1970 GMT. The timezone is not taken into account until you stringfy the date/time with toString()
. And they use your local timezone for that, which is BST, apparently. That means, what is really stored in these objects, is
java.util.date: Mon May 09 23:00:00 GMT 2011
java.sql.time: 02:58:44 GMT
When you add the internal values (which are retrieved by getTime()
) like vickirk suggested, you obtain a date which contains
Tue May 10 01:58:44 GMT 2011, which then results in
Tue May 10 02:58:44 BST 2011 on stringification.
So the explanation for the one hour less is that the timezone offset applies twice, when you stringified the values separately, whereas it applies only once after the addition, because you stringfy only once now. Or, from another point of view, adding the internal value of the point in time 03:58:44 BST is equivalent to adding a time span of 2h 58m 44s.
So to get a time span of 3h 58m 44s encoded in a java.sql.Time, you have to make up for the time zone offset manually. You do that by parsing the time string "00:00:00" with java.sql.Time, which will result in an internal value of -3600000
which is equivalent to 31 Dec 1969 23:00:00 GMT, i.e. one hour before the epoch. This is the negative of the time zone offset.
public static Date mergeDate(Date date, Time time) {
long tzoffset = -(Time.valueOf("00:00:00").getTime());
return new Date(date.getTime() + time.getTime() + tzoffset);
}
Of course, all this is a dirty hack, which is necessary because you insist on interpreting the Time's value as a time span, while it really is a point in time.