应统一设置PHP、框架、CLI及数据库时区为Asia/Shanghai:在public/index.php顶部调用date_default_timezone_set('Asia/Shanghai'),同步配置config/app.php中default_timezone、php.ini中date.timezone,并修正MySQL的time_zone为+08:00,确保各环节时区一致。

PHP框架项目上线后日志时间比实际快8小时、定时任务执行时间错乱、数据库查出的时间和前端显示不一致——这些问题八成是时区配置没对齐,不是代码逻辑问题,而是框架、CLI、Web三端默认时区各自为政。
确认当前时区是否生效
先别急着改配置,用一行命令验明正身:php -r "echo date_default_timezone_get();"。
如果输出是 【UTC】 或空字符串,说明PHP根本没拿到有效时区;如果输出是 【PRC】,立刻停手——这个值在PHP 8.1+已废弃,会触发警告且行为不可靠。
注意:这个命令测的是CLI模式下的时区,和你在浏览器里看到的Web请求结果可能完全不同。
立即学习“PHP免费学习笔记(深入)”;
Laravel项目统一设时区
别在public/index.php里硬写date_default_timezone_set(),这会和框架内部时区管理冲突,导致Carbon和原生date()返回不同结果。
第一步:打开config/app.php,找到'timezone' => 'UTC'这一行。
第二步:把值改成'timezone' => 'Asia/Shanghai',保存文件。
第三步:清空配置缓存:运行php artisan config:clear,否则新设置不会加载。
这一步做完,所有通过now()、Carbon::now()、date()生成的时间都按北京时间计算,包括日志、模型时间戳、队列任务调度时间。
ThinkPHP项目强制覆盖时区
ThinkPHP 6.x 默认不读取php.ini的date.timezone,必须显式声明。
方法一:在app/common.php或public/index.php最顶部(【必须在任何use或new之前】)插入:
date_default_timezone_set('Asia/Shanghai');
方法二:在app/config/app.php中添加:
'default_timezone' => 'Asia/Shanghai',
注意:方法二仅在TP6.1+支持,旧版本无效;若同时用了方法一和方法二,以方法一为准,因为它是运行时最早执行的。
CLI脚本单独补时区(关键!)
网页访问一切正常,但php artisan schedule:run或php think timer:run跑出来的日志时间还是错的?这是CLI模式压根没读你的框架配置。
检查CLI当前时区:php -r "echo date_default_timezone_get();"。
如果结果不是Asia/Shanghai,就进到每个可独立执行的脚本头部加一行:
date_default_timezone_set('Asia/Shanghai');
例如:在app/Console/Commands/BackupCommand.php的handle()方法第一行,或database/seeders/DatabaseSeeder.php开头。
这一步不能省——框架配置管不到CLI入口,而crontab调用的就是CLI。
Docker环境持久化时区
容器每次重启都回UTC?别信ENV TZ=Asia/Shanghai,PHP不读这个变量。
在Dockerfile里加两行:
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
ENV TZ=Asia/Shanghai
再在PHP配置段明确写死:
RUN echo "date.timezone = Asia/Shanghai" >> /usr/local/etc/php/php.ini
这样Web和CLI都从同一份php.ini加载,且系统级时区也对齐,避免DateTime构造时因系统时区干扰产生隐式偏移。



















