Joda-Time, daylight saving time and date time change

I have the following problem using Joda-Time to analyze and create date and time around Daylight Saving Time (DST). Here is an example (please note that March 30, 2008 is daylight saving time in Italy):

DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
DateTime x = dtf.parseDateTime("30/03/2008 03:00:00");
int h = x.getHourOfDay();
System.out.println(h);
System.out.println(x.toString("dd/MM/yyyy HH:mm:ss"));
DateTime y = x.toDateMidnight().toDateTime().plusHours(h);
System.out.println(y.getHourOfDay());
System.out.println(y.toString("dd/MM/yyyy HH:mm:ss"));

I get the following output:

3
30/03/2008 03:00:00
4
30/03/2008 04:00:00

When I look at the hour, I get hour 3. In my data structure, I save the day, saving midnight, and then I have a value for each hour of the day (0-23). Then, when I write the date, I recount the date of the full date of midnight plus an hour. When I get 3 hours before midnight, I get 04:00:00! And if I take it apart again, I get 4 hours!

? 2, , ?

:

String.format("%s %02d:00:00", date.toString("dd/MM/yyyy"), h);

2 30/03/2008 02:00:00, ( 2 ) .

.

+5
3

, , . 23 .

:

    DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss").withLocale(Locale.US);
    DateTime x = dtf.parseDateTime("30/03/2008 00:00:00");

    DateTimeFormatter parser = DateTimeFormat.fullDateTime();
    System.out.println("Start:"+parser.print(x));

    DateTime y = x.plusHours(4);

    System.out.println("After add of 4:"+parser.print(y));

, 05:00.

. , .

- : , , 4, 5 5. , plusHours() . , - :

public class DateTest {
    private static final int HOUR_TO_TEST = 2;

  public static void main(String[] args) {
    DateTimeFormatter dtf = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
    DateTime startOfDay = dtf.parseDateTime("30/03/2008 00:00:00");

    /* Obtained from new DateTime() in code in practice */
    DateTime actualTimeWhenStoring = startOfDay.plusHours(HOUR_TO_TEST);

    int hourOfDay = actualTimeWhenStoring.getHourOfDay();
    int hourOffset = startOfDay.plusHours(hourOfDay).getHourOfDay();

    System.out.println("Hour of day:" + hourOfDay);
    System.out.println("Offset hour:" + hourOffset);

    int timeToSave = hourOfDay;
    if (hourOffset != hourOfDay) {
        timeToSave = (hourOfDay + (hourOfDay - hourOffset));
    }
    System.out.println("Time to save:" + timeToSave);

    /* When obtaining from db: */
    DateTime recalculatedTime = startOfDay.plusHours(timeToSave);

    System.out.println("Hour of time 'read' from db:" + recalculatedTime.getHourOfDay());
  }
}

... - . , . HOUR_TO_TEST, , .

+4

3 , 04:00:00! , 4! ?

, . . 30 2010 00:00 CEST ( ) 29 2010 23:00 UTC. 3 , 30 2010 02:00 UTC. , ( 01:00 UTC), , , 30 , 04:00. .

2, , ?

, 30 2010 02:00 CEST . 30 2010 . 01:00 UTC +1 +2 UTC, 30 2010 00:59 UTC - 30 2010: 01:59 CEST, 30 2010 . 01: 00 UTC 30 2010 . 03:00 CEST. 02: xx .

BTW. "". , UTC :

31 2010 . 02:15 CEST?

, , . 0 31, 2010 00:15 UTC ( ), 31 2010 01:15 UTC ( ).

UTC , .

.

+5

Paweł Dyda Knubo...

ISO 8601

(serialize) - : "30/03/2008 03:00:00". :

  • .
  • , , .
  • UTC.

, . ISO 8601. UTC (Zulu), ISO 8601. : 2013-11-01T04:48:53.044Z

midnight Joda-Time Joda-Time withTimeAtStartOfDay() (. doc). .

Joda-Time 2.3

:

    // © 2013 Basil Bourque. This source code may be used freely forevery by anyone taking full responsibility for doing so.

    // Joda-Time - The popular alternative to Sun/Oracle notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
    // http://www.joda.org/joda-time/

    // Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
    // JSR 310 was inspired by Joda-Time but is not directly based on it.
    // http://jcp.org/en/jsr/detail?id=310

    // By default, Joda-Time produces strings in the standard ISO 8601 format.
    // https://en.wikipedia.org/wiki/ISO_8601

, 23 DST ( ) , - 24 . , ( ).

    // Time Zone list: http://joda-time.sourceforge.net/timezones.html
    org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
    org.joda.time.DateTime dayOfDstChange = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ) ; // Day when DST
    org.joda.time.DateTime dayAfter = dayOfDstChange.plusDays(1);

    // How many hours in this day? Should be 23 rather than 24 on day of Daylight Saving Time "springing ahead" to lose one hour.
    org.joda.time.Hours hoursObjectForDay = org.joda.time.Hours.hoursBetween(dayOfDstChange.withTimeAtStartOfDay(), dayAfter.withTimeAtStartOfDay());
    System.out.println( "Expect 23 hours, got: " + hoursObjectForDay.getHours() ); // Extract an int from object.

    // What time is 3 hours after midnight on day of DST change?
    org.joda.time.DateTime threeHoursAfterMidnightOnDayOfDst = dayOfDstChange.withTimeAtStartOfDay().plusHours(3);
    System.out.println( "Expect 4 AM (04:00) for threeHoursAfterMidnightOnDayOfDst: " + threeHoursAfterMidnightOnDayOfDst );

    // What time is 3 hours after midnight on day _after_ DST change?
    org.joda.time.DateTime threeHoursAfterMidnightOnDayAfterDst = dayAfter.withTimeAtStartOfDay().plusHours(3);
    System.out.println( "Expect 3 AM (03:00) for threeHoursAfterMidnightOnDayAfterDst: " + threeHoursAfterMidnightOnDayAfterDst );

-, UTC. .

    // Serialize DateTime object to text.
    org.joda.time.DateTimeZone romeTimeZone = org.joda.time.DateTimeZone.forID("Europe/Rome");
    org.joda.time.DateTime dayOfDstChangeAtThreeHoursAfterMidnight = new org.joda.time.DateTime( 2008, 3, 30, 0, 0, romeTimeZone ).withTimeAtStartOfDay().plusHours(3);
    System.out.println("dayOfDstChangeAtThreeHoursAfterMidnight: " + dayOfDstChangeAtThreeHoursAfterMidnight);
    // Usually best to first change to UTC (Zulu) time when serializing.
    String dateTimeSerialized = dayOfDstChangeAtThreeHoursAfterMidnight.toDateTime( org.joda.time.DateTimeZone.UTC ).toString();
    System.out.println( "dateTimeBeingSerialized: " + dateTimeSerialized );
    // Restore
    org.joda.time.DateTime restoredDateTime = org.joda.time.DateTime.parse( dateTimeSerialized );
    System.out.println( "restoredDateTime: " + restoredDateTime );
    // Adjust to Rome Italy time zone.
    org.joda.time.DateTime restoredDateTimeAdjustedToRomeItaly = restoredDateTime.toDateTime(romeTimeZone);
    System.out.println( "restoredDateTimeAdjustedToRomeItaly: " + restoredDateTimeAdjustedToRomeItaly );

:

dayOfDstChangeAtThreeHoursAfterMidnight: 2008-03-30T04:00:00.000+02:00
dateTimeBeingSerialized: 2008-03-30T02:00:00.000Z
restoredDateTime: 2008-03-30T02:00:00.000Z
restoredDateTimeAdjustedToRomeItaly: 2008-03-30T04:00:00.000+02:00
+1

All Articles