Search code examples
javajodatimedstperiod

Joda-Time, daylight savings calculation, timezone independent tests


We use fixed time periods in the application. When the user adds a new period, it should be by default from 6:00 AM to 6:00 AM the next day.

Normally, it's 24 hours, but there is one issue : when the daylight saving change is performed, the length of that period changes. For example :

27 October 6:00 AM to 28 October 6:00 AM. In this period is performed change shift from CEST to CET time zone. Thus, this period contains 25 hours :

From 27 October 6:00 AM to 28 October 3:00 AM - there are 21 hours
at 3:00 am the time is shifted back by 1 hour, so there are 4 hours until 28 October 6:00 AM.

We encountered this issue and tried to write a unit test to prevent it from appearing again. The test passes successfully on our machines, but fails on the CI server ( it's in another time zone ).

The question is : how can we possible design our unit test independently from the machine's time zone ?

Currently, the calculation of hours span is calculated using Joda-Time:

    if ((aStartDate == null) || (aEndDate == null)) {
        return 0;
    }
    final DateTime startDate = new DateTime(aStartDate);
    final DateTime endDate = new DateTime(aEndDate);
    return Hours.hoursBetween(startDate, endDate).getHours();

Unit test that passes on our side but fails on CI server :

    Calendar calendar = Calendar.getInstance();
    calendar.set(2012, Calendar.OCTOBER, 27, 6, 0);
    startDate= calendar.getTime();
    calendar.set(2012, Calendar.OCTOBER, 28, 6, 0);
    endDate= calendar.getTime();

We tried to use time zones for calendar :

    TimeZone.setDefault(TimeZone.getTimeZone(TimeZone.getTimeZone("GMT").getID()));
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(TimeZone.getTimeZone("GMT").getID()));
    calendar.set(2012, Calendar.OCTOBER, 27, 6, 0, 0);
    startDate= calendar.getTime();
    calendar.set(2012, Calendar.OCTOBER, 28, 6, 0, 0);
    endDate= calendar.getTime();

but in this case the result startDate is 27 October 9:00 CEST and endDate is 28 October 8:00 CET, so the test fails even on our side.

Thank you in advance.


Solution

  • As I understood your question, you want to set a time zone on the server to test the correct hours during daylight time switches instead of using the standard server time zone. To achieve that, the time zone needs to be able to use daylight saving offsets.

    The time zone you used on the server in your example

    TimeZone zone = TimeZone.getTimeZone("GMT");
    

    does not use daylight time: zone.useDaylightTime() returns false.

    Try using a specific time zone instead, e.g.

    TimeZone zone = TimeZone.getTimeZone("Europe/Chisinau");
    

    has daylight saving offsets.

    You can also use time zones in Joda Time's DateTime classes and avoid using Java's Calendar and Date classes.