php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62326 date_diff() function returns false result
Submitted: 2012-06-14 18:52 UTC Modified: 2021-04-06 19:52 UTC
Votes:28
Avg. Score:4.9 ± 0.3
Reproduced:25 of 26 (96.2%)
Same Version:17 (68.0%)
Same OS:17 (68.0%)
From: ploeger dot private at googlemail dot com Assigned: derick (profile)
Status: Closed Package: Date/time related
PHP Version: 5.3Git-2012-06-14 (snap) OS: Windows Server 2008 R2
Private report: No CVE-ID: None
 [2012-06-14 18:52 UTC] ploeger dot private at googlemail dot com
Description:
------------
The source code will return 05 instead of 06.

If you change the day to 02 instead of 01 in start_timestamp and end_timestamp 
everything seems to work correct.

Debug:
print_r($start_timestamp);
Result: DateTime Object ( [date] => 2012-06-01 00:00:00 [timezone_type] => 3 
[timezone] => Europe/Berlin )

print_r($end_timestamp);
Result: DateTime Object ( [date] => 2012-12-01 00:00:00 [timezone_type] => 3 
[timezone] => Europe/Berlin )

Test script:
---------------
$start_timestamp    = date_create('2012-06-01');
$end_timestamp      = date_create('2012-12-01');
$difference = date_diff($start_timestamp, $end_timestamp);
$difference = $difference->format('%M');  

Expected result:
----------------
06

Actual result:
--------------
05

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-06-14 19:00 UTC] rasmus@php.net
That output 06 on Linux
 [2012-06-14 19:13 UTC] ploeger dot private at googlemail dot com
I could reproduce the bug on WinXP Pro SP3, Win Server 2008 R2 and Win7 Pro.
Default Timezone: Europe/Berlin

Workaround with correct result:
date_default_timezone_set("UTC");
$start_timestamp    = date_create('2012-06-01');
$end_timestamp      = date_create('2012-12-01');
$difference = date_diff($start_timestamp, $end_timestamp);
var_dump($difference);  //6 months

Could you reproduce the bug with:
date.timezone = "Europe/Berlin"
in php.ini on linux?
 [2012-06-14 19:55 UTC] juergen78 at gmail dot com
My Hosters OS:
Linux alfa3025 2.6.32-bpo.5-amd64 #1 SMP Wed Jul 20 09:10:04 UTC 2011 x86_64 

Code:
-----
date_default_timezone_set("Europe/Berlin");
$start_timestamp    = date_create('2012-06-01');
$end_timestamp      = date_create('2012-12-01');
$difference = date_diff($start_timestamp, $end_timestamp);
$difference = $difference->format('%M');
echo $difference;

Output:
05
 [2012-06-15 11:17 UTC] ploeger dot private at googlemail dot com
Test script to show the behavior of the bug:

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

const start_date = '2012-06-01 00:00:00'; 
const end_date = '2012-12-01 00:00:00'; 

$timezones = array('europe/Berlin', 'GMT', 'CET', 'UTC'); 

$possibleTimezones = DateTimeZone::listIdentifiers(); 
$possibleTimezones = array_map('strtolower', $possibleTimezones); 

foreach ( $timezones as $testZone ) 
{ 
    $cur = new DateTimeZone($testZone); 
    $start = date_create(start_date, $cur); 
    $end   = date_create(end_date, $cur); 

    $info[] = join(array( 
        'Soll-TZ   : '.$testZone.PHP_EOL, 
        'Differenz : '.( $start->diff($end)->format('%y Jahre %m Monate %d 
Monatstage ( %a tage total )') ).PHP_EOL, 
        'gelisted  : '.( in_array(strtolower($testZone), $possibleTimezones) ? 
'Ja' : 'Nein' ).PHP_EOL, 
        'Alias     : '.( strcasecmp($testZone, $cur->getName()) == 0 ? 'Nein' : 
'Ja' ).PHP_EOL, 
        'Ist-TZ    : '.( $cur->getName() ).PHP_EOL, 
        'start OfS : '.( ( $cur->getOffset($start) / 60 / 60 ) ).' 
Stunden'.PHP_EOL, 
        'end OfS   : '.( ( $cur->getOffset($end) / 60 / 60 ) ).' 
Stunden'.PHP_EOL 
    )); 
} 

echo join('--- '.PHP_EOL, $info);

Result:
----------------
Soll-TZ   : europe/Berlin
Differenz : 0 Jahre 5 Monate 30 Monatstage ( 183 tage total )
gelisted  : Ja
Alias     : Nein
Ist-TZ    : Europe/Berlin
start OfS : 2 Stunden
end OfS   : 1 Stunden
--- 
Soll-TZ   : GMT
Differenz : 0 Jahre 6 Monate 0 Monatstage ( 183 tage total )
gelisted  : Nein
Alias     : Ja
Ist-TZ    : UTC
start OfS : 0 Stunden
end OfS   : 0 Stunden
--- 
Soll-TZ   : CET
Differenz : 0 Jahre 5 Monate 30 Monatstage ( 183 tage total )
gelisted  : Nein
Alias     : Ja
Ist-TZ    : Europe/Berlin
start OfS : 2 Stunden
end OfS   : 1 Stunden
--- 
Soll-TZ   : UTC
Differenz : 0 Jahre 6 Monate 0 Monatstage ( 183 tage total )
gelisted  : Ja
Alias     : Nein
Ist-TZ    : UTC
start OfS : 0 Stunden
end OfS   : 0 Stunden
 [2013-10-30 02:20 UTC] cmbecker69 at gmx dot de
FWIW: this issue apparently is caused by the daylight saving time shift.
 [2017-05-04 17:25 UTC] peehaa@php.net
-Package: Class/Object related +Package: Date/time related
 [2019-01-14 16:26 UTC] esavichev at gmail dot com
Looks like the same issue on PHP 7.2.10-0ubuntu0.18.04.1
Code to reproduce:

-------------------------------------------------------
echo date_diff(
    date_create('1921-05-02 00:00:00'),
    date_create('1921-05-03 00:00:00')
)->days . "\n"; // 1 - it's correct

echo date_diff(
    date_create('1921-05-01 00:00:00'),
    date_create('1921-05-02 00:00:00')
)->days . "\n"; // 0 - why zero? expected 1!

echo date_diff(
    date_create('1921-05-01 00:00:00'),
    date_create('2019-01-01 00:00:00')
)->days . "\n"; // 35673

echo date_diff(
    date_create('1921-05-02 00:00:00'),
    date_create('2019-01-01 00:00:00')
)->days . "\n"; // 35673 - the same as previous?
-------------------------------------------------------
 [2020-07-09 19:53 UTC] didomak663 at nalafx dot com
My test script is:

<?php
    printf("PHP: %s\nOS: %s\n", PHP_VERSION, php_uname("s")." ".php_uname("r")." ".php_uname("v")." ".php_uname("m"));
    $dateBase = "1500-01-01"; // Base date should be less or equal 1919-07-01, buggy behaviour depends on base date
    $testsize = 200000;

    $prev_shift = 0;
    printf("First date: %s\n", date("Y-m-d", strtotime($dateBase." +0 days")));
    for ($i=0; $i<$testsize; $i++) {
        $date = date("Y-m-d", strtotime($dateBase." +$i days"));
        $interval = date_diff(date_create($date), date_create($dateBase));
        $j = $interval->days;
        if ($i - $j != $prev_shift) {
            printf("%s\t%d\t%d\t%s\n", $date, $i, $j, ($i == $j) ? "date_diff() recoveres" : ($i - $j)." days shift happens");
            $prev_shift = $i - $j;
        }
    }
    printf("Last date: %s\n", date("Y-m-d", strtotime($dateBase." +$testsize days")));
?>

Expected result:

PHP: 7.3.19-1~deb10u1
OS: Linux 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64
First date: 1500-01-01
Last date: 2047-08-01

Actual results:

PHP: 7.3.19-1~deb10u1
OS: Linux 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64
First date: 1500-01-01
1916-07-04	152125	152124	1 days shift happens
1922-10-01	154405	154405	date_diff() recoveres
1930-06-22	157226	157225	1 days shift happens
1981-04-01	175772	175772	date_diff() recoveres
1981-04-02	175773	175772	1 days shift happens
1982-04-01	176137	176137	date_diff() recoveres
1982-04-02	176138	176137	1 days shift happens
1983-04-01	176502	176502	date_diff() recoveres
1983-04-02	176503	176502	1 days shift happens
1984-04-01	176868	176868	date_diff() recoveres
1984-04-02	176869	176868	1 days shift happens
1991-09-30	179606	179606	date_diff() recoveres
1992-01-20	179718	179717	1 days shift happens
Last date: 2047-08-01

PHP: 7.3.19-1+ubuntu16.04.1+deb.sury.org+1
OS: Linux 4.4.0-185-generic #215-Ubuntu SMP Mon Jun 8 21:53:19 UTC 2020 x86_64
First date: 1500-01-01
1916-07-04	152125	152124	1 days shift happens
1922-10-01	154405	154405	date_diff() recoveres
1930-06-22	157226	157225	1 days shift happens
1981-04-01	175772	175772	date_diff() recoveres
1981-04-02	175773	175772	1 days shift happens
1982-04-01	176137	176137	date_diff() recoveres
1982-04-02	176138	176137	1 days shift happens
1983-04-01	176502	176502	date_diff() recoveres
1983-04-02	176503	176502	1 days shift happens
1984-04-01	176868	176868	date_diff() recoveres
1984-04-02	176869	176868	1 days shift happens
1991-09-30	179606	179606	date_diff() recoveres
1992-01-20	179718	179717	1 days shift happens
Last date: 2047-08-01

PHP: 5.4.16
OS: Linux 3.10.0-693.2.2.el7.x86_64 #1 SMP Tue Sep 12 22:26:13 UTC 2017 x86_64
First date: 1500-01-01
1916-07-04	152125	152124	1 days shift happens
1922-10-01	154405	154405	date_diff() recoveres
1930-06-22	157226	157225	1 days shift happens
1981-04-01	175772	175772	date_diff() recoveres
1981-04-02	175773	175772	1 days shift happens
1982-04-01	176137	176137	date_diff() recoveres
1982-04-02	176138	176137	1 days shift happens
1983-04-01	176502	176502	date_diff() recoveres
1983-04-02	176503	176502	1 days shift happens
1984-04-01	176868	176868	date_diff() recoveres
1984-04-02	176869	176868	1 days shift happens
1991-09-30	179606	179606	date_diff() recoveres
1992-01-20	179718	179717	1 days shift happens
Last date: 2047-08-01
 [2020-10-13 13:04 UTC] cmb@php.net
Yes, definitely DST issue, and I believe already reported
elsewhere in this bugtracker.
 [2021-04-06 19:52 UTC] derick@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: derick
 [2021-04-06 19:52 UTC] derick@php.net
The fix for this bug has been committed.
If you are still experiencing this bug, try to check out latest source from https://github.com/php/php-src and re-test.
Thank you for the report, and for helping us make PHP better.

Fixed for PHP 8.1.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 11:01:28 2024 UTC