我遇到两个Datetime不同的问题。以下是显示DateInterval对象的命令行:
php -r "\$a = new Datetime('first day of 4 months ago midnight'); \$b = new Datetime('first day of 1 month ago midnight'); var_dump(\$a->diff(\$b));"
这里是 DateInterval 输出:
class DateInterval#3 (15) {
public $y => int(0)
public $m => int(3)
public $d => int(3)
public $h => int(0)
public $i => int(0)
public $s => int(0)
public $weekday => int(0)
public $weekday_behavior => int(0)
public $first_last_day_of => int(0)
public $invert => int(0)
public $days => int(92)
public $special_type => int(0)
public $special_amount => int(0)
public $have_weekday_relative => int(0)
public $have_special_relative => int(0)
}
编辑:第一个和第二个日期时间:
class DateTime#1 (3) {
public $date =>
string(19) "2014-03-01 00:00:00"
public $timezone_type =>
int(3)
public $timezone =>
string(13) "Europe/Zurich"
}
class DateTime#2 (3) {
public $date =>
string(19) "2014-06-01 00:00:00"
public $timezone_type =>
int(3)
public $timezone =>
string(13) "Europe/Zurich"
}
注意3天!我使用的是PHP 5.5.8,但我确信这个DateInterval前几天有0个月。 DateInterval在PHP 5.4.28和5.5.14中输出0天。我不确定PHP版本是否有效。
在这两种情况下,天属性为92。
答案 0 :(得分:4)
深入了解Paul T. Rawkeen's answer,DateTime::diff
的问题在于它converts the timezone to UTC before computation。
<?php
$zurich = new DateTimeZone('Europe/Zurich');
$utc = new DateTimeZone('UTC');
$a = new DateTime('first day of 4 months ago midnight',$zurich);
$b = new DateTime('first day of 1 month ago midnight',$zurich);
var_dump($a,$b);
$a->setTimezone($utc);
$b->setTimezone($utc);
var_dump($a,$b);
?>
给出以下内容:
object(DateTime)[3]
public 'date' => string '2014-03-01 00:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Zurich' (length=13)
object(DateTime)[4]
public 'date' => string '2014-06-01 00:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Zurich' (length=13)
object(DateTime)[3]
public 'date' => string '2014-02-28 23:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
object(DateTime)[4]
public 'date' => string '2014-05-31 22:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
在时区从Europe/Zurich
转换为UTC
之后,3天的差异非常明显,现在2014-02-28 23:00:00
的日期2014-05-31 22:00:00
和$a
的{{1}}和$b
分别。
解决方案是完全使用UTC并在显示DateTime之前进行转换:
<?php
$zurich = new DateTimeZone('Europe/Zurich');
$utc = new DateTimeZone('UTC');
$a = new DateTime('first day of 4 months ago midnight',$utc);
$b = new DateTime('first day of 1 month ago midnight',$utc);
var_dump($a,$b);
$a->setTimezone($zurich);
$b->setTimezone($zurich);
var_dump($a,$b);
?>
请注意,所有日期现在都是01
,尽管现在的时间有点不同(请参阅本答案末尾的注释):
object(DateTime)[3]
public 'date' => string '2014-03-01 00:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
object(DateTime)[4]
public 'date' => string '2014-06-01 00:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
object(DateTime)[3]
public 'date' => string '2014-03-01 01:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Zurich' (length=13)
object(DateTime)[4]
public 'date' => string '2014-06-01 02:00:00' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Zurich' (length=13)
要对此现象提供一些见解,请注意以下事项:
从欧洲/苏黎世转换为UTC时,必须考虑的不仅仅是年,月和日,还要考虑小时,分钟和秒。如果这是任何其他日子,而不是任何月份的第一个,那么这个问题就不会发生,但是时间仍然是23:00和22:00(在上面的例子之前)。
答案 1 :(得分:2)
这件事取决于你提供的DateTimeZone
。
如果您设置Europe/Zurich
或任何EEST
时间,您将获得所述结果。
例如,如果GMT
/ UTC
,您将获得$d = 0
。
您可以在项目中使用全局时区定义来避免此类问题(,如果它适合您)
date_default_timezone_set(“Europe / Zurich”);
或为DateTime
个对象定义所需的时区。