2026年1月13日、Chrome 144の安定版リリースとともに、Temporal APIがおよそ39.8億人のChromeユーザーに配信された。JavaScript誕生から30年間、開発者を悩ませてきたDateオブジェクトの設計負債──ミュータブルな状態管理、0始まりの月インデックス、タイムゾーン非対応、ミリ秒止まりの精度──がついに清算される。本記事では、Temporal APIの設計思想と主要機能、既存ライブラリからの移行パターン、そしてSafari未対応下でのフォールバック戦略を解説する。

Dateオブジェクトの「7つの設計負債」

JavaScriptのDateオブジェクトは1995年、Java 1.0のjava.util.Dateをわずか10日で移植したものである。Java側では2002年にJoda-Timeが登場し、2014年にはjava.timeパッケージで完全に再設計されたが、JavaScriptは20年以上にわたり初期設計を引きずってきた。

最も深刻な問題はミュータビリティである。Dateオブジェクトは可変であり、参照を共有するコードが意図せず日付を書き換えてしまうバグが頻発する。

// Dateの危険なミュータビリティ
const startDate = new Date('2026-02-12');
const eventDate = startDate;  // 参照を共有
eventDate.setMonth(eventDate.getMonth() + 1); // 変更
console.log(startDate); // startDateも変わってしまう

さらに、月が0始まり(1月=0、12月=11)であるにもかかわらず日は1始まりという不整合、setMonth()によるサイレントコラプション(12月31日にsetMonth(10)を実行すると11月30日ではなく12月1日になる)、IANAタイムゾーンの非対応、Duration型の不在、パース挙動の不一致、ミリ秒精度の限界──これらが「7つの設計負債」としてJavaScript開発者を苦しめてきた。

Temporal APIの設計思想と主要クラス

Temporal APIはTC39プロポーザルとして策定が進められ、2026年2月現在Stage 3に到達している。チャンピオンのRob Palmer氏は、2026年3月にニューヨークで開催されるTC39プレナリーでStage 4への昇格を提案する意向を表明している。Stage 4到達は正式なECMAScript標準への組み込みを意味し、2026年7月の正式批准が見込まれる。

Temporalの最大の特徴はイミュータブル設計である。すべての日時オブジェクトは不変であり、操作のたびに新しいオブジェクトを返す。

// Temporalのイミュータブル設計
const startDate = Temporal.PlainDate.from('2026-02-12');
const laterDate = startDate.add({ months: 1 }); // 新しいオブジェクトを返す
console.log(startDate.toString());  // 2026-02-12(変更されない)
console.log(laterDate.toString());  // 2026-03-12

Temporal APIは用途に応じた7つの主要クラスを提供する。

  • Temporal.PlainDate ── カレンダー日付のみ(2026-02-12)
  • Temporal.PlainTime ── 壁時計時刻のみ(14:30:45)
  • Temporal.PlainDateTime ── 日付+時刻(タイムゾーンなし)
  • Temporal.ZonedDateTime ── 日付+時刻+IANAタイムゾーン
  • Temporal.Instant ── UTCの特定瞬間(ナノ秒精度)
  • Temporal.Duration ── 時間の長さ
  • Temporal.PlainYearMonth / Temporal.PlainMonthDay ── 部分日付

Temporal.ZonedDateTimeはIANAタイムゾーンデータベースにネイティブ対応しており、外部ライブラリなしでAsia/TokyoAmerica/Los_Angeles間の変換が可能である。Temporal.Instantナノ秒精度(Dateの1,000倍)を持ち、金融取引や科学計算といった高精度タイミングの要件にも対応する。月のインデックスは直感的な1始まり(1月=1)に修正され、ISO 8601準拠の一貫したパース挙動が保証される。

Chrome 144搭載の意味 ── ブラウザ対応状況

Temporal APIを最初に本番搭載したブラウザはFirefoxである。2025年5月27日リリースのFirefox 139でフラグなしの完全サポートが実現した。Chrome 144が2026年1月13日にこれに続いたことで、デスクトップブラウザ市場のおよそ77%がネイティブ対応を果たしたことになる。

Chrome 144のV8エンジンは、Rustベースのtemporal_rsライブラリを採用している。これはBoa JavaScriptエンジン向けに開発されたものだが、V8やKieselでも共有されており、エンジン間で一貫した挙動を担保する設計となっている。

現在のブラウザ対応状況は以下の通りである。

  • Firefox 139+(2025年5月〜) ── 完全対応
  • Chrome 144+(2026年1月〜) ── 完全対応
  • Edge ── Chromiumベースのため追従見込み
  • Safari ── Technology PreviewではuseTemporalフラグで利用可能だが、本番リリースは未定

Safari未対応は現時点で最大のギャップであり、iOSのデフォルトブラウザとして全モバイルユーザーの約18%に影響する。この問題に対するフォールバック戦略は後述する。

moment.js / date-fnsからの移行パターン

JavaScriptの日時処理ライブラリ市場はこの10年で大きく変動した。2026年2月時点のnpm週間ダウンロード数は、date-fnsが3,920万、Day.jsが3,220万、moment.jsが2,560万、Luxonが1,870万である。moment.jsは公式にメンテナンスモードを宣言しており、新規プロジェクトでの採用を非推奨としている。

moment.jsからの移行

moment.jsはミュータブル設計であり、Temporalへの移行は設計思想の転換を伴う。

// moment.js → Temporal

// 現在日付の取得
// Before: moment().format('YYYY-MM-DD')
// After:
Temporal.Now.plainDateISO().toString()

// タイムゾーン変換(moment-timezoneが不要に)
// Before: moment.tz("2026-01-13 15:30", "America/Los_Angeles")
// After:
Temporal.ZonedDateTime.from({
  timeZone: 'America/Los_Angeles',
  year: 2026, month: 1, day: 13,
  hour: 15, minute: 30
})

// 日付の加算
// Before: moment().add(7, 'days')
// After:
Temporal.Now.plainDateISO().add({ days: 7 })

date-fnsからの移行

date-fnsは関数型アプローチを採用しており、Temporalのオブジェクト指向メソッドチェーンとは設計が異なるが、概念的な対応関係は明確である。

// date-fns → Temporal

// 日付の加算
// Before: import { addDays } from 'date-fns';
//         addDays(new Date(), 1)
// After:
Temporal.Now.plainDateISO().add({ days: 1 })

// 日付のパース
// Before: import { parse } from 'date-fns';
//         parse('2026-02-12', 'yyyy-MM-dd', new Date())
// After:
Temporal.PlainDate.from('2026-02-12')

// 期間の計算
// Before: import { differenceInDays } from 'date-fns';
//         differenceInDays(end, start)
// After:
start.until(end, { largestUnit: 'day' }).days

移行は段階的に進めることを推奨する。まずは日付の生成・パース処理から置き換え、次にタイムゾーン操作やDuration計算といった複雑なロジックに着手する。テストで既存の計算結果との一致を検証しながら、モジュール単位で進めるのが現実的なアプローチである。

Safari未対応時のフォールバック戦略

2026年2月現在、Safari本番環境ではTemporal APIが利用できない。プロダクション環境でのクロスブラウザ対応には、ポリフィルの活用が不可欠である。

@js-temporal/polyfillの導入

npm install @js-temporal/polyfill
// ポリフィル経由でTemporalを使用
import { Temporal } from '@js-temporal/polyfill';

// Chrome 144+・Firefox 139+ではネイティブ実装が使われ、
// Safari等の未対応ブラウザではポリフィルが機能する
const today = Temporal.Now.plainDateISO();
console.log(today.toString());

@js-temporal/polyfillはグローバルスコープを汚染せず、明示的なインポートが必要な設計となっている。ネイティブ実装が存在するブラウザでも安全に併用できる。

フィーチャーディテクションによる切り替え

// ネイティブ対応を検出して分岐
if (typeof globalThis.Temporal !== 'undefined') {
  // ネイティブ実装を使用(Chrome 144+, Firefox 139+)
  const date = Temporal.Now.plainDateISO();
} else {
  // ポリフィルを動的インポート
  const { Temporal } = await import('@js-temporal/polyfill');
  const date = Temporal.Now.plainDateISO();
}

軽量な代替としてtemporal-polyfill(FullCalendarチーム開発)も選択肢に入る。バンドルサイズを重視するプロジェクトでは検討に値する。

Safariの本番対応時期は2026年2月時点で未発表だが、Technology Previewで実装が進んでいることから、近い将来のリリースが見込まれる。ポリフィルを介した段階的導入により、Safariの正式対応を待たずにTemporalの恩恵を受けることが可能である。

FAQ

Temporal APIはいつから使えるのか?

Firefox 139(2025年5月)とChrome 144(2026年1月)で本番利用が可能である。Safariは未対応だが、@js-temporal/polyfillを使えば全ブラウザで利用できる。

既存のDateオブジェクトは廃止されるのか?

廃止はされない。後方互換性の観点からDateは残り続けるが、新規開発ではTemporalの使用が推奨される。TC39もTemporalを「Dateの後継」と位置づけている。

moment.jsやdate-fnsはもう不要になるのか?

基本的な日時操作はTemporalで完結するが、高度なフォーマットやロケール対応など、ライブラリ固有の機能はしばらく有用である。moment.jsは既にメンテナンスモードであり、段階的なTemporalへの移行が推奨される。

Node.jsでもTemporal APIは使えるのか?

Node.jsはV8エンジンを使用しているため、V8のTemporal対応が反映される。@js-temporal/polyfillを使えばNode.jsのバージョンに依存せず利用可能である。

Temporal APIの学習コストはどの程度か?

7つの主要クラスの使い分けが最初のハードルだが、PlainDateZonedDateTimeDurationの3つを押さえれば日常的なユースケースの大半をカバーできる。MDNの公式ドキュメントが充実している。

参考文献