Yii2应用级timeZone配置需在config/web.php和config/console.php中分别设置'timeZone' => 'Asia/Shanghai'及'components.formatter.timeZone' => 'Asia/Shanghai',因Web与Console入口独立加载配置,漏配会导致时间戳偏差。

Yii2 应用级 timeZone 配置写在哪
Yii2 的时区必须在应用启动早期就生效,否则 date()、DateTime 等函数仍按服务器默认时区解析。最可靠的位置是 config/web.php(或 config/main.php)的 'components' 下的 'formatter' 和全局 'timeZone' 两项都要设,但作用不同:
-
'timeZone'是 PHP 运行时默认时区(影响date()、strtotime()、未显式指定时区的DateTime) -
'formatter.timeZone'仅影响Yii::$app->formatter->asDate()等格式化方法的输出逻辑
所以两者建议保持一致,例如中国标准时间:
'timeZone' => 'Asia/Shanghai',
'components' => [
'formatter' => [
'timeZone' => 'Asia/Shanghai',
],
],
为什么设了 timeZone 还显示 UTC 时间
常见原因是数据库字段类型或查询方式绕过了 Yii 的时区控制:
-
DATETIME字段本身不存时区,读取后直接转为DateTime对象时,若没指定时区,PHP 默认用date_default_timezone_get()—— 但这个值可能被中间件、扩展或php.ini覆盖,和 Yii 配置无关 - ActiveRecord 查询返回的
DateTime对象,其时区取决于yii\db\Schema::typecast()行为,而该行为依赖底层 PDO 的PDO::ATTR_EMULATE_PREPARES和 MySQL 的time_zone设置 - MySQL 服务端时区(
SELECT @@global.time_zone)若为+00:00或SYSTEM(且系统时区是 UTC),NOW()、CURDATE()等函数也返回 UTC 时间
验证方式:在控制器里加一行 var_dump(date_default_timezone_get(), Yii::$app->timeZone);,确保两者一致且非 UTC。
Asia/Shanghai 和 PRC 有什么区别
PHP 支持的时区标识符中,PRC 是旧别名,已废弃;Asia/Shanghai 是 IANA 标准名称,推荐使用:
-
PRC在某些 PHP 版本(尤其是旧版 Alpine 容器)中可能无法识别,抛出DateTimeZone::__construct(): Unknown or bad timezone (PRC) -
Asia/Shanghai兼容所有现代 PHP 版本,且明确对应中国标准时间(含夏令时历史规则,虽然中国已多年不实行) - 不要用
GMT+8或Etc/GMT-8:后者符号反直觉(Etc/GMT-8实际是 UTC+8),且不支持夏令时切换
命令行环境下时区配置容易被忽略
Web 请求走 web.php,但 console 命令(如 yii migrate)加载的是 config/console.php。如果只在 web.php 设了 timeZone,console 里 date() 仍可能用系统默认时区:
- 必须在
config/console.php中同样设置'timeZone'和'components.formatter.timeZone' - 或者统一抽到
config/common.php,再在web.php和console.php中require它 - 运行
php yii help后检查输出的当前时间是否符合预期,是快速验证 CLI 时区是否生效的方法
时区不是“设一次就全局透传”的配置,每个应用入口(web、console、甚至 REST API 的独立入口)都得单独确认。漏掉 console 配置,最容易导致定时任务生成的时间戳错 8 小时。


















