浅谈PHP时区转换以及数据库存标准时间UTC的意义

今天做一个英国的项目,里面涉及到夏令时和时区的转换,以前一直没注意过这方面,所以特地花时间补了补课。

GMT(Greenwich Mean Time) – 格林尼治标准时间,格林威治平均时间:根据本初子午线太阳时再根据地球特点等因素调整的时间

UTC(Universal Time Coordinated) – 协调世界时:在GMT的基础上再根据TAI调整得到的时间

我们一般认为GMT和UTC是一样的,都与英国伦敦的本地时相同。但是实际使用时也会有不同,伦敦的标准timezone是Europe/London,就像上海的标准timezone是Asia/Shanghai一样。Europe/London是有夏令时的,一般的类库比如DateTime,Carbon都会对这个进行计算,如果是UTC,就不会计算了。

如果项目是一个多国共用的项目,就肯定要面临参数统一的问题了,其中尤为重要的就是时间上的统一。举例:因为你这里的早上8点,别人可能才凌晨0点。要根据不同用户的所在地,展现不同的时间。

从数据库层面来讲,有两个字段是必须的,timezone和utc_time,所有的时间都经处理后,转换成UTC时间入库,所有的用户都有自己的timezone,那么,我们这个项目就能容纳更多的用户。

上面就是需求,下面直接落地讲解决办法:

#时区转换
//这里用到了Carbon的扩展,也可以自己用date和strtotime去做,这里不展开了
$time = '2019-09-27T18:54:59';//这里的T也可以用空格替换
$time_zone='Europe/London';
//获取时区和UTC时间的差,正负代表加减
$time_hours = timezone_offset_get( timezone_open( $time_zone ), new \DateTime() )/3600;
//这里用前面用-来将时间补到UTC+0
$time =(new Carbon($time))->addHours(-$time_hours)->toDateTimeString();

其实除了上述的解决方法,还用了另一种,是直接将timezone字段存成了数字,也就是正负的小时差,直接用,不过感觉还是上面更规范。

#这是根据时差获取数据库查询条件的一个帮助方法,因为数据库存的UTC所以查询时也要转换一下条件
function utc_date_format_now($offset){
        $start_time=date('Y-m-d H:i:s',strtotime('today -'.$offset.' hour'));
        $end_time=date('Y-m-d H:i:s',strtotime('tomorrow -'.$offset.' hour'));
        return [$start_time,$end_time];

    }

enjoy it.

打赏作者

发表评论

电子邮件地址不会被公开。