Why is conversion from LocalDateTime to Instant not working?

282 views Asked by At

Do you know why 4. and 6. prints have wrong hours in following code?

LocalDateTime ldtNow = LocalDateTime.now();
LocalDateTime ldtNextMonth = ldtNow.plusMonths(1);

System.out.println("1. " + ldtNow);
System.out.println("2. " + ldtNextMonth);

System.out.println("3. " + ldtNow.atZone(ZoneId.systemDefault()).toInstant().toString());
System.out.println("4. " + ldtNextMonth.atZone(ZoneId.systemDefault()).toInstant().toString());

System.out.println("5. " + ldtNow.atZone(ZoneOffset.systemDefault()).toInstant().toString());
System.out.println("6. " + ldtNextMonth.atZone(ZoneOffset.systemDefault()).toInstant().toString());

This is what it prints:

 1. 2022-10-26T16:53:59.691891
 2. 2022-11-26T16:53:59.691891

 3. 2022-10-26T14:53:59.691891Z
 4. 2022-11-26T15:53:59.691891Z //WRONG?

 5. 2022-10-26T14:53:59.691891Z
 6. 2022-11-26T15:53:59.691891Z //WRONG?

Prints 3. & 4. test it with ZoneId and prints 5. & 6. with ZoneOffset.

The only difference between 3. & 4. (and 5. & 6.) is the usage of LocalDateTime#plusMonths method. What should I do to get right result for zero time (2022-11-26T14:53:59.691891Z)?

1

There are 1 answers

1
c3R1cGFy On BEST ANSWER

The method atZone() returns ZonedDatetime and then you experience the daylight saving effect. Different zones around the globe have daylight saving at different dates.

So your prints are:

 1. 2022-10-26T16:53:59.691891  // LocalDateTime
 2. 2022-11-26T16:53:59.691891  // LocalDateTime

 3. 2022-10-26T14:53:59.691891Z // ZonedDateTime
 4. 2022-11-26T15:53:59.691891Z // ZonedDateTime

 5. 2022-10-26T14:53:59.691891Z // ZonedDateTime
 6. 2022-11-26T15:53:59.691891Z // ZonedDateTime  

UTC time zone is like a reference point for any other timezone. For example CET, central european time timezone have the zone offsets of UTC+2 and UTC+1 depending on the period of the year.

You can see this effect by executing the following snippet:

ZonedDateTime zdt1 = ldtNow.atZone(ZoneOffset.systemDefault());
ZonedDateTime zdt2 = ldtNextMonth.atZone(ZoneOffset.systemDefault());

System.out.println(ZoneOffset.from(zdt1));   // prints +02:00
System.out.println(ZoneOffset.from(zdt2));   // prints +01:00