從 Node.js v24 開始,Date.toString() 在台灣時區下的名稱從 Taipei Standard Time 變成了 Taiwan Standard Time。
我一開始會注意到這件事,是因為某次 NVIDIA 的活動寫了「Taiwan Standard Time」,當下有點疑惑,後來處理時間相關程式碼時又看到,才認真查下去。
查完之後發現,這件事其實跟政治無關,也不是 Node.js 自己改的。
不是 Node.js 自己改的
在 v24 或之後的版本執行:
console.log(new Date().toString());
會看到類似:
Wed Aug 12 2026 01:30:00 GMT+0800 (Taiwan Standard Time)
舊版則是 (Taipei Standard Time)。
很多人第一直覺會以為是 Node.js 自己改的,不過 Node.js 裡並沒有人特地送 PR 說「我們來把台北改成台灣」。
實際上是有人更新了上游的 Unicode 在地化資料庫(Common Locale Data Repository,縮寫:CLDR),而這項變更一路同步到 Node.js v24,變成現在看到的名稱。
路徑大致是:
Unicode CLDR → ICU → Node.js → Date.toString()
是誰改的?
往上游找,可以找到 GitHub 帳號 Robert Bastian(@robertbastian)。
2024 年 10 月 30 日,他在 Unicode 在地化資料庫開了一個 Draft PR,標題很直接:Timezone display name cleanup,內容是在整理一批不一致的時區顯示名稱,其中包含:
Taipei Time → Taiwan Time
後來這批修改成為正式的 PR #4184,於 2025 年 1 月合併,實際改動的 XML 是這樣:
<metazone type="Taipei">
<long>
- <generic>Taipei Time</generic>
- <standard>Taipei Standard Time</standard>
- <daylight>Taipei Daylight Time</daylight>
+ <generic>Taiwan Time</generic>
+ <standard>Taiwan Standard Time</standard>
+ <daylight>Taiwan Daylight Time</daylight>
</long>
</metazone>
有個細節值得注意:第一行 <metazone type="Taipei"> 本身沒有被改掉,Unicode 在地化資料庫內部的 metazone ID 到現在還是叫 Taipei,IANA 的正式時區 ID Asia/Taipei 也完全沒動。真正被換掉的,只有顯示給人看的英文名稱。
就像是門牌號碼和戶籍地址都沒動,只是把門口那塊招牌從「Taipei Standard Time」換成了「Taiwan Standard Time」。
為什麼要改?
這才是我原本最好奇的部分,是有人抗議嗎?台灣政府要求?Google 施壓?還是 Unicode 在做政治表態?
其實都不是,答案意外地普通:命名規則不一致。
Unicode 在地化資料庫對時區顯示名稱本來就有一套邏輯:當一個國家或地區只有單一時區時,通常可以直接使用國家或地區名稱;如果境內存在多個時區,才需要以城市名稱區分,另外也有 primary zone 等例外規則。
例如:
Asia/Shanghai→ China Standard Time(不是 Shanghai Standard Time)Europe/Rome→ Italy Time
像美國這種橫跨多個時區的國家,才比較常需要 Los Angeles、New York 這類城市名稱。
而台灣當時的資料剛好有點矛盾,按照 location format 的邏輯,Asia/Taipei 所屬國家/地區是 TW,因此可以推導出 Taiwan Time;但另一邊,Taipei 這個 metazone 又另外寫死了一組 Taipei Time、Taipei Standard Time、Taipei Daylight Time。
也就是說,同一個時區根據不同的名稱產生方式,可能得到 Taiwan 和 Taipei 兩套不同的結果。
Robert Bastian 做的修改,基本上就是把這些名稱統一,而且這次並不是只有 Taiwan 被挑出來,同一批修改還包含:
- Pyongyang Time → North Korea Time
- Petropavlovsk-Kamchatski Time → Kamchatka Time
- Brunei Darussalam Time → Brunei Time
- East Timor Time → Timor-Leste Time
- Ponape Time → Pohnpei Time
PR 的理由也寫得很直接:讓 non-location name 和 location format 的結果保持一致。
從目前能找到的公開紀錄來看,沒有證據顯示背後存在什麼「Taiwan 正名計畫」,整件事更像是工程師在整理時區資料時,發現幾組名稱彼此不一致,於是一起修掉,只不過其中一筆,剛好把 Taipei Standard Time 變成了 Taiwan Standard Time。
不是 2024 年才出現的概念
原本以為故事到這裡就結束了,結果再往前查,可以一路追到 2015 年。
當時有人在 IANA tz mailing list 討論台灣的時區縮寫。台灣長期使用 CST,但 CST 是時區界的撞名王——可能是 China Standard Time、Central Standard Time、Cuba Standard Time,甚至歷史上的 Chungyuan Standard Time(中原標準時間)。
有人因此提出:台灣是不是該改用 TST(Taiwan Standard Time)?
當時 IANA tzdb 的維護者並不太想動,因為 tzdb 在乎的是時區規則、UTC offset 和歷史資料,而不是「介面上應該顯示什麼名字」,討論中甚至有人直接指出:這比較像本地化的問題,應該留給負責語系與顯示名稱的系統處理。
九年後,Unicode 在地化資料庫把名稱改了。
不只 Node.js 有改
既然源頭是 Unicode 在地化資料庫,影響範圍當然遠不止 Node.js。
只要 runtime、作業系統或函式庫開始使用 CLDR 47(或內含 CLDR 47 的 ICU 77),就會開始顯示新名稱。
ICU:International Components for Unicode,Unicode 國際元件
- Firefox 138(2025 年 4 月)比 Node.js 24 還早幾天升級到 ICU 77
- Node.js 24(2025 年 5 月)
- OpenJDK 25 正式更新到 CLDR 47
- Chrome、Android 後續也跟進
- PHP 的 intl extension 若底層 ICU 夠新,也會變
- .NET 在 Linux/Unix 上若使用系統 ICU,會得到
Taiwan Standard Time;但在 Windows 上仍可能是Taipei Standard Time,因為 Windows 有自己的時區資料
Python 和 Go 完全沒動
這反而讓整件事更有趣,如果真的是「全球時區正式改名」,所有程式語言應該一起變才對。
Python 的 zoneinfo 和 Go 的 time package 主要依賴 IANA tzdb,因此通常還是回傳 CST。
兩個系統負責的事情本來就不一樣:
- IANA tzdb:時區規則、offset、歷史資料(Asia/Taipei、UTC+08:00、CST)
- Unicode 在地化資料庫:介面上該怎麼顯示(Taiwan Standard Time、台北標準時間)
於是現在可以同時存在三個世界:
- IANA tzdb → Asia/Taipei / CST
- Unicode 在地化資料庫 → Taiwan Standard Time
- Windows → Taipei Standard Time
三個都在講同一個地方,沒有任何一方把另外兩方「正式改名」。
回到那一行 JavaScript
整件事最後還是回到最開始那一行:
new Date().toString();
你看到的只是:
- Taipei Standard Time
+ Taiwan Standard Time
背後卻是:
2015 年 IANA mailing list 的討論
→ 2024 年 Unicode 在地化資料庫的整理
→ 2025 年 1 月正式合併
→ CLDR 47 → ICU 77
→ Firefox、Node.js、Chrome、Android、PHP、.NET……
我一開始只是想知道,為什麼 Taiwan Standard Time 這個詞突然出現,沒想到最後一路查到了 Unicode、ICU、IANA、OpenJDK,以及十年前的 mailing list。
這大概也是寫程式有趣的地方之一——很多看似理所當然的事,背後其實沒那麼理所當然。
參考資料
- Node.js v24.0.0 Release Notes
Node.js v24.0.0 發布紀錄,其中包含將 ICU 更新至 77.1 的變更 - Node.js #57455 — deps: update ICU to 77.1
Node.js 將內建 ICU 升級至 77.1 的 Pull Request - ICU 77 Release
ICU 77 的版本說明;此版本採用 CLDR 47 的語系資料 - CLDR 47 Release Notes
Unicode CLDR 47 的版本發布紀錄 - CLDR 46 — Eastern Asia Time Zones
CLDR 46 的東亞時區名稱資料,其中英文標準時間名稱仍為「Taipei Standard Time」 - CLDR 47 — Eastern Asia Time Zones
CLDR 47 的東亞時區名稱資料,其中英文標準時間名稱已改為「Taiwan Standard Time」 - CLDR 48 — Eastern Asia Time Zones
CLDR 48 延續使用「Taiwan Standard Time」 - Unicode Locale Data Markup Language — Time Zone Names
Unicode UTS #35 對時區識別碼、metazone 與在地化時區顯示名稱的規範 - CLDR — Time Zones and City Names
CLDR 對時區名稱、城市名稱與 metazone 在地化方式的說明 - ICU Data
ICU 對資料來源與 CLDR 整合方式的說明 - NVIDIA GeForce 活動規則
NVIDIA 官方頁面中實際使用「Taiwan Standard Time」作為時間標示的案例