ウェブ機能:
Temporal
従来の JavaScript Date オブジェクトは、先発グレゴリオ暦に基づいているため、イスラム暦(太陰暦)、ユダヤ暦(太陰太陽暦)、中国暦(太陰太陽暦)など、他の暦法を使用するユーザー向けのアプリケーションを構築するのは困難です。以前は、これらのシステムをサポートするために、複雑なサードパーティ ライブラリや手動計算に頼る必要がありました。
Temporal API は、複数の暦法を完全にサポートしています。カレンダー識別子を日付オブジェクトに関連付けることで、Temporal は、さまざまな文化的コンテキストに必要な複雑な演算と書式設定をネイティブに処理します。
実装方法
Temporal を使用してグローバル カレンダー システムをサポートするには:
- カレンダーを関連付ける(必須): Temporal オブジェクト(
Temporal.PlainDateなど)を作成または変換する場合は、withCalendar()を使用して目的のカレンダー システムを指定し、カレンダーに依存するオペレーションを実行する必要があります。 - 安定した識別子を使用する(太陰太陽暦では必須): 太陰太陽暦で年をまたいで特定の月を識別するには、数値の
monthインデックスではなくmonthCodeを使用する必要があります。この設定は、ユダヤ暦や中国暦など、閏月を使用するカレンダーでのみ使用してください。 - カレンダーの不変条件を尊重する(必須): 月や日を反復処理する際に、固定値(1 年は 12 か月、1 か月は 31 日など)を想定しないでください。
monthsInYearやdaysInMonthなどのプロパティを使用して、コードがすべてのカレンダーで動作するようにします。 - カレンダー対応の比較を使用する(必須): 特定のカレンダー システム内で日付を比較する場合は、年 / 月 / 日のプロパティを手動で比較するのではなく、
Temporal.PlainDate.compare()を使用する必要があります。これにより、カレンダー ルール内の時系列順が正しく処理されます。
コード例: カレンダーの変換と反復処理
// 1. Helper to check calendar support
function isCalendarSupported(calendarId) {
try {
return Intl.supportedValuesOf('calendar').includes(calendarId);
} catch {
// Fallback for environments where supportedValuesOf is not available
return false;
}
}
// 2. Get current date in default ISO 8601 calendar
const isoDate = Temporal.Now.plainDateISO();
// 3. Convert to Hebrew calendar if supported
const calendarId = 'hebrew';
const targetDate = isCalendarSupported(calendarId)
? isoDate.withCalendar(calendarId)
: isoDate; // Fallback to ISO if not supported
if (targetDate.calendar.id !== calendarId) {
console.warn(`Calendar ${calendarId} not supported; falling back to ISO 8601`);
}
// 4. Log properties specific to the calendar
console.log(`Calendar: ${targetDate.calendar.id}`);
console.log(`Year: ${targetDate.year}`);
console.log(`Month Code: ${targetDate.monthCode}`); // Stable across leap years
// 5. Safely iterate through months in the current year
for (let m = 1; m <= targetDate.monthsInYear; m++) {
console.log(`Month ${m} has ${targetDate.with({ month: m }).daysInMonth} days.`);
}
// 6. Compare dates within the same calendar
const today = Temporal.Now.plainDateISO().withCalendar(calendarId);
const comparison = Temporal.PlainDate.compare(targetDate, today);
const relative = comparison < 0 ? 'Past' : comparison > 0 ? 'Future' : 'Today';
console.log(`Timeline: ${relative}`);
// 7. Format for display using toLocaleString (including era for era-based calendars like 'japanese')
const localizedDisplay = targetDate.toLocaleString('en-u-ca-hebrew', {
day: 'numeric',
month: 'long',
year: 'numeric',
era: 'long'
});
戦略的な実装とベスト プラクティス
- 推奨: 月をループ処理する際は、12 と想定するのではなく、
monthsInYearを上限として使用します。 - 推奨: 年に関係なく、閏月を使用するカレンダー(ヘブライ語や中国語など)で特定の月を識別するには、
monthCodeを使用します。 date.month === 12が 1 年の最後の月であると想定しないでください。date.month === date.monthsInYearを使用します。inLeapYear === trueが 1 年が 1 日だけ長いことを意味すると想定しないでください。太陰太陽暦では、1 か月分のうるう月が追加されることがあります。- 推奨: 特定のカレンダー システムで 2 つの日付を比較する場合は、年 / 月 / 日のプロパティを手動で比較するのではなく、
Temporal.PlainDate.compare()を使用します。 - 推奨: 手動で文字列を連結するのではなく、
toLocaleString()を使用してユーザー向けに日付をフォーマットします。 - すべきこと: カレンダー固有の Temporal オブジェクトを作成する前に、
Intl.supportedValuesOf('calendar')を使用して、ターゲット カレンダー システムが環境でサポートされていることを確認します。 - 推奨事項: 一部のカレンダー(イスラム暦のバリエーションなど)は、固定された計算ではなく、視覚的な観察に依存している場合があることに注意してください。
TemporalAPI は、環境のIntl実装に従います。通常、この実装では計算された近似値が使用されます。重要な文化的または宗教的な日付の計算については、専門家に確認するか、専用のライブラリを使用してください。 toLocaleString()を使用して、元号を使用するカレンダー(和暦、仏暦など)を使用する場合は、元号を考慮してください。
代替戦略
Temporal のフォールバックとブラウザ サポート
ネイティブの Temporal API をまだサポートしていないブラウザの場合は、機能検出を使用して temporal-polyfill(約 15 KB min+gz)を動的に読み込みます。
temporal-polyfill をインポートしても、Temporal オブジェクトがグローバル スコープに自動的に割り当てられるわけではありません。コードが globalThis.Temporal に依存している場合は、明示的に割り当ててください。
// Check if Temporal is supported natively
(async () => {
if (typeof Temporal === 'undefined') {
// Load the polyfill conditionally
const module = await import('https://esm.sh/temporal-polyfill');
globalThis.Temporal = module.Temporal;
// Extend Date.prototype if needed
Date.prototype.toTemporalInstant = module.toTemporalInstant;
}
initializeApp();
})();