记一次调试经历:timezone

在怀疑程序出问题之前,先怀疑是人为的问题。


现在是北京时间 2017-12-15 下午两点半,同事告诉我她遇到了一个奇葩的 Bug,本地和测试环境配置一样,都是设置成美西时间,但是 PHP 里面输出当前日期的时候,本地环境是 2017-12-14,测试环境是 2017-12-15,简单来说就是:测试环境的时区设置出问题了。

date_default_timezone_set("America/Los_Angeles");

第一反应是肯定又是运维配置的问题,但是还是谷歌搜了一下 “date_default_timezone_set() not work”,看到有人说如果 php.ini 里面的 date.timezone 设置要比 date_default_timezone_set() 优先级高,于是尝试了一下使用 ini_set() 来设置时区。

ini_set("date.timezone", "America/Los_Angeles");

还是不行,既然网上找不到正确的解决方法,不妨来看看 PHP 官方文档。date_default_timezone_get() 的文档里面明确说明了 date_default_timezone_set() 的优先级是最高的,然后才是 date.timezone 配置,网上的某些答案真的是误人子弟。

echo date_default_timezone_get();

既然怀疑时区设置有问题,那么不妨查看一下当前时区,America/Los_Angeles,居然设置成功了!设置成功了!设置成功了!时区设置成功了,但是输出的时间不对,会是哪里的问题呢?百思不得其解,于是我把脑洞开到最大:难道是 timezone database 不对?

$timezone = new DateTimeZone("America/Los_Angeles");
$transitions = $timezone->getTransitions();
print_r($transitions);
[146] => Array
        (
            [ts] => 1509872400
            [time] => 2017-11-05T09:00:00+0000
            [offset] => -28800
            [isdst] =>
            [abbr] => PST
        )

使用 DateTimeZone::getTransitions 查看 America/Los_Angeles 时区,可以看到从 2017-11-05 起美西开始执行 PST(太平洋标准时间)。offset 是 -28800 / (60 * 60) = -8h, 也就是 UTC-8,看起来没有任何问题。那么问题到底出在哪里呢?

就在我以为暂时找不到原因了的时候,突然想起来我之前好像遇到过同样的问题。于是在测试服务器上查看了一下当前时间:

TZ='America/Los_Angeles' date

现在是北京时间 2017-12-15 下午三点半,问题终于解决了,date_default_timezone_set(“America/Los_Angeles”) 没有问题,ini_set(“date.timezone”, “America/Los_Angeles”) 也没有问题。真正的问题是,服务器上的被设置为美西时间 2017-12-15 下午三点半。

是的,在北京时间 2017-12-15 下午三点半,我们的测试服务器时间被设置成了美西时间 2017-12-15 下午三点半。而且我们的运维总监一直怀疑是代码问题,从来没有怀疑过是自己服务器配置问题。所以我有两点经验要和大家分享:1. 在怀疑程序出问题之前,先怀疑是人为的问题。2. 在怀疑别人之前,先怀疑是自己的问题。3. 那些一出问题就跳出来指责别人的人,大家要首先怀疑他。


参考:

http://php.net/manual/en/function.date-default-timezone-set.php

http://php.net/manual/en/datetime.configuration.php#ini.date.timezone

http://php.net/manual/en/function.date-default-timezone-get.php

http://php.net/manual/en/timezones.php

http://php.net/manual/en/datetimezone.gettransitions.php

 316 total views