Php 使用不正确时区的日期时间

Php 使用不正确时区的日期时间,php,datetime,timezone,Php,Datetime,Timezone,在我的应用程序中,我试图计算到格林尼治标准时间午夜(英国时间)的剩余时间。目前我正在这样做: $now = new DateTime(); $timeToMidnight = $now->setTimezone(new DateTimeZone('Europe/London'))->diff(new DateTime('tomorrow'))->format('%h hours, %i minutes and %s seconds'); 代码正在运行,但是似乎落后了一个小时(

在我的应用程序中,我试图计算到格林尼治标准时间午夜(英国时间)的剩余时间。目前我正在这样做:

$now = new DateTime();
$timeToMidnight = $now->setTimezone(new DateTimeZone('Europe/London'))->diff(new DateTime('tomorrow'))->format('%h hours, %i minutes and %s seconds');
代码正在运行,但是似乎落后了一个小时(使用GMT-1)。目前时间为晚上11:49,输出如下:

1小时10分36秒
我已经仔细检查了我的
php.ini
,我还将时区设置为GMT:

date.timezone=欧洲/伦敦
通过检查
phpinfo()
也可以确认这一点


有什么好处?为什么我的应用程序没有使用正确的时区?

我在Linux PHP 5.5.5上测试了这个问题,在
PHP.ini
中将
Europe/London
设置为时区。实际上我也把时钟拨慢了四个小时。我用来复制的最小代码是:

$d = new DateTime('tomorrow');
echo $d->format('c e');
(正确的)输出为:

2013-10-27T00:00:00+01:00欧洲/伦敦
我将查找PHP中的错误或时区数据中的错误。为了找出答案,我们将看看今晚伦敦午夜的其他节目。告诉我这应该有一个Unix时间戳138228400。为了再次检查时间戳,我使用PHP运行:

$d = new DateTime('27-10-2013');
echo $d->format('U'); 
它还返回了138 282 8400。那么,让我们看看它应该显示什么

TZ=欧洲/伦敦日期--date=“@138228400”+%c
结果是:

太阳2013年10月27日英国夏令时上午12:00:00
对!这很好。让我们看看PHP

我运行了示例代码以及
date
命令,得到了以下输出:

1小时29分53秒
2013年10月26日星期六21:30:07 UTC
2013年10月26日星期六22:30:07英国夏令时
当然,这是正确的

我认为在这一点上,我们已经排除了tzdata和PHP中的bug,并且需要考虑配置问题和程序员的期望


首先,正如我前面提到的,欧洲/伦敦不是UTC,它没有夏季时间的概念,因此每年不会改变两次。由于它不会导致此类问题,因此,服务器在UTC上运行是一种最佳做法,而不管其用户所在的时区是什么,程序在内部使用UTC,然后转换为本地时区,仅用于显示和用户输入

我最好的猜测是,服务器运行的PHP实际上设置为使用UTC,而不是欧洲/伦敦作为其默认时区。这是我可以重现您的问题的唯一配置。该试验的结果如下:

date.timezone=UTC
2小时24分36秒
2013年10月26日星期六21:35:24 UTC
2013年10月26日星期六22:35:24英国夏令时
今后,您应该尽可能使用UTC(以及Unix时间戳),并在处理用户输入时尽早转换为本地时间,在显示输入时尽可能晚。类似这样的边缘情况(夏季即将结束)可能是一个例外,但您必须格外小心,以确保在构建每个新的
DateTime
对象时,都设置了正确的时区,同时也要注意它们会出现类似这样的问题

另请参见庞大且信息丰富的


最后,为了“修复”您的代码,让我们这样做:

$tz = new DateTimeZone('Europe/London');
$now = new DateTime('now', $tz);
$midnight = new DateTime('tomorrow', $tz);
$timeToMidnight = $now->diff($midnight);
echo $timeToMidnight->format('%h hours, %i minutes and %s seconds');

英国的时钟从英国夏令时改为格林尼治时间tonight@MarkBaker,今天的钟不是倒着走,而是倒着走吗?我很确定这要到凌晨2点才会发生。我的意思是现在伦敦的时间是英国夏季午夜2分钟后。。。格林尼治标准时间是晚上11点2分,所以离格林尼治标准时间(UST)午夜还有58分钟。记住,欧洲/伦敦和UTC是不一样的!UTC没有夏季时间的概念。