時間戳(Timestamp)是**時區無關**的絕對時間點。轉換邏輯是:
錯誤做法:直接對時間戳加減時差(忽略夏令時、歷史時區變更)。
正確做法:使用 `DateTime` + `DateTimeZone` 或 `date_default_timezone_set` 切換。
setTimezone(new DateTimeZone('Asia/Shanghai'));
return $dt->format('Y-m-d H:i:s');
}
/**
* 北京時間 → 太平洋時間
*/
function beijingToPacific(string $beijingTime = 'now'): string {
$dt = new DateTime($beijingTime, new DateTimeZone('Asia/Shanghai'));
$dt->setTimezone(new DateTimeZone('America/Los_Angeles'));
return $dt->format('Y-m-d H:i:s');
}
// 測試
echo "PST/PDT → CST: " . pacificToBeijing('2024-01-15 10:00:00') . PHP_EOL; // 冬令時 +16h
echo "PST/PDT → CST: " . pacificToBeijing('2024-07-15 10:00:00') . PHP_EOL; // 夏令時 +15h
echo "CST → PST/PDT: " . beijingToPacific('2024-01-15 02:00:00') . PHP_EOL;
echo "CST → PST/PDT: " . beijingToPacific('2024-07-15 03:00:00') . PHP_EOL;
PST/PDT → CST: 2024-01-16 02:00:00 // 冬令時差 16 小時 PST/PDT → CST: 2024-07-16 01:00:00 // 夏令時差 15 小時 CST → PST/PDT: 2024-01-15 10:00:00 CST → PST/PDT: 2024-07-15 10:00:00
原碼使用 `date_default_timezone_set` 全局切換,**非線程安全**,且邏輯繞彎:
// 原碼問題:
// 1. 多次切換全局時區,並發環境下極易錯亂
// 2. strtotime/date 依賴當前時區,中間轉換邏輯混亂
// 3. 返回時間戳而非格式化字符串,使用不便
// 修正版:封裝為純函數,無副作用
function pacificToPRC_legacy($time = '') {
$tzFrom = new DateTimeZone('Pacific/Apia'); // 注意:原碼用 Apia(UTC+13) 非美洲太平洋
$tzTo = new DateTimeZone('Asia/Shanghai');
$dt = $time ? new DateTime($time, $tzFrom) : new DateTime('now', $tzFrom);
$dt->setTimezone($tzTo);
return $dt->getTimestamp(); // 或 format()
}
| 地區 | IANA 時區標識符 | 備註 |
|---|---|---|
| 北京/上海 | Asia/Shanghai | 中國標準時間 CST (UTC+8),無夏令時 |
| 美洲太平洋 (洛杉磯) | America/Los_Angeles | PST(UTC-8)/PDT(UTC-7),有夏令時 |
| 薩摩亞 (阿皮亞) | Pacific/Apia | 原碼使用,UTC+13,非通用「太平洋時間」 |
| UTC | UTC | 基準時間,推薦存儲/傳輸用 |
function convertTimezone(string $time, string $fromTz, string $toTz, string $format = 'Y-m-d H:i:s'): string {
$dt = new DateTime($time, new DateTimeZone($fromTz));
$dt->setTimezone(new DateTimeZone($toTz));
return $dt->format($format);
}
// 使用
echo convertTimezone('2024-07-01 12:00', 'America/Los_Angeles', 'Asia/Shanghai'); // 2024-07-02 03:00
echo convertTimezone('2024-07-01 12:00', 'Asia/Shanghai', 'America/Los_Angeles'); // 2024-06-30 21:00
時區轉換看似簡單,實則暗藏夏令時、歷史變更、並發安全等坑點。採用 DateTime + IANA 時區標識符 是現代 PHP 處理時間的專業標準。