ISO 8601

ISO 8601 日期时间格式说明

ISO 8601 是把日期和时间表示为字符串的国际标准。其规范形式 2024-03-15T14:30:00Z 无歧义、可排序,并在所有现代语言和数据库中得到支持。本指南逐个组件地讲解格式、大多数 API 实际使用的 RFC 3339 子集、较新的 RFC 9557 时区扩展,以及持续时间、区间和周日期的变体。

什么是 ISO 8601?

ISO 8601 是国际标准化组织对日期和时间的表示。当前版本(ISO 8601-1:2019 / -2:2019)定义了一种紧凑、有序、与语言无关的文本格式。它的全部目的是消除歧义:像 03/04/2024 这样的日期在美国是 3 月 4 日,在欧洲大部分地区是 4 月 3 日,但 2024-03-04 在任何地方都是同一含义。该标准也是 RFC 3339 的基础,而 RFC 3339 正是大多数互联网协议实际使用的子集。

  • 始终为年-月-日顺序:2024-03-15(不是 03/15/2024 或 15/03/2024)
  • 时间部分以字面 T 或空格分隔:2024-03-15T14:30:00
  • 时区显式:UTC 用 Z,偏移用 ±HH:MM
  • 可作为文本排序——字典序与时间顺序一致

规范的日期时间格式

最常见的形式形如 2024-03-15T14:30:00.123Z。每个组件都是固定宽度并以零填充,这正是它让格式可排序且无歧义的原因。

组件示例含义
YYYY2024四位年份
MM03两位月份(01–12)
DD15两位日(01–31)
TT日期/时间分隔符(RFC 3339 也允许空格)
hh:mm:ss14:30:0024 小时制,以零填充
.fff.123可选的小数秒(ISO 8601 中任意精度)
Z 或 ±hh:mmZ时区指示符(Z = UTC = +00:00)

时区指示符

ISO 8601 的时区被编码为相对 UTC 的偏移,绝不用 EST 或 CET 这类时区缩写(它们含糊)。该字符串携带了足够的信息来重建精确的 UTC 时刻,包括某些地区使用的半小时和 45 分钟偏移。

指示符相对 UTC 的偏移示例时区
Z+00:00UTC("Zulu" 时间)
+09:00快 9 小时日本标准时间
-05:00慢 5 小时美国东部标准时间
+05:30快 5.5 小时印度标准时间
+05:45快 5.75 小时尼泊尔标准时间
(无)未指定本地时间——含糊;在 API 中避免

ISO 8601 vs RFC 3339

RFC 3339 是 ISO 8601 的一个配置文件——更受限、更易解析。大多数互联网协议(JSON API、HTTP、IETF 规范)专门以 RFC 3339 为目标,所以当一个 API 说 "ISO 8601" 时,几乎总是指 RFC 3339 子集。差异虽小,却决定了一个给定字符串能否被解析。

特性ISO 8601RFC 3339
日期/时间分隔符T,或在基本格式中省略T 或一个空格(必需)
时区偏移可选必需
小数秒任意精度允许,由解析器设上限
基本格式(无连字符)允许 20240315T143000Z不允许
周/序数日期允许不允许
典型用途归档、电子表格、交换JSON API、HTTP、IETF 规范

RFC 9557:时区与 Temporal 扩展

像 +01:00 这样的纯偏移告诉你时刻,却不告诉你时区——而且偏移会随夏令时变化,所以同一个时区冬天是 +01:00,夏天是 +02:00。RFC 9557(2024)用 Internet Extended Date/Time Format(IXDTF)弥合了这一缺口:它在方括号中附加 IANA 时区名,如 2024-03-15T14:30:00+01:00[Europe/Paris]。这是 JavaScript Temporal API 读写的字符串格式,因此随着 Temporal 的普及你会越来越多地看到它。它保持向后兼容——去掉方括号后缀,你就得到一个普通的 RFC 3339 时间戳。

  • 仅偏移:2024-03-15T14:30:00+01:00 —— 知道时刻,但不知时区
  • IXDTF(RFC 9557):2024-03-15T14:30:00+01:00[Europe/Paris] —— 时刻加时区
  • 向后兼容:方括号标签可被 RFC 3339 解析器忽略

变体:持续时间、区间、周日期

ISO 8601 涵盖的不止是时刻。若干变体在排程、归档和报表系统中经常出现:

  • 持续时间:P3Y6M4DT12H30M5S = 3 年 6 个月 4 天 12 小时 30 分 5 秒
  • 区间:2024-01-01/2024-02-01,或 2024-01-01/P1M(开始 + 持续时间)
  • 序数日期:2024-075 = 2024 年的第 75 天(3 月 15 日)
  • 周日期:2024-W11-5 = 2024 年 ISO 第 11 周的星期五
  • 重复区间:R3/2024-01-01/P1D = 从 1 月 1 日起三个一天的区间

代码中的 ISO 8601

每种主流语言都能开箱即用地生成和解析 RFC 3339 子集。最安全的习惯是以带 Z 的 UTC 输出,并解析回一个时刻,把任何时区转换留给展示层。

  • JavaScript 输出:new Date().toISOString() // '2024-03-15T14:30:00.123Z'
  • JavaScript 解析:new Date('2024-03-15T14:30:00Z') // RFC 3339 子集
  • Python 输出:datetime.now(timezone.utc).isoformat()
  • Python 解析:datetime.fromisoformat('2024-03-15T14:30:00+00:00') // 3.11+ 支持完整 ISO
  • 大多数数据库(Postgres、SQLite)直接接受并返回 ISO 8601 timestamptz

常见的 ISO 8601 错误

即使有严格的标准,解析与输出代码也会犯同样的几个错误:

  • 省略时区:没有 Z 或偏移的 2024-03-15T14:30:00 是含糊的
  • 用 "+0000" 代替 "+00:00"——有些解析器接受,RFC 3339 不接受
  • 使用非字母的 T(Unicode 形近字复制粘贴时容易出错)
  • 把 12 小时制 AM/PM 混入 ISO 8601——它始终是 24 小时制
  • 截断小数秒却不四舍五入——选定一个精度并坚持
  • 把 ISO 8601 当作依赖区域设置——它不是;格式与语言无关、固定不变

相关参考

FAQ

"2024-03-15 14:30:00Z" 是有效的 ISO 8601 吗?
是 —— 日期与时间之间的空格在 ISO 8601(以及 RFC 3339)中是允许的。为了无歧义的机器解析,更推荐 T 形式。
末尾的 Z 是什么意思?
Z 表示 UTC(偏移 +00:00)。它是 "Zulu time" 的缩写,即字母 Z 的北约/航空音标。
如何在 JavaScript 中解析 ISO 8601?
new Date("2024-03-15T14:30:00Z") 对标准的 RFC 3339 子集有效。要更广泛地支持 ISO 8601,请使用 date-fns 这样的库或 Temporal API。
ISO 8601 和 RFC 3339 一样吗?
不 —— RFC 3339 是一个严格的子集。每个 RFC 3339 时间戳都是有效的 ISO 8601,但并非每个 ISO 8601 时间戳都是有效的 RFC 3339。
什么是 RFC 9557?
RFC 9557(2024)用 Internet Extended Date/Time Format(IXDTF)扩展了 RFC 3339。它在方括号中附加 IANA 时区名——例如 2024-03-15T14:30:00+01:00[Europe/Paris]——并是 JavaScript Temporal API 所用字符串格式的基础。
T 分隔符是必需的吗?
在严格的 ISO 8601 中,基本格式可以省略 T;RFC 3339 要求一个 T 或一个空格。为了机器解析,请始终包含 T。
ISO 8601 和 ISO 8601-2 有什么区别?
ISO 8601-1 涵盖基本的日期与时间表示。ISO 8601-2(2019 年扩展)增加了不确定日期、限定值和复杂区间等新构造。