php时区问题,应该如何解决

481 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情

php时区问题

我们所说的任何一个时间,都是在确定了一个时区的前提下,不然这个时间就是错的。比如:新闻联播 常说“北京时间 2017-3-29 18:34:38 ……”,“美国当地时间2月18日上午在德克萨斯州发生一起……”,如果不先说明时区,那么没人能确定它是中国的时间还是美国的时间,到底什么时候发生的,不知道时区,那这个时间就没有存在的意义了。

先看一个例子:

<?php

$a = time();
$a_ = date('Y-m-d H:i:s', $a);
echo date_default_timezone_get() . '<br />';
echo $a . '<br />';
echo $a_ . '<br />';
echo strtotime($a_) . '<br />';

date_default_timezone_set('PRC');

$b = time();
$b_ = date('Y-m-d H:i:s', $b);
echo date_default_timezone_get() . '<br />';
echo $b . '<br />';
echo $b_ . '<br />';
echo strtotime($b_) . '<br />';

echo $b - $a;

// 输出

UTC
1490783813
2017-03-29 10:36:53
1490783813
PRC
1490783813
2017-03-29 18:36:53
1490783813
0

可见在php中time()与系统的时区设置无关,其他的时间函数则与时区有关,受时区影响。

所以解决国际化网站很好的做法就是所有时间都存time()时间戳就好了,具体显示时则根据不同的时区来进行自动的转换输出就可以了。

注意: SERVER[REQUESTTIMEFLOAT]_SERVER['REQUEST_TIME_FLOAT'] 和 _SERVER['REQUEST_TIME'] 与time一样,同样的不受时区影响,都是 返回 Unix 时间戳 (自 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00) 到当前时间的秒数。 )


PHP中与时区无关的函数

  1. time(): 标准时间戳, 指返回自从Unix纪元 (格林威治时间1970-01-01 00:00:00) 到当前GMT标准时间的秒数, 与PHP系统设置的时区无关。
  2. gmdate(): 某GMT标准时间的"自定义格式"时间, 跟php系统设置的时区无关.

与其说是与时区无关,不受时区影响,不如说是零时区,它本身就是零时区,不可被修改。

mysql中的时区问题

数据库如何存储时间?你真的知道吗?

DateTime 类型是没有时区信息的(时区无关),DateTime 类型保存的时间都是当前会话所设置的时区对应的时间。这样就会有什么问题呢?当你的时区更换之后,比如你的服务器更换地址或者更换客户端连接时区设置的话,就会导致你从数据库中读出的时间错误。不要小看这个问题,很多系统就是因为这个问题闹出了很多笑话。

Timestamp 和时区有关。Timestamp 类型字段的值会随着服务器时区的变化而变化,自动换算成相应的时间,说简单点就是在不同时区,查询到同一个条记录此字段的值会不一样。

PS:DateTime 这种现象应该正是 时区有关 才对