Bug #69468 [Opn->Nab]: DateTime->add problem for 2015-01-31
| From: | requinix@php.net | 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