Search code examples
javacalendardstgregorian-calendar

GregorianCalendar DST problems


If I take the time at the end of the autumn day light time shift (2014-10-26 02:00:00 CET in Denmark) and subtract one hour (so I would expect to go back to 02:00 CEST) and then set the minutes to zero, I get some strange results:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CET"));

cal.set(Calendar.YEAR, 2014);
cal.set(Calendar.MONTH, Calendar.OCTOBER);
cal.set(Calendar.DAY_OF_MONTH, 26);
cal.set(Calendar.HOUR_OF_DAY, 2);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

System.out.println(cal.getTimeInMillis()); // 1414285200000 : 01:00:00 UTC

cal.add(Calendar.HOUR_OF_DAY, -1);

System.out.println(cal.getTimeInMillis()); // 1414281600000 : 00:00:00 UTC (as expected)

cal.set(Calendar.MINUTE, 0);
// or: cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE));
// both should be NOPs.

System.out.println(cal.getTimeInMillis()); // 1414285200000 : 01:00:00 UTC (Why?!)

Is this a bug? I know that Java Calendar has some strange conventions, but I cannot see how this could be correct.

What is the correct way to subtract an hour and set the minutes to 0 using the Calendar class?


Solution

  • Here are the comments to the similar "bug" from Java Bug tracker:

    During the "fall-back" period, Calendar doesn't support disambiguation and the given local time is interpreted as standard time.

    To avoid the unexpected DST to standard time change, call add() to reset the value.

    This means you should replace set() with

    cal.add(Calendar.MINUTE, -cal.get(Calendar.MINUTE));