ID:               49081
 Comment by:       peter dot schleif at gmx dot de
 Reported By:      nate at frickenate dot com
 Status:           Assigned
 Bug Type:         Date/time related
 Operating System: *
 PHP Version:      5.3.0
 Assigned To:      derick
 New Comment:

More simple code to reproduce error:

<?php
   date_default_timezone_set('Europe/Berlin');
   $d1 = new DateTime('2010-01-01 06:00:00');
   $d2 = new DateTime('2010-01-31 10:00:00');
   $d  = $d1->diff($d2);
   print_r($d);
?>

Expected:
---------
   [m] => 0
   [d] => 30

Actual:
-------
   [m] => 1
   [d] => 2


Previous Comments:
------------------------------------------------------------------------

[2009-07-27 22:55:24] nate at frickenate dot com

Description:
------------
DateTime::diff calculates diffs incorrectly.

As an example, the diff of 2009-01-01 and 2009-03-31 *should be* "2
months, 30 days". 2009-01-01 + 2 months = 2009-03-01, + 30 days =
2009-03-31. Taking 2009-01-01 and using DateTime::add() to add 'P2M30D'
does indeed result in 2009-03-31. This is correct.

However, running the diff() of 2009-01-01 and 2009-03-31 returns "3
months, 2 days". add()ing 2009-01-01 + 'P3M2D' returns 2009-04-03
instead of 2009-03-31 (as it should, since the diff that told us to add
3M2D was incorrect).

Reproduce code:
---------------
<?

$jan_1 = new DateTime('2009-01-01');
$mar_31 = new DateTime('2009-03-31');

var_dump(date_diff($jan_1, $mar_31));
var_dump($jan_1->add(new DateInterval('P2M30D'))); // correct period
var_dump($jan_1->add(new DateInterval('P3M2D')));  // incorrect period

// END EXAMPLE CODE - following is just extra fluff


// here's the replacement function I am currently
// using to calculate the correct diff until the
// built-in method is patched and functional
function date_diff2 ($t1, $t2) {
    if (! preg_match('/^\d+\z/', $t1) && ($t1 = strtotime($t1)) ===
false)
        return false;

    if (! preg_match('/^\d+\z/', $t2) && ($t2 = strtotime($t2)) ===
false)
        return false;

    if ($t1 > $t2)
        list($t1, $t2) = array($t2, $t1);

    $diffs = array(
        'years' => 0, 'months' => 0, 'days' => 0,
        'hours' => 0, 'minutes' => 0, 'seconds' => 0,
    );

    foreach (array_keys($diffs) as $interval) {
        while ($t2 >= ($t3 = strtotime("+1 ${interval}", $t1))) {
            $t1 = $t3;
            ++$diffs[$interval];
        }
    }

    return $diffs;
}


?>

Expected result:
----------------
object(DateInterval)#3 (8) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(2)
  ["d"]=>
  int(30)
  ["h"]=>
  int(0)
  ["i"]=>
  int(0)
  ["s"]=>
  int(0)
  ["invert"]=>
  int(0)
  ["days"]=>
  int(89)
}
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2009-03-31 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/Montreal"
}
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2009-07-03 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/Montreal"
}


Actual result:
--------------
object(DateInterval)#3 (8) {
  ["y"]=>
  int(0)
  ["m"]=>
  int(3)
  ["d"]=>
  int(2)
  ["h"]=>
  int(0)
  ["i"]=>
  int(0)
  ["s"]=>
  int(0)
  ["invert"]=>
  int(0)
  ["days"]=>
  int(89)
}
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2009-03-31 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/Montreal"
}
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2009-07-03 00:00:00"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "America/Montreal"
}



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=49081&edit=1

Reply via email to