Moment Timezone 技术指南

指南区域旨在帮助开发者学习如何更好地与日期和时间问题域以及 Moment Timezone 库进行交互。这些指南特别限于有关时区的概念以及 Moment Timezone 如何处理它们。

¥The guides area is designed to help developers learn to better interact with the date and time problem domain, and the Moment Timezone library. These guides are specifically limited to concepts around time zones and how they're handled by Moment Timezone.

有关更一般的日期和时间建议,请参阅 核心 Moment.js 指南

¥For more general date and time advice, see the core Moment.js guides.

时区与偏移量

通常,人们对时区和 UTC 偏移量之间的差异感到困惑。

¥Frequently, people are confused about the difference between time zones and UTC offsets.

核心 Moment.js 文档有 关于这个主题的指南,值得先阅读。从逻辑上讲,它属于 Moment Timezone 的指南,但它早于本指南部分很多年,移动它会破坏互联网上的很多链接。

¥The core Moment.js documentation has a guide on this topic that is worth reading first. Logically it belongs in the guides for Moment Timezone, but it predates this guide section by many years, and moving it would break a lot of links on the internet.

有关区域与偏移的深入描述,请参阅 Stack Overflow 标签。

¥For an in depth description of zones vs offsets, see the Stack Overflow tag.

Moment Timezone 通过使用预编译的时区数据增强核心 Moment.js 功能。

¥Moment Timezone enhances the core Moment.js functionality by using pre-compiled time zone data.

本节介绍数据的来源、限制以及现实世界时区规则的一些怪癖。API 文档 中描述了数据格式的技术细节。

¥This section describes where the data comes from, its limitations, and some quirks of real-world time zone rules. The technical details of the data format are described in the API documentation.

数据源

Moment Timezone 中的所有时区数据均来自 IANA 时区数据库 ("tzdb")。Moment Timezone 直接使用来自 tzdb 的默认数据,仅使用已发布的版本。库所做的唯一更改是将数据转换为 自定义 JSON 格式,并可选择限制使用多少年的数据。

¥All time zone data in Moment Timezone comes from the IANA Time Zone Database ("tzdb"). Moment Timezone consumes the default data directly from the tzdb, using only the published releases. The only changes the library makes are to convert the data to a custom JSON format, and optionally restrict how many years of data to use.

任何对已编译数据文件进行更改而不是从 tzdb 版本派生的拉取请求都将被拒绝。

¥Any pull requests that make changes to the compiled data files without being derived from a tzdb release will be rejected.

如果你认为 Moment Timezone 使用的数据不正确,那么理想的操作顺序是:

¥If you think that the data used by Moment Timezone is incorrect, the ideal order of actions to follow is:

  1. 确保你已升级到最新版本的库。我们尝试密切跟踪 tzdb 版本,因此升级 Moment Timezone 可以解决大多数过时数据的情况。

    ¥Make sure you've upgraded to the latest version of the library. We try to closely track the tzdb releases, so upgrading Moment Timezone resolves most cases of out-of-date data.

  2. 对于数据计算的问题,在 Moment 时区问题跟踪器 中提一个 issue。

    ¥For data calculation problems, raise an issue in the Moment Timezone issue tracker.

  3. 对于其他问题(例如创建新的区域定义),搜索 tzdb 邮件列表的档案。新的数据更改或区域定义可能已经在讨论中,但尚未发布。

    ¥For other problems (such as creating a new zone definition), search the archives of the tzdb mailing list. It's probable that new data changes or zone definitions are already being discussed, but haven't made it to a published release yet.

  4. 如果 tzdb 档案中没有任何内容,请向邮件列表 tz@iana.org 发送消息。

    ¥If there is nothing in the tzdb archives, send a message to the mailing list at tz@iana.org.

有限的数据范围

默认情况下,Moment Timezone 包括来自 IANA 时区数据库 ("tzdb") 的所有数据。这涵盖了某些区域早在 1800 年代的过去数据,以及直到 2499 年的未来数据。这通常比大多数应用所需的数据更多,因此也有一些预构建的数据包可用,但年份范围更有限。这些列在 项目主页"何处使用" 文档 上(或者你可以使用 工具函数 创建自定义日期范围)。

¥By default, Moment Timezone includes all the data from the IANA Time Zone Database ("tzdb"). This covers past data as far back as the 1800s for some zones, and future data up to the year 2499. This is usually more data than required by most applications, so there are also some pre-built data bundles available with more limited year ranges. These are listed on the project homepage and the "Where to use it" documentation (or you can use utility functions to create custom date ranges).

这些有限的打包包经常出现的一个问题是:超出数据范围的日期会怎样?例如,如果加载的数据仅涵盖 2012 年到 2022 年,计算的日期为 2023 年或 2010 年,那么计算出的该日期的 UTC 偏移量是多少?

¥A question that often pops up with these limited bundles is: What happens for dates outside the range of the data? For example, if the loaded data only covers 2012 to 2022, and a date is calculated for 2023, or 2010, what is the calculated UTC offset for that date?

由于 数据格式 的结构,假设数据范围边界处的时区规则无限扩展到过去和未来。这会产生以下行为:

¥Due to the structure of the data format, the time zone rules at the boundaries of the data range are assumed to extended infinitely into the past and future. This produces the following behaviour:

  • 对于数据范围开始之前的日期,使用在该时区的数据中找到的第一个规则。

    ¥For dates before the start of the data range, the first rule found in the data for that time zone is used.

  • 对于数据范围结束后的日期,使用在该时区的数据中找到的最后一条规则。

    ¥For dates after the end of the data range, the last rule found in the data for that time zone is used.

例如,假设一个项目正在使用仅涵盖 2015 年到 2025 年的数据文件,并且想要计算 2026 年某个时间在澳大利亚悉尼的时间。

¥As an example, let's say a project is using a data file that covers only 2015 to 2025, and wants to calculate the time in Sydney, Australia some time in 2026.

  • 从每年的四月到九月,区域 Australia/Sydney 的基准(标准)偏移量为 UTC+10:00。悉尼的夏令时 (DST) 适用于 10 月至次年 3 月,偏移量为 UTC+11:00

    ¥The zone Australia/Sydney has a base (standard) offset of UTC+10:00 from April to September each year. Daylight Saving Time (DST) in Sydney applies from October to March, putting the offset at UTC+11:00.

  • 由于 DST 在一年结束时处于活动状态,因此当数据范围结束时,DST 偏移量将用于所有未来日期。

    ¥Since DST is active when a year ends, and therefore when the data range ends, the DST offset will be used for all future dates.

  • 因此,从 1 月到 3 月计算 2026 年的日期将得到 UTC+11:00 的偏移量。这是正确的,但只是偶然。计算 2026 年 3 月之后的日期仍将得到 UTC+11:00 的偏移量,即使实际值应该是 UTC+10:00。这是错误开始出现的时候。

    ¥Therefore, calculating a date in 2026 from January to March will get an offset of UTC+11:00. This is correct, but only by accident. Calculating a date after March in 2026 will still get an offset of UTC+11:00, even though the real value should be UTC+10:00. This is when bugs will start to appear.

解决这些计算问题的最佳方法是确保你使用的数据范围涵盖项目所需的所有日期。

¥The best fix for these calculation problems is to make sure you're using a data range that covers all the dates your project needs.

DST 跳转的时间

使用夏令时 (DST) 的时区因实现时间跳跃的时间而异。你不应该假设你熟悉的本地时区规则适用于其他时区。

¥Time zones that use daylight saving time (DST) vary about when they implement the time jumps. You shouldn't assume that the rules you're familiar with from a local time zone translate to other zones.

经常引起开发者注意的一个区别是,某些区域会在午夜更改时钟。一个很好的例子来自 2021 年的约旦 (Asia/Amman):

¥One difference that often catches out developers is that some zones change clocks at midnight. A good example comes from Jordan (Asia/Amman) in 2021:

  • 2021-03-25 23:59:59 后一秒是 2021-03-26 01:00:00(DST 开始)。

    ¥One second after 2021-03-25 23:59:59 was 2021-03-26 01:00:00 (DST started).

  • 2021-10-29 00:59:59 后一秒是 2021-10-29 00:00:00(DST 停止)。

    ¥One second after 2021-10-29 00:59:59 was 2021-10-29 00:00:00 (DST stopped).

这就造成了 3 月 26 日午夜没有发生,而 10 月 29 日午夜发生了两次的情况。

¥This creates the situation where midnight at the start of March 26 didn't happen, while midnight on October 29 happened twice.

"解析歧义" 文档 中所述,Moment Timezone 解释了这些奇怪之处。但是,当应用对时间跳跃做出其他假设时,尤其是关于一天的开始时,它们仍然可能存在错误。因此请注意,一天并不总是从午夜开始。

¥Moment Timezone accounts for these oddities as described in the "Parsing Ambiguities" documentation. But applications can still have bugs when they make other assumptions about time jumps, especially regarding the start of a day. So be aware that a day doesn't always start at midnight.