ソフトウェア

JavaScriptの日付の概念を変革するTemporalオブジェクト誕生までの9年間の道のり


JavaScriptの標準であるECMAScriptに元々組み込まれているDateオブジェクトを置き換える新しい日時API「Temporal」が導入されます。TemporalはJavaScriptの日時操作における多くの課題を解決することを目指しています。

Temporal: The 9-Year Journey to Fix Time in JavaScript | Bloomberg JS Blog
https://bloomberg.github.io/js-blog/post/temporal/

JavaScriptのDateオブジェクトは1995年にBrendan EichがJavaのDate実装を参考にしてわずか10日間で実装されたという経緯があり、当時はJavaScriptに複雑な処理をさせることを想定していなかったこともあって実装に問題があるとは考えられていませんでした。


しかしながら2010年代にはJavaScriptがあらゆるタイムゾーンで複雑な処理を支える状況が到来しており、以下を代表例とする様々な設計上の制約や問題点が開発者を苦しめていました。

ミュータビリティ:オブジェクトが変更可能であることに起因する意図しない値変更のリスク
パースの曖昧さ:日付文字列のパース時に意図しない解釈が行われることがある
タイムゾーン・カレンダーとの不整合:タイムゾーンやグレゴリオ暦以外のカレンダーの扱いに弱く、国際化対応で予期せぬ結果を招くことがある


ミュータビリティとはDateオブジェクトのメソッドがオブジェクト自体を変更するというもので、同じオブジェクトを複数の場所で参照している場合に意図しない副作用が発生することがあります。特にJavaScriptは関数の引数が参照渡しであるため、関数内でDateオブジェクトを変更するとそのオブジェクトを参照している他のコードも影響を受けてしまいます。つまり、関数の中身を知らずに使用すると引数のDateオブジェクトが変更される可能性があるため、コードの安全性が損なわれることになります。

const date = new Date("2026-02-25T00:00:00Z");
console.log(date.toISOString());
// "2026-02-25T00:00:00.000Z"が出力される

function addOneDay(d) {
  d.setDate(d.getDate() + 1);   // 引数のDateオブジェクトを変更してしまう
  return d;
}

addOneDay(date);  // 外部から見る限りは日付を加算して返すだけの関数だが、実際には引数のDateオブジェクトも変更している

console.log(date.toISOString());
// "2026-02-26T00:00:00.000Z"が出力される

パースの曖昧さは、DateオブジェクトのコンストラクタやDate.parse()メソッドが日付文字列を解釈する際に、ブラウザや実装によって異なる解釈が行われることがあるという問題です。例えば、"2026-02-25 15:15:00"という文字列はISO 8601形式に似てはいるものの若干の違いがあり、パース結果は仕様で定義されていません。したがって同じコードが異なる環境で異なる結果を生む可能性があり予期しないバグの原因となります。

new Date("2026-06-25 15:15:00").toISOString();
// このコンストラクタはブラウザによって異なる解釈がされる可能性がある
// ・ローカルタイムゾーンの日付として解釈
// ・UTCの日付として解釈
// ・エラー(RangeError: invalid date)となる場合も

タイムゾーン・カレンダーとの不整合についてよく知られている例は以下のコードがあります。

const billingDate = new Date("Sat Jan 31 2026");
billingDate.setMonth(billingDate.getMonth() + 1);
// 期待値:2月28日
// 実際の値:3月2日

Dateに起因する問題を解決しようとすると従来はMoment.jsのようなサードパーティー製ライブラリに依存することとなり、バンドルサイズの増加やロケール・タイムゾーンデータの管理といった新たな課題が生じていました。


Dateオブジェクトにまつわる課題の根本的な解決を目指して2017年のTC39総会にて提案されたTemporalは、JavaScript標準にモダンな日時APIを導入することを目的としています。

Dateオブジェクトの代替
複数のDateTime型の提供
イミュータブル(不変)な設計
タイムゾーンとカレンダーのファーストクラスサポート

提案は一連のプロセスを経て精査されていきます。

ステージ0:アイデアの提示
ステージ1:問題領域が受け入れられた
ステージ2:設計案は決定したが作業は継続中
ステージ2.7:提案は原則的に承認されテストとフィードバック待ち
ステージ3:実施とフィードバック
ステージ4:標準化

MicrosoftのMaggie Johnson-PintがTemporalの提案をTC39に持ち込みステージ1に進んだ後、同じくMicrosoftのMatt Johnson-PintBrian Terlsonを加えた3名が主導していきました。同時期にBloombergのAndrew PaprockiとIgaliaのDaniel EhrenbergV8でタイムソーンを設定可能にする方法について話し合っているうちTemporalの提案との類似性に気付くこととなり、BloombergとIgaliaがTemporalの実装に参加するきっかけとなりました。BloombergのPhilipp Dunkelは自社にTemporalへの投資を説得し、IgaliaのPhilip ChimentoUjjwal SharmaはフルタイムでTemporalの開発に携わることになりました。

さらに、Richard Gibsonはステージ3のレビュアーとして貢献し仕様書をクリーンアップ・寄稿しました。Googleの国際化チームからはShane Carrが参加しカレンダーなどの国際化トピックを担当しました。Justin Grantは2020年にボランティアとして参加し、過去の業務経験を元に夏時間(DST)に関する諸問題を解決するTemporal.ZonedDateTime APIのリリースに大きく貢献しました。


非常に大規模な提案でありJavaScriptにこれまでで最も多くの変更をもたらすものだったことからTemporalの実装は困難を極めました。仕様が膨大で個人で実装するのは非常に困難であり、さらに仕様の変更が頻繁であったため実装が追いつくのも大変でした。Temporalの実装がいかに大変であったかを物語るものとして、ECMAScriptの公式テストスイート(Test262)に追加されたテストの数が挙げられます。記事作成時点でTemporalには約4500のテスト項目があり、Dateを含む他の組み込み機能と比べても非常に多い数となっています。

この記事のタイトルとURLをコピーする

・関連記事
AIで簡単にウェブページ上でさまざまなタスクを実行できるようになる「PageAgent」を使ってみた - GIGAZINE

日付ピッカーをどう実装すべきかのガイド「Pikaday」 - GIGAZINE

無料でJavaScriptによるウェブアプリ構築のデザイン・レンダリング・パフォーマンスパターンがわかる「Patterns.dev」 - GIGAZINE

自作の小さなRPGでパフォーマンス上の問題を引き起こした原因とは? - GIGAZINE

JavaScriptの日付と時刻の管理を大きく簡素化する「Temporal」の実装作業が進行中 - GIGAZINE

ウェブページに「数値の入力欄」を実装する際はテンキーの存在を考慮する必要あり - GIGAZINE

in ソフトウェア, Posted by log1c_sh

You can read the machine translated English article The 9-year journey to the birth of the T….