问题
I use DateTime::diff
to compare two DateTime
, but the result is very weird as if 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"));
Which returns:
int(364)
int(364)
string(15) "00-11-30 00:0:0"
string(15) "00-11-29 00:0:0"
Demo
回答1:
The behavior is correct. Both date intervals represent same number of days (364). The month and date part represent the period that needs to be added to/subtracted from first date to reach second date:
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
A simpler example would be Oct 21 ... Dec 20:
- You need to add 1 month 29 days to Oct 21 to reach Dec 20 (note that month before Dec has 30 days)
- But ... you need to subtract 1 month 30 days from Dec 20 to reach Oct 21. Oct itself has 31 days which explains the difference.
回答2:
Why not subtract min from max?
Pseudo code:
$diff = max($date1, $date2) - min($date1, $date2)
That way you should always get the same and correct result.
回答3:
The result seems wired, but is correct: It is explained by some months having 30 or 31 (or 28) days. If you would execute this example for October
$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)
or February
string(15) "00-11-30 00:0:0"
string(15) "00-11-28 00:0:0"
bool(false)
Yet
var_dump($date1->diff($date2,true)->format("%a"));
will always show
string(3) "365"
回答4:
Ok so just to state my comment as an answer. My guess is that this is the expected behaviour since it's a different amount of days depending on if you go forwards or backwards in time. Imagine going from yesterday to today over a year, that'd be 366 days since you have to round a whole year plus 1 day
. And from today to yesterday (last year) would be only 364 days for the same reason, it's whole year minus one day
. As for the solution, the option that @Andreas suggested is the way to go here.
来源:https://stackoverflow.com/questions/58954032/datetimediff-weired-result