Moment Timezone 技术指南

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

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

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

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

数据源

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

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

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

  1. 确保你已升级到最新版本的库。 我们尝试密切跟踪 tzdb 版本,因此升级 Moment Timezone 可以解决大多数过时数据的情况。
  2. 对于数据计算的问题,在 Moment 时区问题跟踪器 中提一个 issue。
  3. 对于其他问题(例如创建新的区域定义),搜索 tzdb 邮件列表的档案。 新的数据更改或区域定义可能已经在讨论中,但尚未发布。
  4. 如果 tzdb 档案中没有任何内容,请向 tz@iana.org 的邮件列表发送消息。

有限的数据范围

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

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

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

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

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

  • 从每年的四月到九月,区域 Australia/Sydney 的基准(标准)偏移量为 UTC+10:00。 悉尼的夏令时 (DST) 适用于 10 月至次年 3 月,偏移量为 UTC+11:00
  • 由于 DST 在一年结束时处于活动状态,因此当数据范围结束时,DST 偏移量将用于所有未来日期。
  • 因此,从 1 月到 3 月计算 2026 年的日期将得到 UTC+11:00 的偏移量。 这是正确的,但只是偶然。 计算 2026 年 3 月之后的日期仍将得到 UTC+11:00 的偏移量,即使实际值应该是 UTC+10:00。 这是错误开始出现的时候。

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

DST 跳转的时间

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

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

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

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

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