php日期差异在PHP 8(从7)中的表现不同,克隆日期
我有一个WordPress插件,我们正在将托管从PHP 7升级到8。我们具有从会话中的序列化日期字符串创建DateTime对象的功能,并将其与现在使用DateTime diff
函数进行比较。 。在PHP 7中,这项工作(例如1秒)。在PHP 8中,它为我们提供了一年的减去,加上11个月,29天23小时,零(!)分钟和1秒!
我使用PHP CLI运行以下脚本。
<?php
$d = new DateTime();
echo '$d->format("r"): ' . $d->format('r') . "\n";
sleep(1);
$n = new DateTime( $d->format('r') );
$diff_d = $d->diff( new DateTime() );
$diff_n = $n->diff( new DateTime() );
echo "\n";
echo 'print_r($diff_d)' . "\n";
print_r($diff_d);
echo "\n";
echo 'print_r($diff_n)' . "\n";
print_r($diff_n);
echo "\n";
echo 'd' . "\n";
print_r($d);
echo "\n";
echo 'n' . "\n";
print_r($n);
我可以看到如何解决问题的特定实例(我们可能应该将UNIX时间戳放入会话中,而不是日期字符串)。但是我担心我不能再依赖日期diff函数,因为它已使用了其他局部位置,或者是从更令人担忧的字符串中创建dateTime对象。
php 7上的输出
上面的脚本在foo.php中。在CentOS 7服务器上运行。首先,我显示PHP版本,然后运行脚本。这个输出对我来说看起来很正确。
$ php --version
PHP 7.3.33 (cli) (built: Nov 16 2021 11:18:28) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.33, Copyright (c) 1998-2018 Zend Technologies
$ php -f foo.php
$d->format("r"): Tue, 24 May 2022 17:35:16 +0300
print_r($diff_d)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.000213
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
print_r($diff_n)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.41655
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
d
DateTime Object
(
[date] => 2022-05-24 17:35:16.416318
[timezone_type] => 3
[timezone] => Europe/Helsinki
)
n
DateTime Object
(
[date] => 2022-05-24 17:35:16.000000
[timezone_type] => 1
[timezone] => +03:00
)
php 8上的输出
上面的脚本在foo.php中。还可以在CentOS 7服务器上运行。首先,我显示PHP版本,然后运行脚本。这个输出对我来说看起来很错。
$ php --version
PHP 8.1.6 (cli) (built: May 11 2022 01:14:18) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.1.6, Copyright (c) Zend Technologies
$ php -f foo.php
$d->format("r"): Tue, 24 May 2022 17:35:05 +0300
print_r($diff_d)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.001302
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
print_r($diff_n)
DateInterval Object
(
[y] => -1
[m] => 11
[d] => 29
[h] => 23
[i] => 0
[s] => 1
[f] => 0.363031
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
d
DateTime Object
(
[date] => 2022-05-24 17:35:05.361724
[timezone_type] => 3
[timezone] => Europe/Helsinki
)
n
DateTime Object
(
[date] => 2022-05-24 17:35:05.000000
[timezone_type] => 1
[timezone] => +03:00
)
即使出于某种原因,即使是一年,然后向前往前一年,那应该不是59分钟,而不是零吗?
它似乎已连接到从字符串创建的DateTime对象(因为将原始DateTime对象差异为现在是可以的)。但是,当我倾倒$ d
和$ n
时,唯一的区别是地理时区与数值偏移量和缺乏毫秒的偏移 - 但它们彼此表示相同(据我所知,达到毫秒。
有人可以解释为什么会发生这种情况,所以我知道我应该对其其余的代码感到担忧?
I have a WordPress plugin and we are upgrading our hosting from PHP 7 to 8. We have function which creates a DateTime object from a serialised date string in the session and compares it to now using the DateTime diff
function. In PHP 7 this works (gives e.g. 1 second). In PHP 8 it gives us minus one year plus 11 months, 29 days, 23 hours, zero(!) minutes and 1 second!
I am running the following script using the PHP CLI.
<?php
$d = new DateTime();
echo '$d->format("r"): ' . $d->format('r') . "\n";
sleep(1);
$n = new DateTime( $d->format('r') );
$diff_d = $d->diff( new DateTime() );
$diff_n = $n->diff( new DateTime() );
echo "\n";
echo 'print_r($diff_d)' . "\n";
print_r($diff_d);
echo "\n";
echo 'print_r($diff_n)' . "\n";
print_r($diff_n);
echo "\n";
echo 'd' . "\n";
print_r($d);
echo "\n";
echo 'n' . "\n";
print_r($n);
I can see how to fix the particular instance of the problem (we should probably be putting a Unix Timestamp into the session, not a date string anyway). But I'm worried I can't rely on the date diff function anymore as it's used other places - or is it creating a DateTime object from a string which is even more worrying.
Output on PHP 7
The script above is in foo.php. Running on a CentOS 7 server. First I show PHP version then run the script. This output looks correct to me.
$ php --version
PHP 7.3.33 (cli) (built: Nov 16 2021 11:18:28) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.33, Copyright (c) 1998-2018 Zend Technologies
$ php -f foo.php
$d->format("r"): Tue, 24 May 2022 17:35:16 +0300
print_r($diff_d)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.000213
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
print_r($diff_n)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.41655
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
d
DateTime Object
(
[date] => 2022-05-24 17:35:16.416318
[timezone_type] => 3
[timezone] => Europe/Helsinki
)
n
DateTime Object
(
[date] => 2022-05-24 17:35:16.000000
[timezone_type] => 1
[timezone] => +03:00
)
Output on PHP 8
The script above is in foo.php. Also running on a CentOS 7 server. First I show PHP version then run the script. This output looks very wrong to me.
$ php --version
PHP 8.1.6 (cli) (built: May 11 2022 01:14:18) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.1.6, Copyright (c) Zend Technologies
$ php -f foo.php
$d->format("r"): Tue, 24 May 2022 17:35:05 +0300
print_r($diff_d)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 0
[s] => 1
[f] => 0.001302
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
print_r($diff_n)
DateInterval Object
(
[y] => -1
[m] => 11
[d] => 29
[h] => 23
[i] => 0
[s] => 1
[f] => 0.363031
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
d
DateTime Object
(
[date] => 2022-05-24 17:35:05.361724
[timezone_type] => 3
[timezone] => Europe/Helsinki
)
n
DateTime Object
(
[date] => 2022-05-24 17:35:05.000000
[timezone_type] => 1
[timezone] => +03:00
)
Even if it, for some reason, is going back a year and then forward then shouldn't it be 59 minutes, not zero?
It seems to be connected to the DateTime object created from the string (in that diffing the original DateTime object against now is fine). But when I dump out $d
and $n
the only differences are geographical timezone vs numerical offset and the lack of milliseconds - but they are representing the same instant as each other (up to milliseconds) as far as I can see.
Can someone explain why this is happening, so I know how worried about the rest of the code I should be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
此问题似乎已经在最新的PHP版本8.1.10中解决了:
https://3v4l.org/gfeyu
This issue appears to have been fixed in the latest PHP version 8.1.10:
https://3v4l.org/GFeYu