この前のJSConfで、一休の@takashi_ondaさんが、JavaScriptの新しい標準日付ライブラリ Temporal が baselineになることを見越した実装をしていると発表していた
この JavaScriptの新しい標準日付ライブラリ Temporal について調べてみた
今の時点では Stage3
なぜ、Dateではダメなのか?
Dateがダメな理由は以下のブログに書かれている
- Timezonesをまたいだ日付変更ができない
- 日付や時刻の加算、減算処理が使いにくい
- 日付だけ、時刻だけでの処理が困難
- グレゴリオ暦以外のカレンダーの時間を扱うことができない
元々「Java のようにする」という考えのもと、当時の未熟なJavaの日付ライブラリ java.Util.Dateの実装からコピーしてきたとのことだが、Javaも同じような理由からJava8から非推奨になっている
ということで、Temporal では以下のことができるようになる
- 日付と時刻の計算に使いやすいAPIを提供する
- DST(夏時間) 対応の演算を含む、すべてのタイムゾーンに対するファーストクラスのサポート
- 固定された日付と時刻を表すオブジェクトのみを扱う
- 厳密に指定された文字列形式の解析
- グレゴリオ暦以外のカレンダーのサポート
オブジェクトの関係

図を見ると Wall-Clock Time(ウォールクロックタイム) と Exact Time(正確な時間) に 分かれている
それぞれの違いは以下
| 特徴 | Exact Time | Wall-Clock Time |
|---|---|---|
| 基準 | Unixエポック(1970年1月1日 UTC) | 地域のカレンダーと時計 |
| タイムゾーン | タイムゾーンや夏時間(DST)の影響を受けない | タイムゾーンや夏時間(DST)の影響を受ける |
| 連続性 | 連続的 | 非連続的(DSTでスキップや繰り返し) |
| 用途 | システムや分析向けの時間計測 | ユーザー向けの日時表示 |
| 例 | "1700000000秒"(Unixタイム) | "2024-12-09 10:00 AM JST" |
このことから、図にあるそれぞれのクラスは以下に分類できる
Temporal.Instantは正確なUNIIX時間を表すクラスTemporal.PlainXX系のクラスはカレンダーの日付と実時間を表すクラスTemporal.ZonedDateTimeは上の2つに相当するもの、および上の2 つをリンクするタイムゾーンをカプセル化したクラス
Exact Time(正確な時間)からWall-Clock Time(ウォールクロックタイム)への変換例
instant = Temporal.Instant.from('2019-09-03T08:34:05Z'); formatOptions = { era: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }; zdt = instant.toZonedDateTimeISO('Asia/Tokyo'); // => 2019-09-03T17:34:05+09:00[Asia/Tokyo] zdt.toLocaleString('en-us', { ...formatOptions, calendar: zdt.calendar }); // => 'Sep 3, 2019 AD, 5:34:05 PM' zdt.year; // => 2019 zdt.toLocaleString('ja-jp', formatOptions); // => '西暦2019年9月3日 17:34:05' zdt = zdt.withCalendar('japanese'); // => 2019-09-03T17:34:05+09:00[Asia/Tokyo][u-ca=japanese] zdt.toLocaleString('en-us', { ...formatOptions, calendar: zdt.calendar }); // => 'Sep 3, 1 Reiwa, 5:34:05 PM' zdt.eraYear; // => 1
Wall-Clock Time(ウォールクロックタイム)からExact Time(正確な時間)への変換例
// Convert various local time types to an exact time type by providing a time zone date = Temporal.PlainDate.from('2019-12-17'); // If time is omitted, local time defaults to start of day zdt = date.toZonedDateTime('Asia/Tokyo'); // => 2019-12-17T00:00:00+09:00[Asia/Tokyo] zdt = date.toZonedDateTime({ timeZone: 'Asia/Tokyo', plainTime: '10:00' }); // => 2019-12-17T10:00:00+09:00[Asia/Tokyo] time = Temporal.PlainTime.from('14:35'); zdt = time.toZonedDateTime({ timeZone: 'Asia/Tokyo', plainDate: Temporal.PlainDate.from('2020-08-27') }); // => 2020-08-27T14:35:00+09:00[Asia/Tokyo] dateTime = Temporal.PlainDateTime.from('2019-12-17T07:48'); zdt = dateTime.toZonedDateTime('Asia/Tokyo'); // => 2019-12-17T07:48:00+09:00[Asia/Tokyo] // Get the exact time in seconds, milliseconds or nanoseconds since the UNIX epoch. inst = zdt.toInstant(); epochNano = inst.epochNanoseconds; // => 1576536480000000000n epochMilli = inst.epochMilliseconds; // => 1576536480000 epochSecs = Math.floor(inst.epochMilliseconds / 1000); // => 1576536480
このようにして使うことができる
参考
https://zenn.dev/general_link/articles/824f3485817827
https://yosuke-furukawa.hatenablog.com/entry/2020/07/28/102821