0

I am trying to understand why is it that the result of the code is -2, initially I thought it should be -1, but this one really puzzled me

LocalDateTime ld1 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 0);
ZonedDateTime zd1 = ZonedDateTime.of(ld1, ZoneId.of("US/Eastern"));
LocalDateTime ld2 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
long x = ChronoUnit.HOURS.between(zd1, zd2);
System.out.println(x);

output : -2

LocalDateTime ld1 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 3, 0);
ZonedDateTime zd1 = ZonedDateTime.of(ld1, ZoneId.of("US/Eastern"));
LocalDateTime ld2 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
long x = ChronoUnit.HOURS.between(zd1, zd2);
System.out.println(x);

Below are the examples which results works as I expected!

output : -1

LocalDateTime ld1 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 0);
ZonedDateTime zd1 = ZonedDateTime.of(ld1, ZoneId.of("US/Eastern"));
LocalDateTime ld2 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 3, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
long x = ChronoUnit.HOURS.between(zd1, zd2);
System.out.println(x);

output : 1

If someone can help me understand this better, really appreciated.

mark ortiz
  • 659
  • 1
  • 6
  • 13
  • How can you get `1` from the third example when it's *exactly* the same as the second example? – Andreas Jul 30 '17 at 06:24
  • 1
    With a microscopic amount of **research**, i.e. printing the values of `zd1` and `zd2`, you'd have know the answer. – Andreas Jul 30 '17 at 06:26
  • That's Daylight Saving Time: https://www.timeanddate.com/time/change/usa/new-york - clocks shift back 1 hour, so 2 hours has passed between them. You can check this by verifying the corresponding instant of each date: `zd1.toInstant()` will give you the UTC instant, you'll see that the difference is 2 hours –  Jul 31 '17 at 00:15

2 Answers2

2

When you look at the ZonedDateTime objects, you see these:

zd1 = '2015-11-01T02:00-05:00[US/Eastern]'
zd2 = '2015-11-01T01:00-04:00[US/Eastern]'

Daylight Savings Time ended on 1 November 2015. 1am occurred before the clocks went back, and 2am occurred after the clocks went back. Thus two hours difference.

Joe C
  • 15,324
  • 8
  • 38
  • 50
1

US/Eastern, in IANA database (the source where those names come from) is the same as America/New_York timezone (check this list to check the equivalence - search for US/Eastern).

And in America/New_York timezone, Daylight Saving Time ended at November 1st 2015: at 2 AM, clocks shift back 1 hour to 1 AM, and offset changed from -04:00 to -05:00.

If you check the ZonedDateTime's, you'll see the offset change:

System.out.println(zd1);
System.out.println(zd2);

The output is:

2015-11-01T02:00-05:00[US/Eastern]
2015-11-01T01:00-04:00[US/Eastern]

If you see the corresponding Instant, you'll see both dates in UTC:

System.out.println(zd1.toInstant());
System.out.println(zd2.toInstant());

2015-11-01T07:00:00Z
2015-11-01T05:00:00Z

Note that the difference between those dates is 2 hours. You can check this by adding 1 and 2 hours to zd2:

System.out.println(zd2);
System.out.println(zd2.plusHours(1));
System.out.println(zd2.plusHours(2));

The output is:

2015-11-01T01:00-04:00[US/Eastern]
2015-11-01T01:00-05:00[US/Eastern]
2015-11-01T02:00-05:00[US/Eastern]

So, starting at 1 AM in offset -04:00, 1 hour later you are at 2 AM in offset -04:00, but due to DST change, clocks shift back to 1 AM in offset -05:00. Then, 1 hour later, you're at 2 AM in offset 05:00 (zd1). That's why the difference is 2 hours.

This doesn't happen in your second test, because both dates are in the same offset (-05:00), after DST change occurred. So, the difference is just 1 hour. You can again check this by printing the dates and the corresponding Instant:

LocalDateTime ld1 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 0);
ZonedDateTime zd1 = ZonedDateTime.of(ld1, ZoneId.of("US/Eastern"));
LocalDateTime ld2 = LocalDateTime.of(2015, Month.NOVEMBER, 1, 3, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
System.out.println(zd1);
System.out.println(zd2);
System.out.println(zd1.toInstant());
System.out.println(zd2.toInstant());

2015-11-01T02:00-05:00[US/Eastern]
2015-11-01T03:00-05:00[US/Eastern]
2015-11-01T07:00:00Z
2015-11-01T08:00:00Z

Note that the offset is the same, and by the corresponding UTC Instant we can see that the difference is only 1 hour.