0

So, I am working with subtracting relative months. According to the documentation:

Relative month values are calculated based on the length of months that they pass through. An example would be "+2 month 2011-11-30", which would produce "2012-01-30". This is due to November being 30 days in length, and December being 31 days in length, producing a total of 61 days.

I understand why the example when adding months, but I don't understand why 2014-12-31 -1 month produces 2014-12-01. Its 31 days in December, shouldn't the result be the last of November?

Example code. Function 1 produces the result I was expecting from function 2 and 3.

//Func 1
$date = '2014-12-31 23:59:59'; //YYYY-MM-DD
$days = 0;
echo $date.'<br>';
for ($i = 1; $i < 13; $i++) {
    $days += cal_days_in_month(CAL_GREGORIAN, (13-$i), 2014);
    echo date("Y-m-d H:i:s", strtotime("-$days days", strtotime($date))).'<br>';
}
echo "<br><br>";
//Func 2
$date = '2014-12-31 23:59:59'; //YYYY-MM-DD
echo $date.'<br>';
for ($i = 1; $i < 13; $i++) {
    echo date("Y-m-d H:i:s", strtotime("-$i months", strtotime($date))).'<br>';
}
//Func 3
echo "<br><br>";
$dateObj = new DateTime("2014-12-31 23:59:59");
echo $dateObj->format("Y-m-d H:i:s").'<br>';
$dateIntervalObj = new DateInterval("P1M");
for ($i = 0; $i < 12; $i++) {
    echo $dateObj->format("Y-m-d H:i:s").'<br>';
    $dateObj->sub($dateIntervalObj);
}

Result:

2014-12-31 23:59:59
2014-11-30 23:59:59
2014-10-31 23:59:59
2014-09-30 23:59:59
2014-08-31 23:59:59
2014-07-31 23:59:59
2014-06-30 23:59:59
2014-05-31 23:59:59
2014-04-30 23:59:59
2014-03-31 23:59:59
2014-02-28 23:59:59
2014-01-31 23:59:59
2013-12-31 23:59:59


2014-12-31 23:59:59
2014-12-01 23:59:59
2014-10-31 23:59:59
2014-10-01 23:59:59
2014-08-31 23:59:59
2014-07-31 23:59:59
2014-07-01 23:59:59
2014-05-31 23:59:59
2014-05-01 23:59:59
2014-03-31 23:59:59
2014-03-03 23:59:59
2014-01-31 23:59:59
2013-12-31 23:59:59


2014-12-31 23:59:59
2014-12-31 23:59:59
2014-12-01 23:59:59
2014-11-01 23:59:59
2014-10-01 23:59:59
2014-09-01 23:59:59
2014-08-01 23:59:59
2014-07-01 23:59:59
2014-06-01 23:59:59
2014-05-01 23:59:59
2014-04-01 23:59:59
2014-03-01 23:59:59
2014-02-01 23:59:59
user3332631
  • 334
  • 1
  • 3
  • 11

1 Answers1

0

seems to always round up:

2014-10-31 +1 month => 2014-12-01    // this makes sense
2014-12-31 -1 month => 2014-12-01    // this doesn't

in both cases if the day does not exist, it uses the day after it.

Andras
  • 2,995
  • 11
  • 17
  • 1
    Why does this seem super weird `2014-03-31 23:59:59 -1 month => 2014-03-03 23:59:59`? – user3332631 Dec 05 '14 at 05:50
  • ooh, nice catch, good thinking! looks like a bug in php now -- if the date doesn't exist, they add the missing number of days to the beginning of the next month and use that. so if no 31st, use the 1st. If no 30th _or_ 29th, use the 2nd?? That no longer makes sense. – Andras Dec 05 '14 at 05:58
  • It isn't a bug. That is how the PHP devs decided to deal with this problem. Anyway it was done would be wrong for somebody. – vascowhite Dec 05 '14 at 06:05
  • yeah, I've made decisions like that myself, but QA still called it a bug :-) – Andras Dec 05 '14 at 06:08
  • 1
    In function 2, if I change the strtotime function to `last day of -$i months` it produces the same result as function 1. – user3332631 Dec 05 '14 at 06:29