PHP 日期差异在 PHP 8(从 7)中与克隆日期的行为不同

问题描述 投票:0回答:2

我有一个 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 时间戳放入会话中,而不是日期字符串)。但我担心我不能再依赖日期差异函数,因为它在其他地方使用 - 或者它是否从字符串创建 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
时,唯一的区别是地理时区与数字偏移量以及缺少毫秒 - 但据我所知,它们代表彼此相同的瞬间(最多毫秒)。

有人可以解释为什么会发生这种情况,以便我知道我应该多么担心其余的代码吗?

php datetime php-8 php-8.1
2个回答
0
投票

此问题似乎已在最新的 PHP 版本 8.1.10 中得到修复:

https://3v4l.org/GFeYu


-1
投票

我在 8.1.10 之前看到了这个关于 PHP 版本的错误,但我使用的是 PHP 版本 8.1.26

© www.soinside.com 2019 - 2024. All rights reserved.