本文介绍了PHP DateTime setTimezone 2038的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中使用DateTime转换所有日期(从UTC到欧洲/维也纳)。现在我的日期超过2038,并且无法获得正确的时间。

I convert all dates with DateTime (from UTC to Europe/Vienna) in my project. Now I have dates with above 2038, and cannot get the correct time.

示例代码:

$met = new DateTimeZone('Europe/Vienna');
$utc = new DateTimeZone('UTC');

$date = new DateTime('2043-08-04 08:00:00', $utc);
$date->setTimezone($met);
echo $date->format('Y-m-d H:i:s'); // Output is: 2043-08-04 09:00:00 instead of 2043-08-04 10:00:00

由于夏令时,在2043-03-29和2043-10-25之间需要从UTC计算+2小时。

Between 2043-03-29 and 2043-10-25 there is to calculate +2 hours from UTC, because of "summertime".

如果我将2043-08-04 08:00:00更改为2037-08-04 08:00:00我得到了正确的时间。

If I change 2043-08-04 08:00:00 to 2037-08-04 08:00:00 I get the correct time.

我知道这是2038年整数32位有问题,但是如何使用DateTime setTimezone函数使用整数64位?

I know it is a 2038 problem with integer 32 bit, but how I can use integer 64 bit with DateTime setTimezone function?

谢谢

推荐答案

如果该问题与32位Unix时间戳溢出有关,那么您将获得大约1970年的日期以及类似的完全错误的结果。但是,您的结果只有一个小时的时间。实际上,我们可以说 hour 是正确的,因为您只会得到错误的时区偏移量,因为您可以看到是否打印时区信息:

If the issue had anything to do with overflowing 32-bit Unix timestamps you'd be getting dates around 1970 and similar totally incorrect results. However, your result is only off by one hour. In fact, we could argue that the hour is correct since you're only getting a wrong time zone offset, as you can see if you print time zone information:

var_dump($date);
echo $date->format('c');



object(DateTime)#3 (3) {
  ["date"]=>
  string(26) "2043-08-04 09:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(13) "Europe/Vienna"
}
2043-08-04T09:00:00+01:00

这表明内部时间数据库缺少2043年的信息,也缺少本年的信息。我们可以通过以下进一步确认:

This suggests that the internal time database is missing information for year 2043 as it has for current year. We can further confirm this with:

$met = new DateTimeZone('Europe/Vienna');
var_dump($met->getTransitions((new DateTime('2017-01-01'))->format('U'), (new DateTime('2017-12-31'))->format('U')));
var_dump($met->getTransitions((new DateTime('2043-01-01'))->format('U'), (new DateTime('2043-12-31'))->format('U')));

此代码(显然需要在32位平台上运行)打印:

This code (that apparently needs to run on a 32-bit platforms) prints:

array(3) {
  [0]=>
  array(5) {
    ["ts"]=>
    int(1483225200)
    ["time"]=>
    string(24) "2016-12-31T23:00:00+0000"
    ["offset"]=>
    int(3600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CET"
  }
  [1]=>
  array(5) {
    ["ts"]=>
    int(1490490000)
    ["time"]=>
    string(24) "2017-03-26T01:00:00+0000"
    ["offset"]=>
    int(7200)
    ["isdst"]=>
    bool(true)
    ["abbr"]=>
    string(4) "CEST"
  }
  [2]=>
  array(5) {
    ["ts"]=>
    int(1509238800)
    ["time"]=>
    string(24) "2017-10-29T01:00:00+0000"
    ["offset"]=>
    int(3600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CET"
  }
}
array(1) {
  [0]=>
  array(5) {
    ["ts"]=>
    int(2303679600)
    ["time"]=>
    string(24) "2042-12-31T23:00:00+0000"
    ["offset"]=>
    int(3600)
    ["isdst"]=>
    bool(false)
    ["abbr"]=>
    string(3) "CET"
  }
}

正如PHP所知道的那样,2043年是从1月到12月的CET。

As PHP is aware of it, year 2043 is CET from January to December.

此信息来自:

PHP手册包括,以防它已经丢失了数据。如果不是这样,则可能是您不走运。

The PHP manual includes instructions to update it, in case it already has the missing data. If it doesn't, you're probably out of luck.

这篇关于PHP DateTime setTimezone 2038的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 12:49