1.4K Views
March 18, 26
スライド概要
2026年3月16日の勉強会「#temporal_study」で発表したスライドです。たぶんスライドだけ読んでもチンプンカンプンだと思うのでそのうちちゃんと補足記事を書きます。
にとって とは何か web Temporal 2026-03-16 #temporal_study ふぁぼん
🎉🎉🎉 Temporal & Intl era and monthCode Proposal -> stage 4 🎉🎉🎉
自己紹介 技術と i18n(国際化)が好き ECMAScript、特に ECMA-402 Unicode、CLDR、ICU 暦、タイムゾーン テキストレンダリング、組版 Temporal の polyfill の 1 つ ( temporal-polyfill-lite ) の開発者 アルバイト@ピクシブ株式会社 pixiv(web サービス)の開発に関わっています 大学院生(近現代ロシア史) web
宣伝: temporal-polyfill-lite 自分の要件を満たす polyfill がなかったので作った 仕事での本番投入を見据えて開発 最新の仕様に準拠 @js-temporal/polyfill と temporal-polyfill は今のところ 1 年前の仕様のまま トランスパイルと polyfill で古いブラウザにも対応可 内部で BigInt を使っていない グレゴリオ暦しか使わない 99.99%の開発者向けの基本バージョンと、その他の暦をサポー トしたフルバージョンの 2 種類を提供 基本バージョンは既存の polyfill の中でバンドルサイズが最小
Temporal に至るまでの JavaScript の日時処理を振り返る
Date 頭痛の種 ミュータブル 月が 0-indexed 月・日が溢れると勝手に繰り上がる UTC とローカル時間の 2 つしか扱えない ISO 8601(RFC 3339)形式の文字列のパースでタイムゾーンの扱いが一貫していない (以下、文句が無限に続く)
// 2026 年 3 月 31 日 const d = new Date(2026, 2, 31); d.setMonth(1); // 2 月に設定 d; // 2026 年 3 月 3 日 new Date("2026-03-16"); // UTC で 2026 年 3 月 16 日 0 時 new Date("2026-03-16T00:00:00"); // ローカル時間で 2026 年 3 月 16 日 0 時 // 2026 年 3 月 8 日 2 時 0 分 new Date(2026, 2, 8, 2).getHours(); // 2 (大抵の場合) // 3 (実行環境のタイムゾーンがアメリカやカナダなどの場合)
Moment.js 偉大な先駆者 ミュータブルな API バンドルサイズが大きい 全タイムゾーンのデータを独自で保持 当時はそれしか方法がなかった
Intl.DateTimeFormat / toLocaleString 人間が読む日時文字列を出力する API 2010 年代前半に仕様策定・実装 具体的なフォーマットは JS エンジン間、バージョン間、OS 間で異なることがある 任意のタイムゾーンで日時を出力できる グレゴリオ暦以外の暦でも日時を出力できる 大抵の JavaScript エンジンで遅い 特にコンストラクタ おそらく ECMAScript で最も悪用・濫用されてきた API のひとつ 機械が読む文字列(例: ISO 8601 形式)を作るために使うべきではない
真っ当な使い方
各言語で日時を出力
const date = new Date(2026, 2, 16, 19);
// 日本語(日本)、英語(アメリカ)、英語(イギリス)、中国語(大陸)、ロシア語(ロシア)
for (const locale of ["ja-JP", "en-US", "en-GB", "zh-CN", "ru-RU"]) {
date.toLocaleString(locale, { dateStyle: "long" });
}
// ja-JP: 2026 年 3 月 16 日
// en-US: March 16, 2026
// en-GB: 16 March 2026
// zh-CN: 2026 年 3 月 16 日
// ru-RU: 16 марта 2026 г.
元号
new Date(2026, 2, 16).toLocaleDateString("ja-JP", {
calendar: "japanese",
});
// R8/3/16
悪用・濫用の例 ❌ // const isoString = date.toLocaleDateString("sv-SE"); ライブラリか Temporal.PlainDate.prototype.toString を使うべき。
後発の日時ライブラリ ここ 10 年くらいの設計トレンド イミュータブル Intl.DateTimeFormat をハックしてタイムゾーンのデータを取得する設計 Internet Explorer のサポートを切れる時代の到来 ここ 10 年のライブラリはだいたいこっち Luxon Day.js (timezone プラグイン) date-fns-tz @date-fns/tz Tempo
ブラウザのタイムゾーンのデータにアクセスするハック(概略):
const parts = new Intl.DateTimeFormat("en-u-hc-h23", {
year: "numeric",
// 中略
second: "numeric"
timeZone,
}).formatToParts(date);
const year = parseInt(parts.find(p => p.type === "year").type);
// 中略
const offsetMilliseconds =
Date.UTC(year, month - 1, day, hour, minute, second) date.getTime();
どうしてこんなことに?
根本的な原因 の API が貧弱すぎる Date の API が混乱を招く ミュータブル UTC とローカル時間の両方を表現するオブジェクトってどういう意味? ブラウザが持つタイムゾーンのデータにハック的手法でしかアクセスできない → 正しい設計の標準ライブラリを導入して問題を解決しよう! Date
Temporal のメンテナの 1 人が発案 日時に関する基本的な機能が揃った API 異なるセマンティクスを異なる型で表現 日時と期間の足し算・引き算 日時と日時の間の期間の計算 時間や期間の丸め処理 ISO 8601 形式の文字列へのシリアライズ・デシリアライズ 任意のタイムゾーンでの日時情報の取得・計算 任意の暦の計算 Moment.js
Temporal の変更として史上最大級 仕様策定に関わった人数、提案から stage 4 までかかった期間(約 9 年)も最大級 1.2 万行を超える仕様書 現在の ECMA-262 全体は 5.3 万行、ECMA-402 全体は 1 万行 6500 ファイル以上の膨大な test262 テストスイート ECMA-262 が 4500 ファイル、ECMA-402 が 2000 ファイル 参考: Date は 600 ファイル、 Intl.DateTimeFormat は 250 ファイル、 String は 1200 ファイル、 Array は 3000 ファイル ECMAScript
なぜこんなに時間がかかったのか 私は やブラウザベンダの関係者ではなく、あくまで のミーティング記録や各所の TC39 issue 2 TC39 を 年間ウォッチしてきた外部の人間の感覚に基づきます。 タイムゾーンや暦の情報を保持する文字列フォーマットを IETF で標準化していた RFC 9557: Internet Extended Date/Time Format (IXDTF) みたいなやつ シンプルに仕様が大きすぎて test262 のテストを網羅的に整備するのが死ぬほど大変 test262 のカバレッジが低いと実装のハードルも上がる シンプルに仕様が大きすぎて実装が大変 stage 3 になってから実装者からのフィードバックで仕様がかなり削られた曰く付きの プロポーザル iso8601 以外の暦(非 ISO 暦)に関する仕様策定・実装がかなり大変 2026-03-16T19:00:00+09:00[Asia/Tokyo][u-ca=japanese]
Temporal の意義 日時の多様なセマンティクスを表現するイミュータブルなデータ型 タイムゾーンのデータや暦の計算にアクセスするための適切な API タイムゾーンや暦のあらゆるコーナーケースを考慮した包括的な日時処理 API 暦やタイムゾーン関連の挙動の標準化、互換性の向上 特に暦についてはほとんど全て実装依存だった API で提供されるデータである以上、異なる結果が返ってくると互換性の問題が生じる
タイムゾーン関連 どのタイムゾーン DB を使うか 正規形のタイムゾーン ID はどれか どのタイムゾーン ID を同一とみなすか IANA ではなく CLDR に準拠 ECMA-402 に反映済み: Use of the IANA Time Zone Database(プルリク: #877)
暦関連 どの暦をサポートするか それぞれの暦の紀元・時代 (era) の仕様 ルールベースでない暦の扱い 中国と韓国の旧暦、イランのヒジュラ太陽暦、ヒジュラ暦のうちサウジアラビアの Umm al-Qura 暦 どの機関が発行している暦を正統とみなすか 何年から何年の範囲で準拠するか その期間の外はどうするか 日本の元号はどこまで遡るべきか
まとめ: Temporal の意義 エコシステムで日時を表現する基本データ型の導入 エッジケースを考慮した言語レベルの日時計算・処理 タイムゾーンや暦に関する相互互換性の向上 web