Search code examples
javadatetimezonedst

java 1.6 daylight saving


I'm working on a critical application which cares about daylight saving time change.
I'm trying to simulate manually what could happen at runtime by comparing thow date which cross the daylight saving change, so I made the below test. My current location is Italy so the change from CEST (Central European Summer Time) to CET (Central European Time) this year happens on 25/10.
I used the full time zone names, my timezone is Europe/Rome.

And here it is the test I did:

Calendar before = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome DST")); //CEST
before.set(Calendar.DAY_OF_MONTH, 25);
before.set(Calendar.MONTH, Calendar.OCTOBER);
before.set(Calendar.HOUR_OF_DAY, 2);
before.set(Calendar.MINUTE, 30);
before.set(Calendar.SECOND, 0);
before.set(Calendar.MILLISECOND, 0);

System.out.println(before.getTime());

Calendar after = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome")); //CET
after.set(Calendar.DAY_OF_MONTH, 25);
after.set(Calendar.MONTH, Calendar.OCTOBER);
after.set(Calendar.HOUR_OF_DAY, 2);
after.set(Calendar.MINUTE, 30);
after.set(Calendar.SECOND, 0);
after.set(Calendar.MILLISECOND, 0);

System.out.println(after.getTime());

System.out.println(before.compareTo(after));

The output is:

BEFORE DST CHANGE: Sun Oct 25 03:30:00 CET 2015
AFTER DST CHANGE: Sun Oct 25 02:30:00 CET 2015
before.compareTo(after): 1

The comparison result is wrong, i.e. 2:30 CEST is after 2:30 CET, but its the opposite.

I don't know if it's a real test.
Is it Is there any way to fix this?
I tried also with joda time but the result is the same.
Thanks in advance.


Solution

  • Your problem is that "Europe/Rome DST" is not recognized by getTimeZone(timeZoneId).
    When it doesn't understand your input, it returns the GMT timezone by default. You can see the list of available TimeZone ids with getAvailableIDs (the method below getTimeZone at the above link).

    It should be noted that CEST is also not on the list. To simulate the CEST timezone you could choose one of the following solutions:

    • I would recommend using TimeZone.setRawOffset(int offsetInMs) to set the offests for CET and CEST yourself.
    • Use one of the timzones that is defined relative to GMT (ex, with id "Etc/GMT+1"). This will ensure that you are using valid timezone offsets the the TimeZone api will understand.
    • Set the DST offset on the calendar instance Calendar.DST_OFFSET.

    By using the last solution the correct test code is:

    Calendar before = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"));
    before.set(Calendar.DST_OFFSET, 3600000);       
    before.set(Calendar.DAY_OF_MONTH, 25);
    before.set(Calendar.MONTH, Calendar.OCTOBER);
    before.set(Calendar.HOUR_OF_DAY, 2);
    before.set(Calendar.MINUTE, 30);
    before.set(Calendar.SECOND, 0);
    before.set(Calendar.MILLISECOND, 0);
    
    System.out.println("BEFORE DST CHANGE: " + before.getTime());       
    
    Calendar after = Calendar.getInstance(TimeZone.getTimeZone("Europe/Rome"));
    after.set(Calendar.DAY_OF_MONTH, 25);
    after.set(Calendar.MONTH, Calendar.OCTOBER);
    after.set(Calendar.HOUR_OF_DAY, 2);
    after.set(Calendar.MINUTE, 30);
    after.set(Calendar.SECOND, 0);
    after.set(Calendar.MILLISECOND, 0);
    
    System.out.println("AFTER DST CHANGE: " + after.getTime());
    
    System.out.println("before.compareTo(after): " + before.compareTo(after));
    

    And the output:

    BEFORE DST CHANGE: Sun Oct 25 02:30:00 CEST 2015
    AFTER DST CHANGE: Sun Oct 25 02:30:00 CET 2015
    before.compareTo(after): -1