DateTime::diff 奇怪的结果
DateTime::diff weired result
我用DateTime::diff
来比较两个DateTime
,结果很奇怪好像abs($date1 - $date2) != abs($date2 - $date1)
.
$date1 = new DateTime("1980-11-21 00:00:00");
$date2 = new DateTime("1981-11-20 00:00:00");
var_dump($date1->diff($date2,true)->days);
var_dump($date2->diff($date1,true)->days);
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
哪个returns:
int(364)
int(364)
string(15) "00-11-30 00:0:0"
string(15) "00-11-29 00:0:0"
为什么不从最大值中减去最小值?
伪代码:
$diff = max($date1, $date2) - min($date1, $date2)
这样你应该总是得到相同和正确的结果。
好的,所以只是将我的评论作为答案。我的猜测是这是预期的行为,因为它是不同的天数,具体取决于您是向前还是向后。想象一下,从昨天到今天,一年多了,那是 366 天,因为你必须舍入 whole year plus 1 day
。而从今天到昨天(去年)也只有 364 天,同理,是 whole year minus one day
。至于解决方案,@Andreas 建议的选项是这里的方法。
结果似乎有线,但却是正确的:
解释为有些月份有 30 或 31(或 28)天。如果您要在 10 月执行此示例
$date1 = new DateTime("1980-10-21 00:00:00");
$date2 = new DateTime("1981-10-20 00:00:00");
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s") == $date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
string(15) "00-11-29 00:0:0"
string(15) "00-11-30 00:0:0"
bool(false)
或二月
string(15) "00-11-30 00:0:0"
string(15) "00-11-28 00:0:0"
bool(false)
还有
var_dump($date1->diff($date2,true)->format("%a"));
将始终显示
string(3) "365"
行为正确。两个日期间隔代表相同的天数 (364)。月份和日期部分表示从第一个日期到第二个日期需要相加to/subtracted的时间段:
1981-11-20 minus 1980-11-21 represents an interval of 11 month 30 day
1980-11-21 + 11 month = 1981-10-21
1981-10-21 + 30 day = 1981-10-21
1980-11-21 minus 1981-11-20 represents an interval of 11 month 29 day
1981-11-20 - 11 month = 1980-12-20
1980-12-20 - 29 day = 1980-11-21
一个更简单的例子是 10 月 21 日 ... 12 月 20 日:
- 您需要将 10 月 21 日加上 1 个月 29 天才能到达 12 月 20 日(请注意,12 月之前的月份有 30 天)
- 但是...您需要从 12 月 20 日减去 1 个月 30 天才能得到 10 月 21 日。Oct 本身有 31 天,这就解释了差异。
我用DateTime::diff
来比较两个DateTime
,结果很奇怪好像abs($date1 - $date2) != abs($date2 - $date1)
.
$date1 = new DateTime("1980-11-21 00:00:00");
$date2 = new DateTime("1981-11-20 00:00:00");
var_dump($date1->diff($date2,true)->days);
var_dump($date2->diff($date1,true)->days);
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
哪个returns:
int(364)
int(364)
string(15) "00-11-30 00:0:0"
string(15) "00-11-29 00:0:0"
为什么不从最大值中减去最小值?
伪代码:
$diff = max($date1, $date2) - min($date1, $date2)
这样你应该总是得到相同和正确的结果。
好的,所以只是将我的评论作为答案。我的猜测是这是预期的行为,因为它是不同的天数,具体取决于您是向前还是向后。想象一下,从昨天到今天,一年多了,那是 366 天,因为你必须舍入 whole year plus 1 day
。而从今天到昨天(去年)也只有 364 天,同理,是 whole year minus one day
。至于解决方案,@Andreas 建议的选项是这里的方法。
结果似乎有线,但却是正确的: 解释为有些月份有 30 或 31(或 28)天。如果您要在 10 月执行此示例
$date1 = new DateTime("1980-10-21 00:00:00");
$date2 = new DateTime("1981-10-20 00:00:00");
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
var_dump($date1->diff($date2,true)->format("%Y-%m-%d %H:%i:%s") == $date2->diff($date1,true)->format("%Y-%m-%d %H:%i:%s"));
string(15) "00-11-29 00:0:0"
string(15) "00-11-30 00:0:0"
bool(false)
或二月
string(15) "00-11-30 00:0:0"
string(15) "00-11-28 00:0:0"
bool(false)
还有
var_dump($date1->diff($date2,true)->format("%a"));
将始终显示
string(3) "365"
行为正确。两个日期间隔代表相同的天数 (364)。月份和日期部分表示从第一个日期到第二个日期需要相加to/subtracted的时间段:
1981-11-20 minus 1980-11-21 represents an interval of 11 month 30 day
1980-11-21 + 11 month = 1981-10-21
1981-10-21 + 30 day = 1981-10-21
1980-11-21 minus 1981-11-20 represents an interval of 11 month 29 day
1981-11-20 - 11 month = 1980-12-20
1980-12-20 - 29 day = 1980-11-21
一个更简单的例子是 10 月 21 日 ... 12 月 20 日:
- 您需要将 10 月 21 日加上 1 个月 29 天才能到达 12 月 20 日(请注意,12 月之前的月份有 30 天)
- 但是...您需要从 12 月 20 日减去 1 个月 30 天才能得到 10 月 21 日。Oct 本身有 31 天,这就解释了差异。