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 的一個 profile(受限子集)——更受限、更易解析。大多數網際網路協定(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 年擴充)增加了不確定日期、限定值和複雜區間等新構造。