JavaScript の日付処理が変わる — Temporal API が Chrome 137 で使えるようになった
new Date() の後継として10年かけて設計された Temporal API が Chrome 137 に入った。タイムゾーン処理・日付計算・フォーマットが根本的に改善される。
JavaScript で日付を扱うとき、一度はこういうコードを書いたことがあるはずだ。
const date = new Date();
date.getMonth(); // 6 と返ってきたら 7月
そう、getMonth() は 0-indexed。1月が 0、12月が 11。初めてこれを踏んだときの「は?」という感覚は、たぶん誰もが覚えている。
これだけじゃない。new Date() には長年の問題が山積している。タイムゾーン処理が難しい、日付の加算に便利なメソッドがない、immutable じゃないので破壊的変更のバグを踏みやすい……。だから date-fns や dayjs みたいなライブラリが生まれた。
Temporal API は、その new Date() をまるごと置き換えるために 10 年かけて設計された新しい API だ。Chrome 137 でフラグなしで使えるようになった。
一番変わった設計思想: 型で日付を区別する
Temporal の本質は「日付の種類を型で区別する」設計にある。
new Date() はすべてを UTC ミリ秒で管理していた。「日付だけ」「時刻だけ」を表現するのに苦労した。Temporal はそれを最初から分けている。
| 型 | 何を表すか | 使いどころ |
|---|---|---|
Temporal.PlainDate | 日付のみ(時刻なし) | 誕生日、予約日 |
Temporal.PlainTime | 時刻のみ(日付なし) | 営業時間、アラーム |
Temporal.PlainDateTime | 日付+時刻(タイムゾーンなし) | ローカルの予定 |
Temporal.ZonedDateTime | タイムゾーン付き日時 | 会議の招待、ログ |
Temporal.Instant | UTC の絶対時刻 | DB の timestamp |
「誕生日」を new Date() で表すのは本来おかしかった。誕生日にタイムゾーンは関係ない。Temporal.PlainDate を使えば意味が正確になる。
日付計算が素直になる
new Date() で「3ヶ月後」を計算するとこうなる。
const d = new Date();
d.setMonth(d.getMonth() + 3); // 破壊的変更。元の d が変わる
setMonth を呼んだ瞬間に元の値が書き換わる。「変更前の日付も使いたい」となったとき、事前にコピーを作っておかなかったことを後悔する。
Temporal ならこう書ける。
const today = Temporal.Now.plainDateISO();
const threeMonthsLater = today.add({ months: 3 });
// today は変わらない。threeMonthsLater が新しいオブジェクト
immutable なので破壊的変更のバグが起きない。.add() .subtract() .with() が使いやすい。「2つの日付の差」もシンプルだ。
const start = Temporal.PlainDate.from('2026-01-01');
const end = Temporal.PlainDate.from('2026-07-06');
const diff = start.until(end, { largestUnit: 'month' });
console.log(`${diff.months}ヶ月 ${diff.days}日`); // 6ヶ月 5日
new Date() でやるとミリ秒計算になるやつだ。
タイムゾーン処理がようやくまともになる
Temporal の最大の強みはタイムゾーン処理にある。
const tokyoNow = Temporal.Now.zonedDateTimeISO('Asia/Tokyo');
const nyNow = tokyoNow.withTimeZone('America/New_York');
console.log(tokyoNow.toString());
// 2026-07-06T10:00:00+09:00[Asia/Tokyo]
console.log(nyNow.toString());
// 2026-07-05T21:00:00-04:00[America/New_York]
タイムゾーン名が型に含まれるので、「UTC で管理していたつもりがローカル時刻だった」問題が起きにくい。文字列を見れば、その値がどのタイムゾーンのものかが一目でわかる。
今すぐ使えるか?
Chrome 137 でフラグなし対応。Firefox は 139 で対応。Safari はまだ技術プレビューの段階。
ポリフィルがあるので、本番に入れること自体は可能だ。
npm install @js-temporal/polyfill
import { Temporal } from '@js-temporal/polyfill';
新規プロジェクトでライブラリを入れずに日付処理をするなら、Temporal が第一候補になりつつある。既存プロジェクトで date-fns や dayjs が入っているなら、急いで移行する必要はない。
ただ「なぜ Date ライブラリが必要なのか」という問いへの答えが、ブラウザの標準機能として届くようになった。それはそれで、大事な変化だと思う。