php - PHP 的 date_diff() 行为异常
问题描述
可能只是我笨,但是...
<?php
$startDate = date_create('2019-11-01');
$endDate = date_create('2019-12-01');
$interval = date_diff($startDate, $endDate);
var_dump($interval);
?>
在PHPfiddle中给出(如预期的那样):
object(DateInterval)#3 (15)
{ ["y"]=> int(0)
["m"]=> int(1) <=== 这就是我在本地机器上遇到问题的原因
["d" ]=> int(0)
["h"]=> int(0)
["i"]=> int(0)
["s"]=> int(0)
["weekday"]=> int(0 )
["weekday_behavior"]=> int(0)
["first_last_day_of"]=> int(0)
["invert"]=> int(0)
["days"]=> int(30)
["special_type"] => int(0)
["special_amount"]=> int(0)
["have_weekday_relative"]=> int(0)
["have_special_relative"]=> int(0) }
查看 的值m
,即月数。
但是,在我的本地机器上,相同的代码给出:
class DateInterval#4 (16) {
public $y =>
int(0)
public $m =>
int(0) <====== why ??!!
public $d =>
int(30)
public $h =>
int(0)
public $i =>
int(0)
public $s =>
int(0)
public $f =>
double(0)
public $weekday =>
int(0)
public $weekday_behavior =>
int(0)
public $first_last_day_of =>
int(0)
public $invert =>
int(0)
public $days =>
int(30)
public $special_type =>
int(0)
public $special_amount =>
int(0)
public $have_weekday_relative =>
int(0)
public $have_special_relative =>
int(0)
}
好的,我承认是 30 天,但我正在寻找的答案是 1 个月,并且$interval->m
是 zer0。
我错过了什么?我不知道PHPfiddle网站使用的是什么版本的 PHP,但我在本地使用的是 7.3.11。
解决方案
可能差异在于时区。
试试这个:
<?php
date_default_timezone_set('UTC');
$startDate = date_create('2019-11-01');
$endDate = date_create('2019-12-01');
$interval = date_diff($startDate, $endDate);
var_dump($interval);
/*
object(DateInterval)#3 (16) {
["y"]=>
int(0)
["m"]=>
int(1)
...
*/
也试试这个:
<?php
$startDate = date_create('2019-11-01 23:00');
$endDate = date_create('2019-12-01 23:00');
$interval = date_diff($startDate, $endDate);
var_dump($interval);
/* outputs the same ["m"]=> int(1) as above */
可能 date_diff 寻找 UTC 时间戳之间的差异,并且您将 PHP 上的默认时区设置为某个正值。
假设您有一些默认时区,即 UTC+02:00,因此
date_create('2019-11-01')
实际上日期为 2019-10-31 22:00:00 (UTC)
,date_create('2019-12-01')
实际上日期为 2019-11-30 22:00:00 (UTC)
现在你可以看到他们没有整月的差异。
但你可以捕捉到另一个有趣的效果:
<?php
//assuming your timezone is UTC+something
$startDate = date_create('2019-10-31'); // creates a date 2019-10-30 XX:00 UTC
$endDate = date_create('2019-12-01'); // creates a date 2019-11-30 XX:00 UTC
$interval = date_diff($startDate, $endDate);
var_dump($interval);
/*
object(DateInterval)#3 (16) {
["y"]=>
int(0)
["m"]=>
int(1) sic(!)
["d"]=>
int(0) sic(!)
*/
如果您的时区有夏令时,您也可能会得到意想不到的结果。
<?php
// Germany has the daylight saving shift at last Sunday of March and October.
date_default_timezone_set('Europe/Berlin');
$startDate = date_create('2020-03-28 03:00');
$endDate = date_create('2020-03-29 02:00');
$interval = date_diff($startDate, $endDate);
var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0)
$startDate = date_create('2020-03-28 03:00');
$endDate = date_create('2020-03-29 03:00');
$interval = date_diff($startDate, $endDate);
var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0)
$startDate = date_create('2020-03-28 03:00');
$endDate = date_create('2020-03-28 03:00'); // the same
$endDate->modify('+23 hour');
$interval = date_diff($startDate, $endDate);
var_dump($interval); // ["d"]=> int(1) ["h"]=> int(0)
PHPFiddle将默认时区设置为 UTC,因此默认情况下会给出一个月的差异。
为避免这种情况,只需从头开始以 UTC 执行所有日期计算:
<?php
$timeZone = new DateTimeZone('UTC');
$startDate = new DateTime('2019-10-31', $timeZone);
$endDate = new DateTime('2019-12-01', $timeZone);
$interval = date_diff($startDate, $endDate);
var_dump($interval);
推荐阅读
- c++ - 如何逐行打印文本文件并正确分隔?
- php - 需要代码从 WordPress 中的帖子中删除链接
- tfs - 将工作项从一个集合的团队项目单独移动到另一个集合
- c - 如果我想在 C 中写入数组,如何使数组发挥作用?
- javascript - componentDidMount() 在 render() 方法之前渲染
- javascript - amphtml 标记显示错误“引用的 AMP URL 不是 AMP”
- graph - 给定一个表示 n 个元素之间成本的邻接矩阵,我如何将 n 个元素分成 k 个组?
- jsonschema - 'if, then and else' 关键字可以应用在对象的属性中还是严格保留在外部?
- angular - 了解功能模块中的 Angular 路由
- ios - 使用 AudioKit 导出过滤后的音频