ZonedDateTime -> ChronoUnit.HOURS.between(zd1(Hour 2), zd2(Hour 1)) return -2

ZonedDateTime -> ChronoUnit.HOURS.between(zd1(Hour 2), zd2(Hour 1)) return -2

我想明白为什么代码的结果是-2,一开始我以为应该是-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, 1, 0);
ZonedDateTime zd2 = ZonedDateTime.of(ld2, ZoneId.of("US/Eastern"));
long x = ChronoUnit.HOURS.between(zd1, zd2);
System.out.println(x);

输出:-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);

以下是结果符合我预期的示例!

输出:-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);

输出:1

如果有人能帮助我更好地理解这一点,非常感谢。

当您查看 ZonedDateTime 个对象时,您会看到这些:

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

夏令时于 2015 年 11 月 1 日结束。凌晨 1 点发生在时钟倒转之前,凌晨 2 点发生在时钟倒转之后。因此相差两个小时。

US/Eastern,在 IANA database (the source where those names come from) is the same as America/New_York timezone (check this list 中检查等价性 - 搜索 US/Eastern).

并且在 America/New_York 时区,Daylight Saving Time ended at November 1st 2015:凌晨 2 点,时钟向后移动 1 小时至凌晨 1 点,偏移量从 -04:00 更改为 -05:00

如果您检查 ZonedDateTime,您会看到偏移量发生变化:

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

输出为:

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

如果您看到相应的 Instant,您将看到两个 UTC 日期:

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

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

请注意,这些日期之间相差 2 小时。您可以通过将 1 小时和 2 小时添加到 zd2:

来检查这一点
System.out.println(zd2);
System.out.println(zd2.plusHours(1));
System.out.println(zd2.plusHours(2));

输出为:

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

因此,从偏移量 -04:00 的凌晨 1 点开始,1 小时后您在偏移量 -04:00 的凌晨 2 点,但是由于 DST 更改,时钟在偏移量 [=180] 回到凌晨 1 点=19=]。然后,1 小时后,您位于偏移量 05:00 (zd1) 的凌晨 2 点。这就是为什么时差是2小时。

这不会在您的第二次测试中发生,因为在发生 DST 更改后,两个日期都处于相同的偏移量 (-05:00)。因此,时差仅为 1 小时。您可以通过打印日期和相应的 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

注意offset是一样的,通过对应的UTC Instant可以看出仅仅相差1小时