php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #62327 Calculation error in DateTime::add() or DateTime::diff()
Submitted: 2012-06-14 19:04 UTC Modified: -
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:2 (200.0%)
Same OS:2 (200.0%)
From: helmut at qweb dot at Assigned:
Status: Open Package: Date/time related
PHP Version: Irrelevant OS: Linux, Windows
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2012-06-14 19:04 UTC] helmut at qweb dot at
Description:
------------
The task was to shift a date-interval like [ begin: 2012-05-07, end: 2012-06-01 ] to another begin date like 2012-05-21 - an end date 2012-06-15 is expected (first example). The function shift_datetimeobject() uses DateTime::diff() and DateTime::add() to calculate the end date - it fails in the 3rd of 4 attempts.

The second function shift_timestamp() uses timestamp to solve the same task. it works like expected.

The bug was found on Windows Server 2008/Apache 2.4.2/PHP 5.4.4 and on Debian Linux squeeze/PHP 5.3.3-7+squeeze9 with Suhosin-Patch/cli and libapache2-mod-php5 5.3.3-7+squeeze9

Test script:
---------------
function shift_datetimeobject($begin1, $end1, $begin2) {
    
    $dt_begin1 = new DateTime($begin1);
    $dt_end1 =  new DateTime($end1);

    $span = $dt_begin1->diff($dt_end1);

    $dt_return = new DateTime($begin2);
    return array($dt_return->add($span), $span);
}
function shift_timestamp($begin1, $end1, $begin2) {
    
    $dt_begin1 = new DateTime($begin1);
    $st_begin1 = $dt_begin1->getTimestamp();

    $dt_end1 =  new DateTime($end1);
    $st_end1 = $dt_end1->getTimestamp();

    $span = $st_end1 - $st_begin1;

    $dt_begin2 = new DateTime($begin2);
    $st_begin2 = $dt_begin2->getTimestamp();

    $st_end2 = $st_begin2 + $span;
    $dt_end2 = new DateTime();
    return $dt_end2->setTimestamp($st_end2);   
}

$params = array(
    array('2012-05-07', '2012-06-01', '2012-05-21'),
    array('2012-06-11', '2012-07-13', '2012-06-18'),
    array('2012-06-25', '2012-07-27', '2012-07-02'),
    array('2012-07-09', '2012-07-27', '2012-07-16'),
);
foreach ($params as $p) {
    $erg_object = shift_datetimeobject($p[0], $p[1], $p[2]);
    $erg_stamp  =      shift_timestamp($p[0], $p[1], $p[2]);    
    printf("Params: %s, %s, %s\n", $p[0], $p[1], $p[2]);
    printf('$erg_stamp     = %s' . "\n", $erg_stamp->format('Y-m-d'));
    printf('$erg_object[0] = %s' . "\n", $erg_object[0]->format('Y-m-d'));
    printf("span (object)  = %s\n", $erg_object[1]->format('%a days %H:%I:%S'));
    if ($erg_object[0] == $erg_stamp) {
        echo "OK";
    } else {
        echo "WRONG!";
    }
    echo "\n\n";
}

Expected result:
----------------
Params: 2012-05-07, 2012-06-01, 2012-05-21
Result: 2012-06-15

Params: 2012-06-11, 2012-07-13, 2012-06-18
Result: 2012-07-20

Params: 2012-06-25, 2012-07-27, 2012-07-02
Result: 2012-08-03

Params: 2012-07-09, 2012-07-27, 2012-07-16
Result: 2012-08-03

Actual result:
--------------
Params: 2012-05-07, 2012-06-01, 2012-05-21
$erg_stamp     = 2012-06-15
$erg_object[0] = 2012-06-15
span (object)  = 25 days 00:00:00
OK

Params: 2012-06-11, 2012-07-13, 2012-06-18
$erg_stamp     = 2012-07-20
$erg_object[0] = 2012-07-20
span (object)  = 32 days 00:00:00
OK

Params: 2012-06-25, 2012-07-27, 2012-07-02
$erg_stamp     = 2012-08-03
$erg_object[0] = 2012-08-04
span (object)  = 32 days 00:00:00
WRONG!

Params: 2012-07-09, 2012-07-27, 2012-07-16
$erg_stamp     = 2012-08-03
$erg_object[0] = 2012-08-03
span (object)  = 18 days 00:00:00
OK

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-07-09 13:54 UTC] xKhorasan+php at gmail dot com
Submitted a pull request to derickr/timelib.
https://github.com/derickr/timelib/pull/15
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue May 21 21:01:26 2019 UTC