はじめに
JavaScriptは絶え間ない進化を続けています。これを追いかけていくと、多数の便利な追加や改善の中に、従来のコードが時代遅れになるような、コードの書き方が変わるほどのインパクトある機能を見つけることができます。本連載は、JavaScriptを普段使いする開発者に向けて、JavaScriptの標準規格である「ECMAScript」で標準化された、あるいは標準化予定の機能を紹介しながら、開発者が自身のコードをどうアップデートすべきか解説します。
対象読者
- JavaScriptの最新バージョンの機能を把握したい方
- JavaScriptの経験者で、JavaScriptに改めて入門したい方
- プログラミング言語の最新パラダイムに関心のある方
必要な環境
本記事のサンプルコードは、以下の環境で動作を確認しています。他の環境では動作しないか、動作が不安定になる可能性があります。
-
macOS Sequoia
- Node.js 26.3
Dateに替わる新進の標準API、Temporalとは?
本項のテーマであるTemporalは、Dateに替わる新たな日時表現・操作のためのAPIです(Temporalとは「時の」といった意味です)。
JavaScriptにおける日時表現・操作のためのAPIとしては、Dateが長らく使われてきました。しかし、このDateはその出自から問題を抱えているため、開発者にさまざまな対応策を強いてきた、ある種の「困りもの」でした。具体的にどのような問題があったかについては後述しますが、Dateの問題点を解決し、整理整頓して一新したのがTemporalです。
Temporalは、2017年に最初のProposalが投稿され、標準化が進められてきました。このTemporalは本稿作成時点でStage 4に達し、来たるECMAScript 2027の標準機能として追加される予定です。5月にはついにNode 26にも実装されるなど、本記事の執筆時点ではSafariを除く主要なPCブラウザおよびJSエンジンでは問題なく使える状況となっています。
このため、W3C WebDX Community Groupのコミュニティ活動として策定される指標では、Limited Availability(一部のプラットフォームで動作しない)という扱いになっています。
Temporalのクラスは極めて整理されている
Temporalは名前空間であり、その配下に用途に応じたたくさんのクラスが配置されます。その主なものを以下の表に挙げます。
| クラス | 用途 |
| Instant | タイムゾーンのない、絶対的な「特定の瞬間」 |
| ZonedDateTime | タイムゾーンと暦情報を含んだ、最も包括的な日時データ |
| PlainDateTime | タイムゾーンを持たない、カレンダー上の「日付と時刻」の情報 |
| PlainDate | 時刻情報を持たない「日付のみ」の情報 |
| PlainTime | 日付情報を持たない「時刻のみ」の情報 |
| PlainYearMonth | 「年月」のみの情報 |
| PlainMonthDay | 「月日」のみの情報 |
| Duration | 2つの時点の間の「期間・時間差」 |
| Now | 現在の時刻や日付を各形式で取得するためのユーティリティー空間 |
このように、たくさんのクラスがあるので関係が分かりにくいかも知れません。そこで、以下の図を用意しました。
InstantとZonedDateTimeはExact Time(正確な時間)と呼ばれ、ある瞬間を表す日時データに相当します。InstantがUnixエポック(UTCにおける1970年1月1日午前0時0分0秒)からの経過時間としてのタイムスタンプ情報、ZonedDateTimeが日時とタイムゾーンのペアで、それぞれ日時を表します。ちなみにInstantとは、まさに「一瞬」を意味し、その瞬間瞬間を表す概念です。
これに対してPlainで始まるクラスはWall-Clock Time(壁掛け時計の時間)と呼ばれ、タイムゾーンを持たずに日時を単純に表すデータに相当します。壁掛け時計なので、日時の表現に徹するわけです。タイムゾーンとは関係なく、日付や時間の表現が欲しい場合に使うクラスです。
ところで、Exact TimeとWall-Clock Timeが分けられているのはなぜでしょうか? これは、Dateオブジェクトが抱えていた、「タイムゾーンや夏時間(DST)の扱いでバグを生み出しやすい」という設計ミスを根本から解決するためです。
たとえば、海外の複数の拠点間でオンライン会議を開催するとします。「2026年6月2日の午前6時に開催」という場合、Wall-Clock Timeだけでは拠点のタイムゾーンごとに複数の「2026年6月2日の午前6時」が発生してしまいます。これに夏時間の切り替えが絡めば、さらに日時の候補が増えてしまいます。これに対してExact Timeでは、Unixエポックからの経過時間で日時を表現するので、世界中のどの場所でも「唯一の正しい瞬間」を取り扱うことができます。
具体的には、以下のアプローチがとられます。
- 絶対的な時間と人間の都合による時間を明確に分ける
- 夏時間による「存在しない時間」や「重複する時間」を安全に扱う
- 従来のDateオブジェクトの失敗(Exact TimeとWall-Clock Timeがごっちゃ)を繰り返さない
いずれも、タイムゾーンや夏時間を考慮した計算では必須のアプローチといえます。
インスタンス生成の方法はいくつもある
Temporalにおいて、インスタンス生成の方法はいくつもあり、目的や利便性に応じて使い分けられます。
- 現在日時から生成(Now)
- コンストラクタで生成
- 日時オブジェクトから生成(fromメソッド)
- 日時文字列から生成(fromメソッド)
ここではまず、Nowを使って、現在日時をさまざまな形式で取得してみます。以下のリストは、現在日時をInstant、タイムゾーン付き日時、タイムゾーンなし日時/日付/時間の形式で取得する例です。
// Instantを生成 const instant = Temporal.Now.instant(); console.log(instant.toString()); // 2026-06-08T02:31:45.025769043Z // ZonedDateTimeを生成 const zdt = Temporal.Now.zonedDateTimeISO(); console.log(zdt.toString()); // 2026-06-08T11:31:45.042727051+09:00[Asia/Tokyo] // PlainDateTimeを生成 const dt = Temporal.Now.plainDateTimeISO(); console.log(dt.toString()); // 2026-06-08T11:31:45.04475 // PlainDateを生成 const date = Temporal.Now.plainDateISO(); console.log(date.toString()); // 2026-06-08 // PlainTimeを生成 const time = Temporal.Now.plainTimeISO(); console.log(time.toString()); // 11:31:45.045188965
その他の生成方法については、Temporalの機能を紹介していく過程で、随時取り上げていきます。
なお詳しくは後述しますが、Temporalではさまざまな暦に対応しています。既定はグレゴリオ暦を基本としたISO 8601で、「ISO」の付いたメソッドはこれに基づき動作します。
ところで、Temporalは単独のクラスではなく、多くのクラスを傘下に収める名前空間です。これほどのクラスを用意しなければならない背景とは何だったのでしょうか。以降で、Dateの抱える問題点を露わにしながら、Temporalがそれをどのように解決してきたかを掘り下げていきましょう。
