繁体   English   中英

PHP DateTime-> diff()无法正常工作

[英]PHP DateTime->diff() doesn't work correctly

我遇到了一个有趣的案例,与DateTime类的diff()方法有关。

如果我尝试计算两个月之间的差异,比如

$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%m');

结果我得到0

为什么会这样?

print_r的公司:

$ datetime1:

DateTime Object ( [date] => 2019-06-01 00:00:00.000000 
[timezone_type] => 3 [timezone] => Europe/Berlin )

$ DATETIME2:

DateTime Object ( [date] => 2019-07-01 00:00:00.000000 
[timezone_type] => 3 [timezone] => Europe/Berlin )

$间隔:

DateInterval Object ( [y] => 0 [m] => 0 [d] => 30 [h] => 0 [i] => 0 [s] => 0 [f] => 0 
[weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 
[invert] => 0 [days] => 30 [special_type] => 0 [special_amount] => 0
 [have_weekday_relative] => 0 [have_special_relative] => 0 )

PHP中的时区和日期处理存在很大的不一致

这似乎是一个错误( 根据此评论 ,日期时间格式被强制为GMT *偏移)。

*(但强迫GMT似乎与下面代码建立的结果不一致)

将服务器时区值设置为任何时区不会影响此脚本时区异常。

以下两个案例显示了不同时区的情况:


情况1:

以下代码将输出每个时区的结果列表:

$tzList = DateTimeZone::listIdentifiers(DateTimeZone::ALL);

print "Current Zone:". print_r(ini_get('date.timezone'),true)."<br>\n<BR>\n";

foreach($tzList as $tzRow) {
    $tz = new DateTimeZone($tzRow);
    //$tz = null;
    $datetime1 = new \DateTime('June 2019', $tz);
    $datetime2 = new \DateTime('July 2019', $tz);
    $interval = $datetime1->diff($datetime2, false);
    echo $interval->format('%a %m') . PHP_EOL. " :: ";

    print print_r($datetime1->getTimezone(),true)."<BR>";
}

此列表输出的结果显示高(~60%)的速率为0 ,其余为1个月。

请看这里: http//sandbox.onlinephpfunctions.com/code/b18ba13deb94d112b12630a12265363fb6c7670b


案例2:

在创建对象后设置时区会产生一致的答案(尽管不正确)

$tzList = DateTimeZone::listIdentifiers(DateTimeZone::ALL);

print "Current Zone:". print_r(ini_get('date.timezone'),true)."<br>\n<BR>\n";

foreach($tzList as $tzRow) {
    //$tz = new DateTimeZone($tzRow);
    $tz = null;
    $datetime1 = new \DateTime('June 2019', $tz);
    $datetime2 = new \DateTime('July 2019', $tz);
    $datetime1->setTimezone(new DateTimeZone($tzRow));
    $datetime2->setTimezone(new DateTimeZone($tzRow));
    $interval = $datetime1->diff($datetime2, false);
    echo $interval->format('%a %m') . PHP_EOL. " :: ";

    print print_r($datetime1->getTimezone(),true)."<BR>";
}

这些输出全部在 30天内生成; 所有 0个月的差异。

请参阅此处的代码: http//sandbox.onlinephpfunctions.com/code/7bcc62f4e36f41df71b9cb928de75a53f233d9fd


因此,如果您希望使用有时正确的结果或普遍不正确的rbut一致结果,通过在DateTime对象中建立Timezone值进行设置这是您的选择。


可能解决方案

如果服务器时区正确设置为UTC“正确”时区(在Case 1中自然返回“1”月),则上面的CASE 2在给予DateTime对象的所有时区中一致地工作。

你可以通过添加时区来尝试吗?

$timezones = [
    'UTC',
    'Europe/Berlin',
    'America/Belize',
    'Asia/Hong_Kong',
];

foreach ($timezones as $timezone) {
    $tz = new DateTimeZone($timezone);
    $datetime1 = new \DateTime('June 2019', $tz);
    $datetime2 = new \DateTime('July 2019', $tz);
    $interval = $datetime1->diff($datetime2);
    echo str_pad($timezone, 20, ' ').' '.$interval->format('months: %M,  day: %D,  days: %a') . PHP_EOL;
}

结果:

UTC                  months: 01,  day: 00,  days: 30
Europe/Berlin        months: 00,  day: 30,  days: 30
America/Belize       months: 01,  day: 00,  days: 30
Asia/Hong_Kong       months: 00,  day: 30,  days: 30

问题出在您的时区。

有一个文章,解释一下这里

看这个例子:

<?php

echo "----- Europe/Berlin -----\n";
date_default_timezone_set('Europe/Berlin'); 
$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
print_r($datetime1);
print_r($datetime2);

$interval = $datetime1->diff($datetime2);
print_r($interval);

echo "%m = " . $interval->format('%m') . PHP_EOL;
echo "%a = " . $interval->format('%a') . PHP_EOL;
echo "%s = " . $interval->format('%s') . PHP_EOL;


echo "\n\n\n----- America/Sao_Paulo -----\n";
date_default_timezone_set('America/Sao_Paulo'); 
$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
print_r($datetime1);
print_r($datetime2);

$interval = $datetime1->diff($datetime2);
print_r($interval);

echo "%m = " . $interval->format('%m') . PHP_EOL;
echo "%a = " . $interval->format('%a') . PHP_EOL;
echo "%s = " . $interval->format('%s') . PHP_EOL;

并输出:

$ php date_diff.php 
----- Europe/Berlin -----
DateTime Object
(
    [date] => 2019-06-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => Europe/Berlin
)
DateTime Object
(
    [date] => 2019-07-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => Europe/Berlin
)
DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => 30
    [h] => 0
    [i] => 0
    [s] => 0
    [f] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 30
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)
%m = 0
%a = 30
%s = 0



----- America/Sao_Paulo -----
DateTime Object
(
    [date] => 2019-06-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => America/Sao_Paulo
)
DateTime Object
(
    [date] => 2019-07-01 00:00:00.000000
    [timezone_type] => 3
    [timezone] => America/Sao_Paulo
)
DateInterval Object
(
    [y] => 0
    [m] => 1
    [d] => 0
    [h] => 0
    [i] => 0
    [s] => 0
    [f] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 30
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)
%m = 1
%a = 30
%s = 0

在我的时区$interval->format('%m'); 是1。

您可以在日期上设置时区以计算它们之间的差异。

$datetime1 = new \DateTime('June 2019', new DateTimeZone('UTC'));
$datetime2 = new \DateTime('July 2019', new DateTimeZone('UTC'));
$interval = $datetime1->diff($datetime2);
print_r($interval);
echo "%m = " . $interval->format('%m') . PHP_EOL;

$ php date_diff.php 
DateInterval Object
(
    [y] => 0
    [m] => 1
    [d] => 0
    [h] => 0
    [i] => 0
    [s] => 0
    [f] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 30
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)
%m = 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM