Stanislav Bashkyrtsev - 2 years ago 157
Java Question

# ZonedDateTime & LocalDateTime are different for 100 years ago

The behaviour that I see is very strange - sometimes

`LocalDateTime`
would be equal to
`ZonedDateTime`
, 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
`jdk1.8.0_65`
and
`jdk1.8.0_91`
,
`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:

``````assertEquals(
LocalDateTime.now(offset).minusYears(85).toInstant(offset),
ZonedDateTime.now().minusYears(85).withZoneSameInstant(offset).toInstant());
``````

For 1919 it's 1 hour difference:

``````assertEquals(
LocalDateTime.now(offset).minusYears(86).toInstant(offset),
ZonedDateTime.now().minusYears(86).withZoneSameInstant(offset).toInstant());

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

For 1920 it's 2 hours difference:

``````assertEquals(
LocalDateTime.now(offset).minusYears(95).toInstant(offset),
ZonedDateTime.now().minusYears(95).withZoneSameInstant(offset).toInstant());

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

For 1921 again milli or nano seconds difference:

``````assertEquals(
LocalDateTime.now(offset).minusYears(96).toInstant(offset),
ZonedDateTime.now().minusYears(96).withZoneSameInstant(offset).toInstant());
``````

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

``````assertEquals(
LocalDateTime.now(offset).minusYears(97).toInstant(offset),
ZonedDateTime.now().minusYears(97).withZoneSameInstant(offset).toInstant());

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

# Update

As @Tunaki pointed I had to specify the offset for the
`ZonedDateTime`
:

``````assertEquals(
LocalDateTime.now(offset).minusYears(95).toInstant(offset),
ZonedDateTime.now(offset).minusYears(95).withZoneSameInstant(offset).toInstant());
``````

The problem is that this doesn't know about Time Zones: `LocalDateTime.now(offset).minusYears(97).toInstant(offset)`. There is only offset present. But this knows about the time zone: `ZonedDateTime.now().minusYears(97).toInstant()`

• `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: `ZonedDateTime.now(offset).minusYears(97)`. 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(Instant.now());
assertEquals(
LocalDateTime.now(offset).minusYears(97).toInstant(offset),
ZonedDateTime.now(offset).minusYears(97).toInstant());
``````

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

``````ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Europe/Moscow")).minusYears(97);
ZoneOffset offset = zoned.getOffset();//agrees with history
assertEquals(
LocalDateTime.now().minusYears(97).toInstant(offset),
zoned.toInstant());
``````

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download