-->

Merge java.util.date with java.sql.Time

2020-04-09 00:15发布

问题:

I have an extensive DATE-TIME conversion class, but i came across a scenario that i cannot resolve:

I have a java.util.date: Tue May 10 00:00:00 BST 2011
I have a java.sql.time: 03:58:44

I need to create a java.util.date: Tue May 10 03:58:44 BST 2011

The only approach i came up with is:

public static Date getDate(Date date, Time time) {
    Calendar calendar=Calendar.getInstance();
    calendar.set(date.getYear(), date.getMonth(), date.getDay(), time.getHours(), time.getMinutes(), time.getSeconds());
    return calendar.getTime();
}

Totally deprecated code, and does not work: java.lang.IllegalArgumentException at java.sql.Time.getYear(Unknown Source)

Any ideas?

回答1:

java.sql.Time is just a wrapper over the java.util.Date. You can use it as if you would add two java.util.Date objects.

For example, set Calendar to java.sql.Time:

calendar.setTime(time);

Now extract the hour/minute/seconds fields, i.e.:

calendar.get(Calendar.HOUR);

Next, set the Calendar to java.util.Date object and add these three fields to its time, i.e.:

calendar.add(Calendar.HOUR, hour);

And get the Date back:

calendar.getTime();


回答2:

Easiest way would be to just add the milli secs together to create a new date, ala

public static Date getDate(Date date, Time time) {
    return new Date(date.getTime() + time.getTime())
}


回答3:

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.



回答4:

Instead, you can use this.

   public static Date getDate(Date date, Time time) {
        Calendar calendar=Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
        calendar.setTime(date);
        calendar.add(Calendar.MILLISECOND, (int) time.getTime());
        return calendar.getTime();
    }


回答5:

Can you do

java.util.Date newDate = new java.util.Date(sqlDate.getTime());


回答6:

try these

 public static Date getDate(Date date, Time time) {
            Calendar calendar=Calendar.getInstance();
            calendar.setTime(date);
            Calendar calendar1=Calendar.getInstance();
            calendar1.setTime(time);
            calendar.set(Calendar.MINUTE, calendar1.get(Calendar.MINUTE));
            calendar.set(Calendar.SECOND, calendar1.get(Calendar.SECOND));
            calendar.set(Calendar.HOUR_OF_DAY, calendar1.get(Calendar.HOUR_OF_DAY));
            return calendar.getTime();
        }