Stanislav Bashkyrtsev Stanislav Bashkyrtsev - 4 months ago 33
Java Question

ZonedDateTime & LocalDateTime are different for 100 years ago

The behaviour that I see is very strange - sometimes

would be equal to
, other times it will differ by 1 hour or 2 and sometimes it's 30 minutes. All these strange differences depend on the year that I subtract. Can someone explain what's happening? Tried
MacOS 10.11.5
. I work with UTC:

ZoneOffset offset = ZoneOffset.UTC;

Here are some experiments. For 1919 values may differ by nano or milliseconds, which is expected:


For 1919 it's 1 hour difference:


Expected :<1930-05-28T20:19:10.383Z>
Actual :<1930-05-28T21:19:10.383Z>

For 1920 it's 2 hours difference:


Expected :<1921-05-28T20:21:45.094Z>
Actual :<1921-05-28T18:21:45.094Z>

For 1921 again milli or nano seconds difference:


And the weirdest of all - 1930 year with 30 mins difference:


Expected :<1919-05-28T20:24:27.345Z>
Actual :<1919-05-28T19:53:08.346Z>


As @Tunaki pointed I had to specify the offset for the



The problem is that this doesn't know about Time Zones: There is only offset present. But this knows about the time zone:

  • ZoneId contains information about the place and the time difference at that place. It knows that N years ago in that particular time zone the offset was 2 hours, not 3 as it is now.
  • ZoneOffset keeps track only about the hours/minutes shift. It doesn't know the history of time changes in a particular country. It just "adds hours".

The suggested (and a little bit incorrect) solution is to let ZonedDateTime to forget about zones and use offset instead: This now would agree with LocalDateTime with the same offset - both would show same incorrect information. But they would agree since both "just add hours" instead of understanding the time difference at that point of history for that place:

ZoneOffset offset = ZoneId.of("Europe/Moscow").getRules().getOffset(;
assertEquals(,      ;

Alternatively we can set the LocalDateTime to show the correct value for that time for that place:

ZonedDateTime zoned ="Europe/Moscow")).minusYears(97);
ZoneOffset offset = zoned.getOffset();//agrees with history

PS: This all shows that ZonedDateTime can work differently in different situations - sometimes it knows about time zones, other times it just "adds hours" as you would do with LocalDateTime by setting the offset manually. To me this is a weird implementation. JodaTime probably is still the best Java implementation. At least you don't have to learn it for several days to understand it.