
Warning: It is not safe to rely on the system’s timezone settings 怎么快速定位原因
这个警告不是 PHP 报错,而是 E_WARNING,说明 PHP 根本没拿到合法时区,正 fallback 到系统默认(通常是 UTC)。它每次调用 date()、strtotime()、new DateTime() 都会触发,但不中断执行——所以你可能只在日志里看到,页面却“看起来正常”,直到缓存失效、JWT 过期或定时任务跑偏才暴露。
别急着改代码,先确认真实生效值:
php -r "echo date_default_timezone_get() . \"\n\"; echo ini_get('date.timezone');"
如果第一行输出是 UTC 或空,第二行是 no value,说明配置根本没加载;如果两行不一致,说明代码里有人提前调了 date_default_timezone_set() 但传了非法字符串(比如 "CST" 或 "GMT+8")。
.user.ini 设置 date.timezone 为什么有时不生效
很多虚拟主机禁用 date_default_timezone_set(),但允许 .user.ini。它生效快、不用重启,但有硬性前提:
立即学习“PHP免费学习笔记(深入)”;
-
.user.ini文件名必须带点开头,不能叫user.ini或timezone.ini - 内容只能是纯 INI 格式:
date.timezone = "Asia/Shanghai"(双引号必需,PRC或GMT+8无效) - PHP 必须启用
user_ini.enable(查phpinfo()中该项是否为On) - OPcache 缓存了旧配置?改完等最多 300 秒,或手动调
opcache_reset()(如有权限) - 路径必须放在实际 Web 入口目录下(比如
/var/www/html/.user.ini),子目录不继承
date_default_timezone_set() 调用失败的三个高发场景
即使函数没被禁用,也常因调用时机或参数翻车:
- 在
require或include其他文件之后才调用 → 前面文件里已有date()执行,警告已触发,时区被锁死为 UTC - 传入拼写错误的 IANA 名,例如
"Asia/Shangahi"、"Asia/Beijing"(IANA 数据库中不存在)、"China/Standard" - CLI 和 Web 使用不同 php.ini:网页里设好了,但
php artisan schedule:run或 crontab 脚本仍报警告 —— 检查php -i | grep "Loaded Configuration File"
安全写法是在所有入口脚本最顶部加:
if (!date_default_timezone_set('Asia/Shanghai')) {
error_log('Failed to set timezone: ' . date_default_timezone_get());
}
为什么改了 php.ini 还是不生效
90% 的问题出在“改错了文件”或“没重启对服务”:
- Web 和 CLI 模式加载不同 php.ini:用
php --ini(CLI)和phpinfo()(Web)分别看Loaded Configuration File路径 - 改了
php.ini-development这类模板文件,实际加载的是php.ini(通常无后缀) - Nginx + PHP-FPM 环境:必须重启
php-fpm进程,只 reload Nginx 没用 - Docker 容器:改了宿主机的 php.ini?没用。必须进容器改 /usr/local/etc/php/php.ini 并重建容器,或用
docker exec重启 php-fpm - Apache + mod_php:改完要
systemctl restart apache2(Debian/Ubuntu)或httpd(CentOS)
真正麻烦的不是设不对,而是设得“半对”:比如开发机用 "Asia/Shanghai" 测试通过,上线后服务器系统时区是 UTC,且 php.ini 里没配,结果所有 new DateTime() 默认按 UTC 解析字符串 —— 对象一创建就偏了 8 小时,后面怎么算都补不回来。



















