Bug #69468 [Opn->Nab]: DateTime->add problem for 2015-01-31

From: Date: Thu, 16 Apr 2015 11:30:10 +0000
Subject: Bug #69468 [Opn->Nab]: DateTime->add problem for 2015-01-31
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-192131@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69468&edit=1 ID: 69468 Updated by: requinix@php.net Reported by: pawaroti at gmail dot com Summary: DateTime->add problem for 2015-01-31 -Status: Open +Status: Not a bug Type: Bug Package: Date/time related Operating System: Windows 7 PHP Version: 5.5.24RC1 Block user comment: N Private report: N New Comment: P1M means "increment the month number by 1". Jan 31 + 1 month = Feb 31, which is invalid and overflows into March, becoming Mar 3. Similarly for other months with <31 days. You need to decide what result you want to get, understand why you want to get it, and then write code to support it. You may find that the logic is easier to express using the procedural functions. For example, if you wanted to use the last day of the month if the date overflowed, // extract month, day, and year components $start = date_parse("2015-01-31"); // use month+1 and allow for overflow $target = mktime(0, 0, 0, $start["month"] + 1, $start["day"], $start["year"]); // end day < start day promises that the date must have overflowed if (getdate($target)["mday"] < $start["day"]) { // use underflow with month+2 $target = mktime(0, 0, 0, $start["month"] + 2, 0, $start["year"]); } http://3v4l.org/Y3CHG Previous Comments: ------------------------------------------------------------------------ [2015-04-16 10:37:16] pawaroti at gmail dot com Description: ------------ Adding 1 month using DateInterval('P1M') sets date to 2015-03-03 if adding from DateTime('2015-01-31') +1 month = 2015-03-03 +2 months = 2015-03-31 +3 months = 2015-05-01 +4 months = 2015-05-31 +5 months = 2015-07-01 +6 months = 2015-07-31 +7 months = 2015-08-31 +8 months = 2015-10-01 +9 months = 2015-10-31 +10 months = 2015-12-01 +11 months = 2015-12-31 +12 months = 2016-01-31 BEFORE: object(DateTime)[5] public 'date' => string '2015-01-31 00:00:00.000000' (length=26) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/Warsaw' (length=13) AFTER object(DateTime)[5] public 'date' => string '2015-03-03 00:00:00.000000' (length=26) public 'timezone_type' => int 3 public 'timezone' => string 'Europe/Warsaw' (length=13) INTERVAL object(DateInterval)[6] public 'y' => int 0 public 'm' => int 1 public 'd' => int 0 public 'h' => int 0 public 'i' => int 0 public 's' => int 0 public 'weekday' => int 0 public 'weekday_behavior' => int 0 public 'first_last_day_of' => int 0 public 'invert' => int 0 public 'days' => boolean false public 'special_type' => int 0 public 'special_amount' => int 0 public 'have_weekday_relative' => int 0 public 'have_special_relative' => int 0 Test script: --------------- for($i=0; $i<=12; $i++) { $data = new DateTime('2015-01-31'); echo $data->add(new DateInterval('P'.$i.'M'))->format('Y-m-d').'<br />'; } Expected result: ---------------- 2015-02-28 2015-03-31 2015-04-30 2015-05-31 2015-06-30 2015-07-31 2015-08-31 2015-09-30 2015-10-31 2015-11-30 2015-12-31 2016-01-31 Actual result: -------------- 2015-03-03 2015-03-31 2015-05-01 2015-05-31 2015-07-01 2015-07-31 2015-08-31 2015-10-01 2015-10-31 2015-12-01 2015-12-31 2016-01-31 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=69468&edit=1

« previous php.bugs (#192131) next »