PHP时区需通过设置IANA时区标识符(如Asia/Shanghai)解决,而非校准;最彻底方式是修改php.ini中date.timezone并重启服务,次选运行时调用date_default_timezone_set(),新代码推荐DateTime构造时指定时区。

PHP 时区不是靠“校准”解决的,而是通过明确设置时区标识符(如 Asia/Shanghai)来避免时间偏差。默认时区为 UTC 或系统本地时区,若未显式配置,date()、strtotime()、DateTime 等函数会出错或返回错误时间。
修改 php.ini 中的 date.timezone 配置
这是最彻底、全局生效的方式,适用于所有 PHP 脚本和 CLI 环境。
- 找到正在使用的
php.ini文件(运行php --ini或phpinfo()查看 “Loaded Configuration File”) - 取消注释并修改
date.timezone行,例如:date.timezone = "Asia/Shanghai"
- 注意:必须使用 IANA 时区名(如
Asia/Shanghai),不能写GMT+8或PRC—— 后者已废弃且不被识别 - 改完后需重启 Web 服务器(如 Apache/Nginx)或 PHP-FPM 进程,否则不生效
运行时用 date_default_timezone_set() 设置
适合无法修改 php.ini 的场景(如共享主机),或需要在单个脚本中临时切换时区。
- 必须在调用任何日期函数前执行,否则会触发警告:
It is not safe to rely on the system's timezone settings - 示例:
date_default_timezone_set("Asia/Shanghai"); echo date('Y-m-d H:i:s'); - 该设置只对当前请求/脚本生命周期有效,不影响其他请求或 CLI 子进程
- 如果项目混合使用
date()和DateTime,此方式同样生效 —— 它是 PHP 内部默认时区的统一入口
DateTime 构造时指定时区(推荐用于新代码)
比全局设置更精确,避免时区污染,尤其适合处理多时区业务(如订单创建地、用户所在地、服务器日志时间)。
立即学习“PHP免费学习笔记(深入)”;
- 不依赖全局时区,每个对象独立携带时区信息:
$dt = new DateTime('now', new DateTimeZone('Asia/Shanghai')); - 可安全转换:
$utc = $dt->setTimezone(new DateTimeZone('UTC')); - 数据库存取时建议统一用 UTC,展示时再转目标时区 —— 避免夏令时、历史时区变更导致的歧义
- 注意:
new DateTime()不传DateTimeZone时,会 fallback 到date_default_timezone_get()返回的值
验证时区是否生效及常见陷阱
光改配置不验证,等于没改。很多问题其实出在“以为改了,其实没生效”。
- 检查当前生效时区:
echo date_default_timezone_get(); // 应输出 Asia/Shanghai
- 确认
phpinfo()页面中 “date.timezone” 行显示的是你设的值,且状态为 “Local Value” 和 “Master Value” 一致 - CLI 和 Web 的 php.ini 可能不同:用
php -i | grep timezone查 CLI,用phpinfo()查 Web - Docker 环境中,PHP 容器内时区 ≠ 宿主机时区,需在 Dockerfile 或 docker-compose.yml 中同时设置
TZ=Asia/Shanghai并挂载 /etc/localtime,否则date()可能仍返回 UTC 时间
真正麻烦的不是改哪一行,而是 PHP 有至少 4 个地方可以设时区(php.ini、.htaccess、ini_set()、date_default_timezone_set()),优先级不同,还可能互相覆盖。线上出问题时,先查 date_default_timezone_get() 返回什么,再逆向排查哪里被覆盖了。











