php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70126 Wrong calculation of the difference between two dates
Submitted: 2015-07-24 09:50 UTC Modified: 2022-10-19 15:26 UTC
From: php at tul dot io Assigned: derick (profile)
Status: Not a bug Package: Date/time related
PHP Version: 7.0.0beta2 OS: any
Private report: No CVE-ID: None
 [2015-07-24 09:50 UTC] php at tul dot io
Description:
------------
DateTime::diff() reports the wrong number of days and months when not in an inverted order (start date < end date). To reproduce, the two dates used as input have to be even number of months apart and the day of the start date has to be greater than the day of the end date (e.g. 2015-01-31 to 2015-03-01).

Test script:
---------------
<?php

$date1 = new DateTime('2015/01/31');
$date2 = new DateTime('2015/03/01');

print_r($date1->diff($date2));
print_r($date2->diff($date1));

Expected result:
----------------
DateInterval Object
(
    [y] => 0
    [m] => 1
    [d] => 1
    [h] => 0
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 29
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)
DateInterval Object
(
    [y] => 0
    [m] => 1
    [d] => 1
    [h] => 0
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 1
    [days] => 29
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

Actual result:
--------------
DateInterval Object
(
    [y] => 0
    [m] => 0
    [d] => 29
    [h] => 0
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 29
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)
DateInterval Object
(
    [y] => 0
    [m] => 1
    [d] => 1
    [h] => 0
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 1
    [days] => 29
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
)

Patches

bug-datetime-diff-calculations (last revision 2015-07-24 09:51 UTC by php at tul dot io)

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-07-24 10:33 UTC] derick@php.net
-Status: Open +Status: Suspended -Assigned To: +Assigned To: derick
 [2015-07-24 10:33 UTC] derick@php.net
timelib development lives at http://github.com/derickr/timelib - the one in PHP is a bundled version. Timelib does right now not have a test harnass for diffs, although there is a tester for it: https://github.com/derickr/timelib/blob/master/tests/tester-diff.c

Once it's fixed (and tested) in timelib, I'm happy to resync it back to PHP.
 [2022-10-19 15:26 UTC] derick@php.net
-Status: Suspended +Status: Not a bug
 [2022-10-19 15:26 UTC] derick@php.net
Sorry, but your problem does not imply a bug in PHP itself.  For a
list of more appropriate places to ask for help using PHP, please
visit http://www.php.net/support.php as this bug system is not the
appropriate forum for asking support questions.  Due to the volume
of reports we can not explain in detail here why your report is not
a bug.  The support channels will be able to provide an explanation
for you.

Thank you for your interest in PHP.

The actual result is the correct result. What "diff" returns you is a way how to get from $date1 to the argument in the ->diff() method through the use of the string "+{$m} month {$d} days" as an argument to ->modify().

To go from 2015/01/31 to 2015/03/01, it can't be 1 month and 1 day, because that would do the following:

2015/01/31
     +1 +1
2015/02/32
which rolls over to:
2015/03/04

Which is clearly not the right answer:

<?php
echo (new DateTimeImmutable("2015-01-31"))->modify("+1 month 1 day")->format("Y-m-d"), "\n";
?>
// 2015-03-04

The only value that works is 0 months, 29 days:

<?php
echo (new DateTimeImmutable("2015-01-31"))->modify("+0 month 29 days")->format("Y-m-d"), "\n";
?>
// 2015-03-01
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 12 10:01:26 2024 UTC