This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Bug in Calendar when setting time across daylight-saving boundaries?!


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




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]