了解 ZonedDateTime::plusDays 的 javadoc

shi*_*iva 6 java datetime java-time

我无法理解为 ZonedDateTimeClass 中的 plusDays() 方法提供的文档的特定部分。文件指出:

\n
\n

返回添加了指定天数的此 ZonedDateTime 的副本。

\n

这在本地时间线上运行,将天数添加到本地日期时间。然后使用区域 ID 获取偏移量,将其转换回 ZonedDateTime。

\n

当转换回 ZonedDateTime 时,如果本地日期时间处于重叠状态,则如果可能,将保留偏移量,否则将使用较早的偏移量。如果存在间隙,则本地日期时间将向前调整\n间隙的长度。

\n

该实例是不可变的并且不受该方法调用的影响。

\n

参数:days \xe2\x80\x93 要添加的天数,可以为负数

\n

返回:基于此日期时间并添加了天数的 ZonedDateTime,\n不为 null

\n

抛出: DateTimeException \xe2\x80\x93 如果结果超出支持的日期\n范围

\n
\n

我的理解是:假设我们有 ZonedDateTime 对象代表September 4, 2022 6 PM in America/New_York TimeZone. 所以这个方法会先将其转换为LocalDateTime,即会丢失时区信息,只保留September 4, 2022 6 PM。它将向其添加一些天数,假设为 7,以便结果为September 11, 2022 6 PM,现在它将通过提供与时区相关的信息将其转换回 ZonedDateTime 对象。

\n

但是,我无法理解文档的后半部分,即

\n
\n

当转换回 ZonedDateTime 时,如果本地日期时间处于重叠状态,则如果可能,将保留偏移量,否则将使用较早的偏移量。如果存在间隙,则本地日期时间将向前调整\n间隙的长度。

\n
\n

他们的意思是什么local date-time is in an overlap?...then the offset will be retained if possible, otherwise the earlier offset will be used.- 这两个不同的偏移量是什么?If in a gap...- 这个差距是什么?

\n

M. *_*tin 4

“间隙”和“重叠”术语在类的类级 Javadoc 中定义ZonedDateTime:

\n
\n

此类处理从 的本地时间线LocalDateTime到 的即时时间线的转换Instant。两条时间线之间的差异是与 的偏移量UTC/Greenwich,用 a 表示ZoneOffset。

\n

两条时间线之间的转换涉及使用从 ZoneId 访问的规则来计算偏移量。获取某一时刻的偏移量很简单,因为每个时刻都有一个有效的偏移量。相比之下,获取本地日期时间的偏移量并不简单。分三种情况:

\n
    \n
  • 正常,有一个有效偏移量。对于一年中的绝大多数时间,适用正常情况,其中本地日期时间有一个有效的偏移量。
  • \n
  • 间隙,有效偏移量为零。此时时钟通常会向前跳动,因为春季夏令时从“冬季”变为“夏季”。在间隙中,存在没有有效偏移的本地日期时间值。
  • \n
  • 重叠,具有两个有效偏移。通常,由于秋季夏令时从“夏季”变为“冬季”,时钟会调慢。在重叠中,本地日期时间值具有两个有效偏移量。
  • \n
\n
\n

例子

\n

让我们使用您的America/New_York时区的具体示例。根据timeanddate.com 的数据,2022 年纽约夏令时变化为:

\n
\n

2022 年 3 月 13 日 - 夏令时开始

\n

当当地标准时间即将到达
\n2022 年 3 月 13 日星期日凌晨2:00:00时,时钟向前调1小时,
\n改为 2022 年 3 月 13 日星期日凌晨3:00:00当地夏令时间。

\n

2022 年 11 月 6 日 - 夏令时结束

\n

当当地夏令时间即将到来时
\n2022 年 11 月 6 日星期日凌晨2:00:00时钟向后调整1 小时为
\n2022 年 11 月 6 日星期日凌晨1:00:00当地标准时间。

\n
\n

因此,纽约时区 3 月 13 日 2:00 至 2:59 之间没有时间。1:59 发生在标准时间。当该分钟结束时,不会出现 2:00 小时,而是当地时间跳至夏令时 3:00。

\n

此外,1:00 到 1:59 之间的时间在 11 月 6 日出现两次:一次在白天,另一次在标准时间。

\n

JavaZonedDateTime示例

\n
ZoneId zone = ZoneId.of("America/New_York");\n\n// 2022-03-13T03:15:30-04:00[America/New_York] (no 2:15)\nSystem.out.println(\n        ZonedDateTime.of(LocalDateTime.parse("2022-03-12T02:15:30"), zone)\n        .plusDays(1));\n
Run Code Online (Sandbox Code Playgroud)\n

由于 3 月 12 日凌晨 2:15 不存在,并且相差在 1 小时之内,因此您引用的以下逻辑适用,为当地时间添加 1 小时:

\n
\n

如果存在间隙,则本地日期时间将按间隙的长度向前调整。

\n
\n

因此,在 3 月 11 日凌晨 1:15 添加 1 天时,使用凌晨 3:15。

\n
ZoneId zone = ZoneId.of("America/New_York");\n\n// 2022-11-06T01:15:30-04:00[America/New_York] (First 1:15)\nSystem.out.println(\n        ZonedDateTime.of(LocalDateTime.parse("2022-11-05T01:15:30"), zone)\n        .plusDays(1));\n\n// 2022-11-06T01:15:30-05:00[America/New_York] (Second 1:15)\nSystem.out.println(\n        ZonedDateTime.of(LocalDateTime.parse("2022-11-05T01:15:30"), zone)\n        .plusDays(1).plusHours(1));\n
Run Code Online (Sandbox Code Playgroud)\n

由于 1:15 AM 处于重叠期间 \xe2\x80\x94 1:15 AM 在 11 月 6 日出现两次 \xe2\x80\x94 您引用的以下逻辑适用,使用与 1:15 相同的 -04:00 区域偏移量11 月 5 日上午:

\n
\n

如果本地日期时间重叠,则如果可能,将保留偏移量

\n
\n

因此,在 11 月 5 日的 1:15 处添加 1 天会使用 11 月 6 日的第一个 1:15。第二次调用使这一点更加明显,它表明向此时间戳添加一个小时将返回 11 月 6 日的第二个 1:15事实上,尽管它们都是当地时间 1:15,但它们在时间轴上是不同的点,这一事实可以从它们不同的区域偏移量中看出:-04:00 和 -05:00。

\n