日付は過去、時間は未来へ
95日前原文(piccalil.li)
概要
- JavaScriptのDateオブジェクトは多くの混乱と非直感的な挙動を持つ
- Dateの設計ミスにより、日付・時刻処理が一貫性を欠く
- 不変性の原則に反し、Dateはミュータブルなオブジェクト
- Temporal APIの登場で、Dateの問題が解消される見込み
- 今後はTemporalの利用が推奨される流れ
JavaScriptのDateはなぜ嫌われるのか
- Dateコンストラクタは月のみ0始まり、年や日は1始まりという直感に反する仕様
- 文字列パースの挙動が一貫しない
- 例:
"2026-01-02"と"2026/01/02"で異なる日付解釈
- 例:
- 西暦の扱いが曖昧
- 49 → 2049年、99 → 1999年、100 → 0100年など
- 内部的にはUNIXタイムスタンプ(ミリ秒単位)で管理
- タイムゾーンや夏時間のサポートが貧弱
- グレゴリオ暦のみ対応、他の暦には非対応
- JavaScriptのDateはJavaのDateを急いでコピーした産物であり、設計思想の欠如
Dateの本質的な問題点
- JavaScriptのプリミティブ値は不変(immutable)
- 例:
3やtrueは決して他の値にならない
- 例:
- Dateはオブジェクト=ミュータブル(mutable)
- 例:
new Date()で生成したオブジェクトは内部状態を変更可能
- 例:
- 参照渡しのため、意図せず値が変わるリスク
- 例: 関数の引数でDateを渡すと、元の値も変化
- 「1月1日」という絶対的な日付を不変値で表現できない矛盾
- 現実世界の「日付」概念とプログラム上の実装の乖離
Dateのミュータブル性によるバグ例
- 関数でDateを受け取り、日付を加算すると元のDateも書き換わる
- 例:
const today = new Date(); const addDay = theDate => { theDate.setDate(theDate.getDate() + 1); return theDate; }; console.log(`Tomorrow: ${addDay(today).toLocaleDateString()}`); // 1/1/2026 console.log(`Today: ${today.toLocaleDateString()}`); // 1/1/2026(本来は12/31/2025であってほしい)
- 例:
- 参照のコピー=同じオブジェクトを指すため、予期せぬ副作用が発生
Dateの終焉とTemporalの登場
- Dateは今後非推奨(deprecate)予定
- ただし、完全な削除は難しいため「使わないことが推奨」される状態に
- Temporal APIがDateの後継として標準化
- Temporalはコンストラクタではなく、名前空間オブジェクト
- 例:
Temporal.NowやTemporal.PlainDateなどの静的メソッド群
- 例:
- Mathオブジェクトと同様の使い勝手
- より直感的・一貫性のある日付・時刻操作が可能
Temporalの特徴と今後の展望
- 不変性(immutable)を重視した設計
- 多様なカレンダー体系やタイムゾーンに対応
- 副作用のない日付・時刻演算が可能
- サードパーティ製ライブラリ不要な時代へ移行
- 既存コードの移行には注意が必要だが、新規開発ではTemporal一択
まとめ
- JavaScriptのDateは設計上のミスやミュータブル性によるバグの温床
- Temporal APIの登場で、日付・時刻処理の新しい標準が到来
- 今後はTemporalの利用が推奨され、Dateの時代は終わりを迎える