Bug in Calendar when setting time across daylight-saving boundaries?!
Bryce McKinlay
mckinlay@redhat.com
Mon Oct 4 22:05:00 GMT 2004
Martin,
I took a quick look at this. On mainline I do not see a problem with
day-of-month changing, so I guess this has already been fixed - probably
with Mark Wielaard's recent Calendar improvements.
I did see the problem with the hour-of-day being wrong. The problem here
is that Calendar.set does not invalidate the DST_OFFSET field even
though changing other fields could roll the time over a DST boundary.
Thus, computeTime() applies the DST offset to the resulting Date value
even if the date is no longer in a DST period.
This patch below should fix the problem. I haven't yet tested this
extensively. Could you submit a mauve regression test, based on your
test case?
Thanks
Bryce
2004-10-04 Bryce McKinlay <mckinlay@redhat.com>
* java/util/Calendar.java (set): Invalidate DST_OFFSET as setting a
calendar field may roll over a DST boundary.
--- Calendar.java 29 Aug 2004 17:28:09 -0000 1.23
+++ Calendar.java 4 Oct 2004 22:02:42 -0000
@@ -651,6 +651,10 @@
isSet[HOUR_OF_DAY] = false;
break;
}
+
+ // We may have rolled over a DST boundary.
+ if (field != DST_OFFSET && field != ZONE_OFFSET)
+ isSet[DST_OFFSET] = false;
}
/**
Martin Egholm Nielsen wrote:
> Hi there,
>
> I was just about to tear my hear out, when I suddenly discovered that
> gcj's Calendar had some problems returning a correct Date-instance
> [getTime()] when you have changed the date of a Calendar-instance
> across the boundary of daylight-savings.
> I little complicated in short terms, but consider todays date where I
> live - it's October the 2nd. Hence, we are using daylight-savings. If
> I then fetch a Calendar instance and change the month to November, the
> same day of month, and the same hour of day, I have passed the date of
> daylight savings, but then it goes wrong.
> The calendar instance representing the future date calculates the
> Date-instance wrong if I invoke #getTime(). The hour of day is an hour
> short, but the day of month has suddenly gained a day - weird.
> Consider the following output from an example-application compiled
> with gcj illustrating the bug:
>
> ======== OUTPUT FROM GCJ ========
> Calendar's date before: Sat Oct 02 10:30:52 GMT+02:00 2004
> Calendar's date after: Wed Nov 03 09:30:52 GMT+01:00 2004
>
> Calendar reports hour-of-day before: 10
> Calendar reports hour-of-day after: 10
> Calendar's date reports hour-of-day before: 10
> Calendar's date reports hour-of-day after: 9
>
> Calendar reports day-of-month before: 2
> Calendar reports day-of-month after: 2
> Calendar's date reports day-of-month before: 2
> Calendar's date reports day-of-month after: 3
>
>
> Sun's Java returns the expected:
>
> ======== OUTPUT FROM SUN ========
> Calendar's date before: Sat Oct 02 10:11:28 GMT+02:00 2004
> Calendar's date after: Tue Nov 02 10:11:28 GMT+01:00 2004
>
> Calendar reports hour-of-day before: 10
> Calendar reports hour-of-day after: 10
> Calendar's date reports hour-of-day before: 10
> Calendar's date reports hour-of-day after: 10
>
> Calendar reports day-of-month before: 2
> Calendar reports day-of-month after: 2
> Calendar's date reports day-of-month before: 2
> Calendar's date reports day-of-month after: 2
>
>
> I have attached the example application.
> Does anybody know if this bug has been corrected in recent libgcj's?
> I've seen it with both gcj 3.3.3 and 3.4.0.
>
> Best regards,
> Martin Egholm
>
>------------------------------------------------------------------------
>
>import java.util.Calendar;
>import java.util.Date;
>import java.util.SimpleTimeZone;
>import java.util.TimeZone;
>
>public class CalendarTest {
>// private Class c = gnu.java.locale.Calendar.class;
>
> public static void main(String[] args) {
> // Create a timezone with daylight savings enabled from the last sunday
> // of march, and until the last sunday of october:
> SimpleTimeZone stz = new SimpleTimeZone(60 * 60 * 1000, "MyZone",
> Calendar.MARCH, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000,
> Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
>
> // Register the timezone as the default:
> TimeZone.setDefault(stz);
>
> Calendar cal = Calendar.getInstance();
> Date calendarsDateBefore = cal.getTime();
> System.out.println("Calendar's date before: " + calendarsDateBefore );
>
> // Let's store the hour-of-day and day of month for later:
> int hourOfDayBefore = cal.get(Calendar.HOUR_OF_DAY);
> int dayOfMonthBefore = cal.get(Calendar.DAY_OF_MONTH);
>
> int changeMonthTo;
>
> // Let's test if our current date is in the dst-area:
> if (stz.inDaylightTime(cal.getTime())) {
> changeMonthTo = Calendar.NOVEMBER;
> } // if
> else {
> changeMonthTo = Calendar.APRIL;
> } // else
>
> // Set the month to a month with different dst-settings that the one
> // we're in now:
> cal.set(Calendar.MONTH, changeMonthTo);
>
> // Specifically set the hour of day and day of month to the same as
> // before:
> cal.set(Calendar.HOUR_OF_DAY, hourOfDayBefore);
> cal.set(Calendar.DAY_OF_MONTH, dayOfMonthBefore);
>
> Date calendarsDateAfter = cal.getTime();
> System.out.println("Calendar's date after: " + calendarsDateAfter );
>
> int hourOfDayAfter = cal.get(Calendar.HOUR_OF_DAY);
> int dayOfMonthAfter = cal.get(Calendar.DAY_OF_MONTH);
>
> System.out.println();
> System.out.println("Calendar reports hour-of-day before: "
> + hourOfDayBefore);
> System.out.println("Calendar reports hour-of-day after: "
> + hourOfDayAfter);
> System.out.println("Calendar's date reports hour-of-day before: "
> + calendarsDateBefore.getHours());
> System.out.println("Calendar's date reports hour-of-day after: "
> + calendarsDateAfter.getHours());
>
> System.out.println();
>
> System.out.println("Calendar reports day-of-month before: "
> + dayOfMonthBefore);
> System.out.println("Calendar reports day-of-month after: "
> + dayOfMonthAfter);
> System.out.println("Calendar's date reports day-of-month before: "
> + calendarsDateBefore.getDate());
> System.out.println("Calendar's date reports day-of-month after: "
> + calendarsDateAfter.getDate());
> } // main
>} // CalendarTest
>
>
More information about the Java
mailing list