使用 Temporal 協調全球事件

網頁功能: Temporal

使用舊版 Date 物件安排跨時區活動非常困難,尤其是在日光節約時間 (DST) 轉換期間,可能會跳過或重複小時。

Temporal API 提供 Temporal.ZonedDateTime,用於表示特定時區的日期和時間,並自動以可預測的方式處理日光節約時間轉換。

導入方式

如要協調全球活動並處理潛在的日光節約時間衝突,請按照下列步驟操作:

  1. 必要: 建立 ZonedDateTime:使用 Temporal.ZonedDateTime.from() 建立可感知時區的日期時間物件。
  2. 必要: 處理模糊時間:使用 disambiguation 選項,控制時間模糊或不存在時 (例如時鐘變更期間) 的行為。
  3. 必填: 轉換時區:使用 .withTimeZone() 查看其他地點的對應時間。

範例:排程和衝突偵測

// 1. Define the event time and target time zone
const date = "2025-03-09";
const time = "02:30"; // This time is skipped in New York during Spring Forward
const timeZone = "America/New_York";
const inputStr = `${date}T${time}[${timeZone}]`;

// 2. Detect conflicts using 'reject'
let hasConflict = false;
try {
  // 'reject' throws RangeError if the time is ambiguous or does not exist
  Temporal.ZonedDateTime.from(inputStr, { disambiguation: 'reject' });
} catch (e) {
  if (e instanceof RangeError) {
    hasConflict = true;
    console.log("This time falls in a DST transition gap or overlap.");
  }
}

// 3. Resolve the time safely using 'compatible' (default)
// 'compatible' will resolve to a valid time even if skipped or repeated
const hostTime = Temporal.ZonedDateTime.from(inputStr, { disambiguation: 'compatible' });
console.log(`Resolved time: ${hostTime.toString()}`);

// 4. Convert to another time zone (e.g., Tokyo)
const tokyoTime = hostTime.withTimeZone("Asia/Tokyo");
// Use toLocaleString() for user-facing display instead of manual hour/minute padding
console.log(`Tokyo time: ${tokyoTime.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit' })}`);

策略執行與最佳做法

  • 務必使用 Temporal.ZonedDateTime 標示與特定地理位置相關的活動 (例如在特定城市舉辦的會議)。
  • 建議:如需偵測並警告使用者夏令時間轉換期間的時間表衝突,請使用 disambiguation: 'reject'。
  • 建議:如果希望系統在發生衝突時自動選擇合理的時間,請使用 disambiguation: 'compatible' (預設)。
  • 請勿將 Temporal.PlainDateTime 用於全球事件,因為它不含時區資訊,且無法考量日光節約時間的變化。
  • 建議使用 .withTimeZone() 計算其他位置的等效時間,而不變更原始物件 (Temporal 物件不可變更)。
  • 務必使用原生 .toLocaleString() 格式 (例如 { hour: 'numeric', minute: '2-digit' }) 顯示面向使用者的時間,而非手動計算時間和填補。

備用策略

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();
})();