Chrome v144からJavaScriptのTemporalが使用可能に!

Temporalとは

TemporalとはJavaScriptのDateオブジェクトの長年の問題点を解決するために設計された、次世代の日時APIです。

JavaScriptの言語仕様として組み込まれるため、Temporalを使用すればdate-fnsやDay.jsなどのライブラリの依存関係が不要になります。

現在のChromeやMicrosoft Edgeの最新バージョンであるv144がTemporalに対応するようになったため、利用できるブラウザが増えました。

Temporal - JavaScript | MDN

new Date()はデメリットが多い

JavaScriptで日時の生成にnew Date()を使用しているケースが多いと思いますが、Dateには以下の7つの問題点があるため、使用することはオススメしません。

1. 不変性ではない

Dateは不変性ではないため、意図せず参照渡しのような形になって値を変更してしまいます。

Temporalだと日付を変更しても、元の日付は変更されません。

JavaScript
// ❌ Date - 元のオブジェクトが変更されてしまう
const date1 = new Date('2024-01-15')
const date2 = date1
date2.setDate(20)
console.log('Date1:', date1.getDate()) // 20 (意図せず変更されている!)
console.log('Date2:', date2.getDate()) // 20

// ✅ Temporal - 常に新しいオブジェクトが返される
const temporal1 = Temporal.PlainDate.from('2024-01-15')
const temporal2 = temporal1.add({ days: 5 })
console.log('Temporal1:', temporal1.toString()) // 2024-01-15 (変更されない)
console.log('Temporal2:', temporal2.toString()) // 2024-01-20

2. タイムゾーンの扱いが曖昧

Dateはローカルタイムゾーンに依存、明示的な制御が困難です。

Temporalでは国別のタイムゾーンを明示的に扱えて、サマータイム(DST)も自動的に正しく処理されるので、間違った日時を設定してしまうことがありません。

JavaScript
// ❌ Date - タイムゾーンの扱いが曖昧
const date = new Date('2024-03-10T02:30:00')
console.log('Date:', date.toString())
// ローカルタイムゾーンに依存、明示的な制御が困難

// ✅ Temporal - タイムゾーンを明示的に扱える
const zonedDateTime = Temporal.ZonedDateTime.from({
  timeZone: 'America/New_York',
  year: 2024,
  month: 3,
  day: 10,
  hour: 2,
  minute: 30
})
console.log('Temporal:', zonedDateTime.toString())
// サマータイム(DST)も自動的に正しく処理される

3. 文字列へ変換しにくい

Dateだと直接yyyy-mm-ddの文字列に変換できませんが、Temporalなら直接変換できます。

JavaScript
// ❌ Date - 文字列に変換しにくい
const date = new Date('2024-03-21')
const yyyy = date.getFullYear()
const mm = String(date.getMonth() + 1).padStart(2, '0')
const dd = String(date.getDate()).padStart(2, '0')
const text = `${yyyy}-${mm}-${dd}`
console.log(text) // 2024-03-21

// ✅ Temporal - 文字列に変換しやすい
const date = Temporal.PlainDate.from('2024-03-21')
console.log(date.toString()) // 2024-03-21

4. ハイフン(-)とスラッシュ(/)のどちらも使える

Dateはハイフン(-)とスラッシュ(/)のどちらも日付形式が使えますが、結果が変わってしまいます。

この違いによってバグが発生することがあるのですが、Temporalだとハイフン(-)のみ使用可能となっているため、前述のような表記による問題は発生しません。

JavaScript
// ❌ Date - ハイフンとスラッシュのどちらも使用可
const date1 = new Date('2024-03-21')
console.log(date1) // Thu Mar 21 2024 09:00:00 GMT+0900 (日本標準時)

const date2 = new Date('2024/03/21')
console.log(date2) // Thu Mar 21 2024 00:00:00 GMT+0900 (日本標準時)

// ✅ Temporal - ハイフンは使用可だが、スラッシュは使用不可
const date1 = Temporal.PlainDate.from('2024-03-21') // エラーにならない
const date2 = Temporal.PlainDate.from('2024/03/21') // エラーになる

5. 0を1月とする一貫性のない動作

Dateはnew Date(2026, 1, 1)のように書くと1を2月にするという一貫性のない動作になります。これはバグ発生の要因になりやすいです。

Temporalではこのように月の始まりを0とする動作をしないので、1月は1であるという一貫性のある動作になります。

JavaScript
// ❌ Date - 一貫性のない動作
new Date(2026, 0, 1) // 2026年1月1日 (月が0始まり)
new Date(2026, 1, 1) // 2026年2月1日 (月が0始まり)

// ✅ Temporal - 一貫性のある動作
Temporal.PlainDate.from(2026, 0, 1)   // これはエラーになる
Temporal.PlainDate.from('2026-01-01') // 2026年2月1日 (月が1始まり)

6. 日付の計算がしにくい

Dateは日付の加算や減算を行うときは以下のようなコードとなり、直感的にわかりにくいです。

Temporalならaddおよびsubstractのメソッドチェーンを使用できるので直感的に計算可能です。

JavaScript
// ❌ Date - 日付の計算がしにくい
const today = new Date()
const result = new Date(today)

result.setMonth(result.getMonth() + 1)
result.setDate(result.getDate() + 2)
result.setFullYear(result.getFullYear() - 3)
console.log(result.toISOString().split('T')[0])
// 2023-02-20 (1ヶ月2日後から3年前)

// ✅ Temporal - 日付の計算がしやすい
const today = Temporal.Now.plainDateISO()
const result = today
  .add({ months: 1, days: 2 })
  .subtract({ years: 3 })

console.log(result.toString())
// 2023-02-20 (1ヶ月2日後から3年前)

7. 日付の期間が計算しにくい

Dateは期間の処理が複雑で面倒です。

Temporalならt1.since(t2)という書き方で期間を取得できます。

JavaScript
// ❌ Date - 複雑で面倒
const date1 = new Date('2026-01-18')
const date2 = new Date('2024-03-15')
const diffMs = date1 - date2
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
console.log(`${diffDays}`) // 674日 (日数のみしか出せない)

// ✅ Temporal - 簡単に期間を出せる
const temporal1 = Temporal.PlainDate.from('2026-01-18')
const temporal2 = Temporal.PlainDate.from('2024-03-15')
const durationDay = temporal1.since(temporal2, { largestUnit: 'day' });
const duration = temporal1.since(temporal2, { largestUnit: 'year' })
console.log(`${durationDay.days}`) // 674日 (日数のみの場合)
console.log(`${duration.years}${duration.months}ヶ月${duration.days}`)
// 1年10ヶ月3日 (年月日も出せる)

まとめ

TemporalはDateが抱えてきた設計上の不整合や扱いにくさを解消し、より安全で直感的な日時処理を可能にする標準APIであり、今後のJavaScript開発では重要な選択肢になります。

最新のChromeやMicrosoft Edgeでは使用可能になっているので、Consoleで記事内のコードを実行して、利便性を実感してみてください。