php时区设置不生效的典型表现是date()输出比系统时间慢8小时或报时区警告,主因包括改错php.ini路径、cli与web环境配置分离、docker环境变量覆盖、未重启服务,以及误用prc/utc等非法或非东八区值。

php.ini 中 date.timezone 设置不生效的典型表现
改完 date.timezone = Asia/Shanghai 却发现 date('Y-m-d H:i:s') 依然比系统时间慢 8 小时,或者直接报 Warning:It is not safe to rely on the system's timezone settings——这说明 PHP 根本没读到你改的值。
常见原因包括:
- 改错了 php.ini 文件:用
phpinfo()查看Loaded Configuration File路径,不是随便找一个php.ini就去改 - PHP 运行模式影响加载:CLI(命令行)和 Web(如 Apache/Nginx + php-fpm)可能使用不同的
php.ini,需分别确认 - 被环境变量覆盖:Docker 容器中若设置了
PHP_INI_DIR或挂载了其他 ini 文件,会优先加载它们,导致主配置被跳过 - 忘记重启服务:Apache 需
sudo systemctl restart apache2,php-fpm 需sudo systemctl restart php*-fpm(版本号要匹配)
date.timezone 值写成 PRC 或 UTC 会怎样
PRC 是旧式缩写,在部分 PHP 版本(尤其是 5.4 以前)中支持,但自 PHP 5.5 起已弃用;UTC 是合法值,但它不是“北京时间”,而是零时区——设成它,date() 输出永远比东八区少 8 小时。
必须使用 IANA 标准时区名:
- 中国大陆统一用
Asia/Shanghai(不是Asia/Beijing,后者不存在) - 避免拼写错误:大小写敏感,不能写成
asia/shanghai或Asia/shanghai - 不要加引号:
date.timezone = "Asia/Shanghai"是错的,ini 文件里不加引号
为什么改了 php.ini 还要调用 date_default_timezone_set()
不是“还要”,而是“可能必须”——尤其在共享主机、无权限改 php.ini、或框架启动逻辑绕过全局配置时。
比如 Laravel 的 config/app.php 中 'timezone' => 'Asia/Shanghai' 本质就是调用 date_default_timezone_set();如果这个配置被中间件、服务提供者或 .env 中的 APP_TIMEZONE 覆盖,而你又没检查实际生效值,php.ini 的设置就形同虚设。
验证是否真正生效的唯一方式是运行:
var_dump(date_default_timezone_get(), date('Y-m-d H:i:s'));
这两项输出必须同时符合预期:前者返回 Asia/Shanghai,后者显示当前北京时间(非 UTC 时间)。
修改 date.timezone 后 MySQL 时间仍不对怎么办
PHP 和 MySQL 时区完全独立。PHP 改了 date.timezone,只影响 date()、strtotime()、DateTime 默认行为,不影响 MySQL 的 NOW()、CURDATE() 或字段插入逻辑。
MySQL 需单独配置:
- 查当前设置:
SELECT @@global.time_zone, @@session.time_zone; - 临时设会话级:
SET time_zone = '+08:00'; - 永久生效:在
my.cnf的[mysqld]段下加default-time-zone = '+08:00',然后重启 MySQL - 注意:设成
SYSTEM并不等于 PHP 的时区,它读的是操作系统时区,而 PHP 不读操作系统时区
最稳妥的做法是:PHP 统一用 date('Y-m-d H:i:s') 输出东八区字符串,MySQL 配置为 +08:00,且所有时间字段类型优先选 TIMESTAMP(自动按 MySQL 时区转存 UTC),而非 DATETIME(纯字符串存储,无时区语义)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











