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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: ploeger dot private at googlemail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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: Mon Dec 30 17:01:29 2024 UTC