Magento 的时区和时间(原理)

Magento 的时间存储使用的是 MySQL 的 TIMESTAMP 。TIMESTAMP 在数据库内部是以 UTC 时间存储的,在取回显示时却是依据当前时区进行转化的。

比如当前时区是UTC,存入UTC时间00:00,你看到的是00:00,但当你将时区改成UTC+8以后,你看到的时间将会是08:00,存储的值一直没有变,但是你看到的不一样了。关于这个请参考MySQL 文档: The DATE, DATETIME, and TIMESTAMP Types

重点摘要:

MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time. The time zone can be set on a per-connection basis. As long as the time zone setting remains constant, you get back the same value you store. If you store a TIMESTAMP value, and then change the time zone and retrieve the value, the retrieved value is different from the value you stored. This occurs because the same time zone was not used for conversion in both directions. The current time zone is available as the value of the time_zone system variable.

Magento 的系统使用的都是 UTC 时间,两个地方有体现:

第一处是 PHP 的时区设置,在 Magento 2 的入口文件 app/bootstrap.php 中有设置date_default_timezone_set('UTC');
了解更多可参考:PHP 的时间和时区

第二处是与数据库连接的时候,gento\Framework\DB\Adapter\Pdo\Mysql::_connect

$this->_connection->query("SET time_zone = '+00:00'");

下面是一个关于 MySQL 的时区例子,为了帮助理解的。

MySQL 的 time_zone 默认是 SYSTEM,我将他改为 UTC

SET GLOBAL time_zone = '+00:00';

查看时区

show variables like '%time_zone%';

然后我建立了一个表:

name 描述
id 自增
create_time timestamp 默认CURRENT_TIMESTAMP

然后插入几行数据

id create_time
1 2016-10-12 03:23:31
2 2016-10-12 03:28:16

因为我的时区设置的是 UTC ,所以本地时间是 2016-10-12 11:23

我们来用php 取出时间看看

$servername = "localhost";
$username = "root";
$password = "";
$sql = "";
$conn = new PDO("mysql:host=$servername;dbname=test", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->exec("SET CHARACTER SET UTF8"); 

// 注意这里
// $conn->exec("SET time_zone = '+08:00'");

$sql="select * from test.time";
$sth = $conn->query($sql);
while($row = $sth->fetch()){
    echo "id:".$row['id']."<br />";
    echo "create_time:".$row['create_time']."<br />";
}

我们得到的结果是这样的:

id:1
create_time:2016-10-12 03:23:31
id:2
create_time:2016-10-12 03:27:37

看这个时间是UTC 的时间吧。然后我们将上面的注释去掉,得到的将会是本地时间:

id:1
create_time:2016-10-12 11:23:31
id:2
create_time:2016-10-12 11:27:37

Magento 2 当前的版本中关于cron 的时间有 Bug,时间有误,详情请见 https://github.com/magento/magento2/issues/4237

发表评论

电子邮件地址不会被公开。 必填项已用*标注