萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 時區設定三大方法完整指南:解決 8 小時時差問題

問題根源

PHP 預設時區為 **UTC**(協調世界時),中國標準時間(CST)為 **UTC+8**,直接使用 date()、time()、DateTime 會比本地時間少 8 小時。

方法一:修改 php.ini(全域生效、需重啟、推薦生產環境)

; php.ini
date.timezone = "Asia/Shanghai"
; 或
date.timezone = "PRC"
  1. 找到 php.ini 位置:php --ini 或 phpinfo()。
  2. 搜尋 date.timezone,取消註解並設定值。
  3. 重啟 PHP-FPM / Apache:systemctl restart php8.1-fpm。
  4. 驗證:php -r "echo date('Y-m-d H:i:s');" 輸出本地時間。

優點:一次設定、全域生效、無程式碼入侵。
缺點:需服務器權限、修改後需重啟、容器化部署需重建映像或掛載配置。

方法二:腳本執行期設定(程式碼控制、無需權限、最常用)

<?php
// 必須在任何日期/時間函式呼叫**之前**執行
date_default_timezone_set('Asia/Shanghai');
// 或
date_default_timezone_set('PRC'); // 別名,效果相同

// 後續 date(), time(), new DateTime() 皆使用 CST
echo date('Y-m-d H:i:s'); // 正確顯示北京時間

優點:開發者可控、無需重啟、適合共享主機/無權限環境。
缺點:每個入口檔案/框架啟動檔都要寫、易遺漏導致不一致。

方法三:ini_set() 執行期修改(同方法二、語法不同)

<?php
ini_set('date.timezone', 'Asia/Shanghai');
// 效果等同 date_default_timezone_set()

注意:ini_set 某些指令需 PHP_INI_ALL 權限,date.timezone 屬 PHP_INI_ALL,可運行期修改。

時區識別碼對照表(常用)

完整列表見 PHP 官方時區列表。

現代最佳實踐:使用 DateTimeImmutable + DateTimeZone

<?php
// 明確指定時區,避免全域設定影響
$dt = new DateTimeImmutable('now', new DateTimeZone('Asia/Shanghai'));
echo $dt->format('Y-m-d H:i:s'); // 2024-01-15 14:30:00

// 時區轉換
$utc = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$cst = $utc->setTimezone(new DateTimeZone('Asia/Shanghai'));
echo $cst->format('Y-m-d H:i:s'); // 自動 +8 小時

// 儲存建議:資料庫統一存 UTC (TIMESTAMP / DATETIME + UTC)
// 顯示時按用戶時區轉換

框架整合範例

地區識別碼備註
中國大陸Asia/Shanghai**推薦**,IANA 標準
中國大陸PRC別名,相容舊代碼
台灣Asia/Taipei
香港Asia/Hong_Kong
新加坡Asia/Singapore
UTCUTC基準時間
框架設定位置範例
Laravelconfig/app.php'timezone' => 'Asia/Shanghai',
Symfonyconfig/packages/framework.yamlframework: { php_timezone: 'Asia/Shanghai' }
ThinkPHPconfig/app.php'default_timezone' => 'Asia/Shanghai'
Yii2config/web.php (components)'formatter' => ['timeZone' => 'Asia/Shanghai']

常見坑與避雷指南

  1. 多次設定衝突:php.ini + 程式碼雙重設定以程式碼為準,但易造成困惑 → **統一由框架/入口檔集中設定**。
  2. Docker 容器時區:容器內系統時區也需設定,否則 date('e') 顯示 UTC。
    Dockerfile: ENV TZ=Asia/Shanghai + RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  3. 資料庫時區不一致:MySQL time_zone 變數、connectionTimeZone (PDO) 需與 PHP 一致,建議**雙方皆用 UTC 存儲,顯示層轉換**。
  4. strtotime()、mktime() 受 date.timezone 影響,DateTime 建構子預設也受影響,DateTimeImmutable 同理。

總結

**生產環境首選:php.ini 設定 date.timezone = Asia/Shanghai + 容器環境變數 TZ=Asia/Shanghai**。
**開發/無權限環境**:入口檔第一行 date_default_timezone_set('Asia/Shanghai')。
**現代化開發**:棄用 date(),改用 DateTimeImmutable + 明確 DateTimeZone,資料庫存 UTC,顯示層按用戶時區轉換,徹底消除時區 Bug。

copyright © 萬盛學電腦網 all rights reserved