與後端的時區處理

問題描述

當前端與後端交換時間數據時,如果沒有正確處理時區,可能會導致顯示的時間不正確。

時間格式與時區處理

我傳給後端的格式是 2025-03-31T17:00,這是一個沒有時區標記的時間格式。當這種沒有時區標記的時間被解析時,JavaScript 和大多數系統會將其視為本地時間。

如果後端接收到 2025-03-31T17:00 這個值,它應該理解為「本地時區的 2025 年 3 月 31 日 17:00」。理想情況下,後端會將其轉換為 UTC 時間存儲,並在返回給前端時使用 UTC 格式並添加 Z 標記,例如 2025-03-31T09:00:00Z(假設原始時間是台灣 UTC+8 時間 17:00)。

後端給的時間 2025-03-31T17:00:00.000Z 已經是 UTC 時間(Z 表示零時區),而當 Angular 的 DatePipe 處理這個時間時,它會自動將其轉換為瀏覽器的本地時區(對於台灣來說是 UTC+8),所以實際顯示的時間會自動加上 8 小時,變成 2025-04-01 01:00:00

解決方案

解決方法是在送表單時將本地時間明確轉換為帶時區標記的 ISO 格式,這樣後端收到的就是標準的 UTC 時間:

// 例如,假設 endTimeValue 是 "2025-03-31T17:00"
const localTime = new Date(endTimeValue); // 解析為本地時間
const formData = {
  // ...其他字段
  end_time: localTime.toISOString() // 轉換為帶有 Z 標記的 UTC 時間
};

使用 toISOString() 會將時間轉換為 UTC 並添加 Z 標記,例如 2025-03-31T09:00:00.000Z(如果您在 UTC+8 時區且原時間是 17:00)。

在實際應用中,最好確保表單值不為 null:

if (this.createEventForm.valid) {
  const eventData = {
    // ...
    end_time: new Date(this.createEventForm.controls.endTime.value).toISOString(),
    // ...
  };
}

在前端顯示時間

對於從後端獲取的時間,可以使用 Angular 的 DatePipe 並讓它自動處理時區轉換:

{{ eventData.created_at | date : "yyyy-MM-dd HH:mm" }}

如果需要特定時區的顯示,可以指定時區:

<!-- 強制使用 UTC 時區 -->
{{ eventData.created_at | date : "yyyy-MM-dd HH:mm" : "UTC" }}

<!-- 強制使用台灣時區 -->
{{ eventData.created_at | date : "yyyy-MM-dd HH:mm" : "+0800" }}

注意事項

  1. 一致性:前後端應該有一致的時間處理策略

  2. 存儲:建議在數據庫中以 UTC 格式存儲時間

  3. 顯示:只在最終顯示給用戶時轉換為本地時區

  4. 測試:跨時區測試時間處理邏輯

Last updated