日付と時間を扱うことは、JavaScript開発者にとって長い間苦痛のポイントでした。ネイティブのDate
オブジェクトは、その癖と制限により、多くの開発者がMoment.jsやdate-fnsのようなサードパーティのライブラリに移行する原因となりました。しかし、JavaScriptを進化させる責任を持つTC39委員会が解決策に取り組んできました:Temporal APIです。この包括的かつ現代的なアプローチは、JavaScriptの時間関連操作における長年の課題を解決することが約束されています。
JavaScriptのDateオブジェクトの問題
Temporal APIに飛び込む前に、現在のDate
オブジェクトの制限を理解することが重要です:
- 可変状態: Dateオブジェクトはその場で変更でき、予期しない副作用が生じる可能性があります
- 機能の制限: 日数を加算したり日付を比較したりする単純な操作は、複雑なコードを必要とします
- 文字列解析の不一致: 文字列からの日時解析は、ブラウザによって信頼性が低いことで有名です
- タイムゾーンサポートなし: UTCおよびローカル時間以外のタイムゾーンを十分に処理できません
- グレゴリオ暦のみ: 他のカレンダーシステムのサポートがありません
- 混乱したAPI:
getMonth()
のようなメソッドは、0から始まる値(0-11ではなく1-12)を返します
これらの問題により、JavaScriptでの日付の処理はエラーを引き起こしやすく、いらいらさせるものとなり、サードパーティのライブラリの広範な採用につながっています。
Temporal APIの紹介
Temporal APIは、日付と時間を扱うための現代的な包括的解決策を提供するJavaScriptへの提案された追加です。それは、さまざまな日付と時間の操作のためのクラスを含むグローバルオブジェクト(Temporal
)として設計されています。
Temporal APIの基本原則には以下が含まれます:
- 不変性: すべてのTemporalオブジェクトは不変であり、副作用を排除します
- 明確さ: 異なる日付/時間の概念の間の明確な区別
- タイムゾーンサポート: すべてのタイムゾーンに対する一級のサポート、DST安全な算術を含む
- 複数のカレンダーシステム: グレゴリオ暦以外のカレンダー帳に対応
- 精度: 時間計算に対するナノ秒精度
- 一貫性: 標準化された解析とフォーマット
Temporal APIの主要データ型
Temporal APIは、日付と時間のさまざまな側面を処理するためのいくつかの専門クラスを導入します:
タイムゾーン情報なしのプレインデータ型
- Temporal.PlainDate: 日付に関するカレンダー日を表します(例:2006年8月24日)
- Temporal.PlainTime: 日付やタイムゾーンなしの壁時計時間(例:午後7時39分)を表します
- Temporal.PlainDateTime: タイムゾーン情報なしの日付と壁時計時間を組み合わせます
- Temporal.PlainYearMonth: 特定の年と月(例:2020年10月)を表します
- Temporal.PlainMonthDay: 年なしの月と日を表します(例:7月14日)
タイムゾーン情報ありのゾーンデータ型
- Temporal.ZonedDateTime: 特定の地域からの視点で、特定の時間における実際のイベントを表すタイムゾーンに対応した日付/時間オブジェクト
- Temporal.Instant: カレンダーや場所に関する考慮なしで、時間の固定点を表します(正確な時間)
追加の型
- Temporal.Duration: 時間の長さ(例:5分30秒)を表現します
- Temporal.TimeZone: タイムゾーンを表し、変換メソッドを提供します
- Temporal.Calendar: カレンダーシステムを表します
Temporal APIを使用する
Temporalオブジェクトの作成
Temporal APIは、オブジェクトを作成するためのいくつかの方法を提供します:
// 現在の日付と時間を取得
const now = Temporal.Now.plainDateTimeISO();
console.log(now.toString()); // 例:2023-08-24T14:30:45.123456789
// 日付のみ
const today = Temporal.Now.plainDateISO();
console.log(today.toString()); // 例:2023-08-24
// 時間のみ
const currentTime = Temporal.Now.plainTimeISO();
console.log(currentTime.toString()); // 例:14:30:45.123456789
// コンポーネントからオブジェクトを作成
const date = Temporal.PlainDate.from({ year: 2023, month: 8, day: 24 });
const time = Temporal.PlainTime.from({ hour: 14, minute: 30, second: 45 });
const dateTime = Temporal.PlainDateTime.from({
year: 2023,
month: 8,
day: 24,
hour: 14,
minute: 30,
second: 45
});
// ISO文字列から作成
const dateFromString = Temporal.PlainDate.from("2023-08-24");
const timeFromString = Temporal.PlainTime.from("14:30:45");
const dateTimeFromString = Temporal.PlainDateTime.from("2023-08-24T14:30:45");
タイムゾーンの使用
Temporal APIを使うことで、タイムゾーンの取り扱いが非常に簡単になります:
// 現地タイムゾーンでの現在の時間
const localTime = Temporal.Now.zonedDateTimeISO();
console.log(localTime.toString());
// 例:2023-08-24T14:30:45+01:00[Europe/London]
// 特定のタイムゾーンでの現在の時間
const tokyoTime = Temporal.Now.zonedDateTimeISO("Asia/Tokyo");
console.log(tokyoTime.toString());
// 例:2023-08-24T22:30:45+09:00[Asia/Tokyo]
// タイムゾーン間の変換
const nyTime = localTime.withTimeZone("America/New_York");
console.log(nyTime.toString());
// 例:2023-08-24T09:30:45-04:00[America/New_York]
日付と時間の算術
Temporal APIの最も強力な機能の一つは、直感的な算術操作です:
// 時間を加算
const tomorrow = today.add({ days: 1 });
const nextWeek = today.add({ days: 7 });
const twoHoursLater = currentTime.add({ hours: 2 });
// 時間を減算
const yesterday = today.subtract({ days: 1 });
const lastWeek = today.subtract({ days: 7 });
const twoHoursEarlier = currentTime.subtract({ hours: 2 });
// 期間の使用
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
const laterTime = currentTime.add(duration);
// 2つの日付の差を見つける
const date1 = Temporal.PlainDate.from("2023-01-01");
const date2 = Temporal.PlainDate.from("2023-08-24");
const difference = date1.until(date2);
console.log(difference.toString()); // P236D(ISO 8601の期間形式)
console.log(difference.days); // 236
"with"を使ったコンポーネントの修正
Temporal APIは、修正されたコンポーネントで新しいオブジェクトを作成するクリーンな方法を提供します:
// 日付の年を変更
const nextYear = date.with({ year: date.year + 1 });
// 特定のコンポーネントを設定
const newDateTime = dateTime.with({ hour: 12, minute: 0, second: 0 });
console.log(newDateTime.toString()); // 2023-08-24T12:00:00
Temporalオブジェクトの比較
APIは直感的な比較メソッドを提供します:
const date1 = Temporal.PlainDate.from("2023-08-24");
const date2 = Temporal.PlainDate.from("2023-09-15");
console.log(date1.equals(date2)); // false
console.log(date1.equals(date1)); // true
console.log(date1.before(date2)); // true
console.log(date1.after(date2)); // false
console.log(date1.since(date2).days); // -22
DSTおよび曖昧な時間の処理
Temporal APIは、夏時間の移行の複雑さを優雅に処理します:
// DST移行中の時間を作成
const dstTime = Temporal.ZonedDateTime.from({
timeZone: "America/New_York",
year: 2023,
month: 11,
day: 5,
hour: 1,
minute: 30
});
// APIは曖昧な時間を扱う方法を指定できます
const dstTimeExact = Temporal.ZonedDateTime.from({
timeZone: "America/New_York",
year: 2023,
month: 11,
day: 5,
hour: 1,
minute: 30,
disambiguation: "earlier" // オプション:'earlier', 'later', 'compatible', 'reject'
});
非グレゴリオ暦のサポート
Date
オブジェクトとは異なり、Temporal APIは複数のカレンダーシステムをサポートします:
// ヘブライ暦の日付を作成
const hebrewDate = Temporal.PlainDate.from({
year: 5783,
month: 5,
day: 15,
calendar: "hebrew"
});
// カレンダーシステム間の変換
const gregorianDate = hebrewDate.withCalendar("iso8601");
解析とフォーマット
Temporal APIは、解析とフォーマットのための組み込みメソッドを提供します:
// 文字列からの解析
const date = Temporal.PlainDate.from("2023-08-24");
// カスタムフォーマット
const options = {
year: 'numeric',
month: 'long',
day: 'numeric'
};
console.log(date.toLocaleString("ja-JP", options)); // 2023年8月24日
現在の状況とブラウザのサポート
執筆時点で、Temporal APIはTC39の提案プロセスのステージ3にあり、最終決定が近づいていますが、まだ公式のECMAScript標準には含まれていません。ネイティブブラウザのサポートはまだ待機中ですが、開発者は@js-temporal/polyfill
のようなポリフィルを使用して、今日このAPIを使い始めることができます:
// ポリフィルのインストール
// npm install @js-temporal/polyfill
// コードでの使用
import { Temporal } from "@js-temporal/polyfill";
const now = Temporal.Now.plainDateTimeISO();
結論
Temporal APIは、JavaScriptの日付と時間の処理能力において大幅な改善を示しています。Date
オブジェクトの長年の問題に対処し、包括的で直感的なAPIを提供することで、JavaScriptでの時間の概念の処理をより快適でエラーを減らすものにすることを約束しています。
Temporal APIの主な利点には次のものがあります:
- 不変性: すべての操作が新しいオブジェクトを返し、副作用を防ぎます
- 明確さ: 異なる種類の日付と時間の明確な区別
- 包括的: 単純な日付から複雑なタイムゾーン対応の操作までカバーしています
- 直感的:
add()
、subtract()
、with()
のようなメソッドで、一般的な操作が簡単になります - 精密: ナノ秒精度をサポートしています
- グローバル: 複数のタイムゾーンとカレンダーシステムをサポートしています
ブラウザがこのAPIをネイティブに実装するのを待っている間、ポリフィルは開発者が今日これらの改善を享受し始めることを可能にします。ウェブアプリケーションがますますグローバルで時間に敏感になる中で、Temporal APIはすべてのJavaScript開発者のツールキットの中で不可欠なツールとなり、基本的な日付と時間の操作に対する外部ライブラリの必要性をようやく終わらせることでしょう。
Temporal APIを取り入れることで、開発者は時間、日付、およびタイムゾーンの複雑さを正しく処理し、グローバルにおいて優れたユーザーエクスペリエンスを実現するクリーンでメンテナンスしやすいコードを書くことができるようになります。