php时区配置存在系统级、php.ini层、运行时层三个层级:系统级由linux的/etc/timezone等决定;php.ini层通过date.timezone设置;运行时层用date_default_timezone_set()覆盖前两者。

PHP时区配置存在哪几个层级
PHP时区不是单点设置,而是三层叠加:系统级(OS)、PHP全局配置(php.ini)、运行时(date_default_timezone_set())。迁移时只改php.ini里的date.timezone,很可能被代码里某处date_default_timezone_set('UTC')覆盖掉——这是最常被忽略的源头。
- 系统级:Linux 的
/etc/timezone或/etc/localtime软链接,影响gettimeofday()等底层调用,但 PHP 默认不依赖它 -
php.ini层:date.timezone = "Asia/Shanghai",仅对未显式调用date_default_timezone_set()的脚本生效 - 运行时层:任何地方调用
date_default_timezone_set()都会覆盖前两者,且作用域是当前请求生命周期
如何安全备份当前时区配置
不能只备份 php.ini,得确认实际生效的是哪个值。用 php -r "echo date_default_timezone_get();" 获取运行时结果,再对比 php --ini 找到加载的 php.ini 路径,打开查 date.timezone 行。
- 执行
php -r "echo date_default_timezone_get() . "\n";"—— 这是真实生效的时区 - 执行
php --ini查看主配置文件路径,然后grep "^date.timezone" /path/to/php.ini - 如果输出为空,说明没在
php.ini里设,得检查代码中是否硬编码了date_default_timezone_set() - 建议把这两条命令的结果一起存为
timezone-backup-$(date +%Y%m%d).txt,避免迁移后回溯困难
跨环境迁移时区配置的常见翻车点
开发机设成 "Asia/Shanghai",上生产却用 "PRC"(已废弃别名),或反过来——PHP 会静默接受但行为不一致。更隐蔽的是 Docker 容器里没挂载宿主机时区文件,php.ini 虽然写了 Asia/Shanghai,但 date_default_timezone_get() 返回 UTC。
-
"PRC"、"ROC"、"GMT+8"等非标准字符串在新版 PHP(>=8.1)可能触发警告甚至拒绝设置 - Docker 镜像里必须同时做两件事:
ENV TZ=Asia/Shanghai+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime,否则date命令和 PHP 时区可能不一致 - Apache + mod_php 和 PHP-FPM 的
php.ini可能不同,用phpinfo()页面确认“Loaded Configuration File”路径
运行时强制统一时区的兜底方案
如果无法控制所有代码(比如用了第三方 SDK),又必须确保全站时间逻辑一致,别指望修改配置文件,直接在入口文件顶部加一行 date_default_timezone_set("Asia/Shanghai") 最可靠。
立即学习“PHP免费学习笔记(深入)”;
- 放在
index.php或框架的公共引导文件开头,早于任何可能调用date()或new DateTime()的代码 - 不要用
ini_set("date.timezone", "..."),它在某些 SAPI(如 CLI)下无效,而date_default_timezone_set()全局有效 - 注意:如果已有代码在
__autoload或 Composer 自动加载里调用了时间函数,这行代码必须比自动加载注册更早执行
date_default_timezone_get() 的返回值,比盯着 php.ini 文件更管用。











