有人可以向我解释为什么从DateTime对象添加和减去相同的DateInterval导致不同的日期? 查看小时数:当我减去间隔时,从20:00到19:00,但是当我添加间隔时,它仍然是19:00。
$date = new DateTime("2015-04-21 20:00", new DateTimeZone('Europe/Berlin'));
$days = 28;
$minutes = $days * 24 * 60;
$interval = new DateInterval("PT{$minutes}M");
var_dump($date);
$date->sub($interval);
var_dump($date);
$date->add($interval);
var_dump($date);
结果:
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-04-21 20:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-03-24 19:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-04-21 19:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
在我看来$date->sub($interval);
因为夏令时差异而在20:00到19:00之间改变小时(它与其他日期一样有效,即2015-05-21 20:00),但是$date->add($interval);
并不适用DTS。这可能是个错误吗?
答案 0 :(得分:1)
使用$interval->invert
似乎可以解决问题:
$date = new DateTime("2015-04-21 20:00", new DateTimeZone('Europe/Berlin'));
$days = 28;
$minutes = $days * 24 * 60;
$interval = new DateInterval("PT{$minutes}M");
$interval->invert = 1;
var_dump($date);
$date->add($interval);
var_dump($date);
$date->sub($interval);
var_dump($date);
结果是:
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-04-21 20:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-03-24 19:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2015-04-21 20:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
答案 1 :(得分:0)
确实是因为夏令时。例如,如果您将时区更改为“America / Los_Angeles”,那么在给定的时间内会很好,因为在洛杉矶,时间在3月初发生了变化。 您也可以使用相同的时区进行测试,将您的日期设置在11月初,然后您将看到28天前的21:00。
答案 2 :(得分:0)
我最近在这段代码中遇到了类似的问题:
private function convertSecondsToInterval($value)
{
$dt1 = new \DateTime();
$dt2 = clone $dt1;
$dt2->add(new \DateInterval('PT'. $value . 'S'));
return $dt2->diff($dt1);
}
在2018-03-24到2018-03-25之间的夜晚(从CET到法国CEST的时区变化),我注意到一个奇怪的行为:DateInterval结果比预期的少1小时。这是因为默认情况下,DateTime对象位于Europe / Paris时区。因此,例如在2018-03-24 20:00:00增加7小时时,我将时区变化(+01:00变为+02:00),导致总和比预期少1小时。
实施的解决方案是使用UTC时区初始化DateTime对象以跳过日光变换问题。
private function convertSecondsToInterval($value)
{
$dt1 = new \DateTime('now', new \DateTimeZone('UTC'));
$dt2 = clone $dt1;
$dt2->add(new \DateInterval('PT'. $value . 'S'));
return $dt2->diff($dt1);
}