Node.js 26 で Temporal API がデフォルト有効化 — Date 地獄からの解放と実務移行ガイド

はじめに

JavaScript の Date は誕生から30年近く、開発者から「設計の失敗作」と揶揄されてきた。タイムゾーンを正しく扱えず、ミュータブルで、月が0始まりという罠まである。2026年5月5日にリリースされた Node.js 26 で、その後継となる Temporal API がついにフラグなしで標準搭載 された。3月のTC39でStage 4に到達し、ECMAScript 2026の正式仕様に組み込まれることが決まった直後の動きだ。本稿では、Node.js 26 の変更点、Temporal API の構造、そして実務での乗り換え方を整理する。

Node.js 26 で何が変わったのか

Node.js 26 は、Temporal API のデフォルト有効化を目玉に据えたメジャーリリースだ。これまで Temporal を試すには --harmony-temporal のような実験フラグが必要だったが、Node.js 26 以降は グローバルオブジェクトとして Temporal がそのまま使える。

ほかの主な変更点も合わせて押さえておきたい。

  • V8 エンジンを 14.6 へ更新: Stage 4 になった Temporal を含む ECMAScript 2026 機能群を取り込む
  • Undici 8.0 へ更新: HTTP クライアントの性能改善と HTTP/3 サポート強化
  • 複数のレガシーAPI削除: モダンな代替が定着したため、punycode などの非推奨化が進行
  • LTS 移行は 2026年10月: 現時点では Current 扱いで、本番投入は LTS 化後を狙うのが安全

ブラウザ側の動きも揃ってきている。Firefox は2025年5月の139から、Chrome/Edge は2026年4月の144から Temporal を標準サポート済み。Safari は Technology Preview で部分対応の段階で、ここだけは出遅れている。Node.js も加わったことで、ようやく主要ランタイムの足並みが揃った ことになる。

Temporal API の技術的な仕組み

Temporal は単なる Date のリプレースではなく、用途別に型を分けた設計 に踏み込んでいる。Date がすべてを「ミリ秒のタイムスタンプ」一本で表現していたのに対し、Temporal は以下の主要オブジェクトを使い分ける。

// 絶対時刻(UTC上の一点)
Temporal.Now.instant();
// => 2026-05-14T03:21:09.123456789Z

// タイムゾーン付き日時 — 実務で最もよく使う型
const meeting = Temporal.ZonedDateTime.from(
  '2026-05-14T10:00:00[Asia/Tokyo]'
);

// タイムゾーンを含まない日付・時刻・日時
const birthday = Temporal.PlainDate.from({ year: 2026, month: 5, day: 14 });
const opening  = Temporal.PlainTime.from({ hour: 9, minute: 0 });

// 期間(カレンダー計算可能)
const sprint = Temporal.Duration.from({ weeks: 2 });

設計上の重要なポイントは以下の通り。

  • イミュータブル: すべての Temporal オブジェクトは生成後に変更されない。add / with などのメソッドは新しいオブジェクトを返す。Date のように setMonth() で破壊的に書き換えるバグから解放される
  • ナノ秒精度: ミリ秒止まりだった Date と異なり、Temporal.Instant は10⁻⁹秒まで保持する。高精度タイムスタンプを扱う観測系・分散システムで効く
  • タイムゾーンが第一級: ZonedDateTime はサマータイム遷移や歴史的なオフセット変更まで処理する。new Date('2026-03-08T02:30:00') のような曖昧な扱いがなくなる
  • カレンダー対応: ISO 8601 だけでなく和暦・ヘブライ暦などの非グレゴリオ暦も計算できる

タイムゾーン変換の例を見れば、Date で書いた場合との差は歴然だ。

const tokyo = Temporal.ZonedDateTime.from('2026-05-14T10:00:00[Asia/Tokyo]');
const ny    = tokyo.withTimeZone('America/New_York');
// => 2026-05-13T21:00:00-04:00[America/New_York]

const diff = tokyo.until(Temporal.Now.zonedDateTimeISO());
console.log(diff.total({ unit: 'hour' }));

エンジニアへの影響と移行戦略

Temporal が標準化されたことで、これまで date-fns / dayjs / Luxon といったライブラリで補ってきた領域の多くが言語標準で賄えるようになる。とはいえ、明日からすべて書き換えるべきかというとそうではない。Node.js 26 はまだ Current(10月にLTS)で、Safari の本対応も未確定だ。現実的な移行戦略は以下の3段階 だ。

  1. 新規コードから Temporal を採用: 既存コードの一斉書き換えはコストとリスクが大きい。新しいモジュール・API レイヤから Temporal 直書きに切り替える
  2. 日時操作を境界に閉じ込める: アプリ内では ZonedDateTime を使い、Date との変換は toLegacyDate() / Temporal.Instant.fromEpochMilliseconds() をユーティリティ関数に集約する。境界が一箇所にまとまれば、後から差し替えやすい
  3. ブラウザ側はポリフィルで前倒し対応: Safari 対応が必要なフロントエンドは @js-temporal/polyfill を併用する。Stage 4 到達後の現在、API は安定しておりプロダクション利用に問題ない

具体的なユースケースとしては、スケジューラー・予約システム・金融データ・ログ解析 など、タイムゾーンや日付演算が複雑になるドメインで恩恵が大きい。たとえば「東京で2026年5月14日10:00開始の会議をニューヨーク時間で表示しつつ、サマータイム終了をまたいで2週間後に再設定する」といった処理が、ライブラリなしで安全に書けるようになる。

逆に、単なるエポック秒の記録や API レスポンスへのタイムスタンプ付与だけなら、Date.now() のままで困らない。変換と演算が絡む場面で Temporal を入れる という線引きが、当面は妥当だ。

まとめ

Node.js 26 の Temporal API デフォルト有効化は、JavaScript の日時処理が9年がかりでようやく実用段階に入ったことを示す節目だ。要点は以下の通り。

  • Node.js 26(2026-05-05)で Temporal がフラグなしで利用可能、LTSは2026年10月から
  • ECMAScript 2026 で Stage 4 確定、Chrome/Edge/Firefox/Node.js が標準サポート(Safari は未対応)
  • 用途別の型分離・イミュータブル・ナノ秒精度・タイムゾーン第一級が Date との決定的な違い
  • 移行は「新規コードから」「変換を境界に集約」「ブラウザはポリフィル併用」の3段階が現実的

長年「JS の日時は欠陥」と語り継がれてきた状況が、ようやく終わろうとしている。Safari の本対応と Node.js 26 の LTS 化が揃う2026年秋以降、Temporal は新規プロジェクトの標準選択肢になるだろう。

今日のその他のニュース

Python 3.14/3.15 で Incremental GC をリバート

Python の議論 では、3.14で導入された incremental GC を、性能・安定性の課題から3.14/3.15で撤回する方針が示された。世代別GCの挙動変更に依存していたライブラリは挙動確認が必要。

DuckDB が「Quack」プロトコルを発表

DuckDB 公式ブログで、HTTPベースのクライアント・サーバプロトコル「Quack」が公開された。「embedded only」だったDuckDBで複数writerによるリモート書き込みが可能になり、サーバ用途への展開が始まる。

Wasp 開発者「新言語を作ったのは失敗だった」

Wasp ブログでは、5年・500万ドルを投じてWeb開発向けDSLを開発したチームが「言語を発明した判断は誤りだった」と振り返った。エコシステム作りのコストとツーリング負担が主な理由。

ソース