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。每个组件都是固定宽度并以零填充,这正是它让格式可排序且无歧义的原因。
| 组件 | 示例 | 含义 |
|---|---|---|
| YYYY | 2024 | 四位年份 |
| MM | 03 | 两位月份(01–12) |
| DD | 15 | 两位日(01–31) |
| T | T | 日期/时间分隔符(RFC 3339 也允许空格) |
| hh:mm:ss | 14:30:00 | 24 小时制,以零填充 |
| .fff | .123 | 可选的小数秒(ISO 8601 中任意精度) |
| Z 或 ±hh:mm | Z | 时区指示符(Z = UTC = +00:00) |
时区指示符
ISO 8601 的时区被编码为相对 UTC 的偏移,绝不用 EST 或 CET 这类时区缩写(它们含糊)。该字符串携带了足够的信息来重建精确的 UTC 时刻,包括某些地区使用的半小时和 45 分钟偏移。
| 指示符 | 相对 UTC 的偏移 | 示例时区 |
|---|---|---|
| Z | +00:00 | UTC("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 8601 | RFC 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 年扩展)增加了不确定日期、限定值和复杂区间等新构造。