1

I need a method for adding some number of months to any date in PHP. I know how to do this in MySQL but not in PHP. Here's my attempt:

MySQL:

    SELECT DATE_ADD( '2011-12-29', INTERVAL 2
    MONTH ) // Output "2012-02-29"

    SELECT DATE_ADD( '2011-12-30', INTERVAL 2
    MONTH )  // output "2012-02-29"

    SELECT DATE_ADD( '2011-12-31', INTERVAL 2
    MONTH )  // output "2012-02-29"

PHP:

    $date = date_create('2011-12-29');
    $date->modify("+1 month");
    echo $date->format("Y-m-d");
    // Output is "2012-01-29" -- this is correct 

    $date = date_create('2011-12-30');
    $date->modify("+2 month");
    echo $date->format("Y-m-d");
    // Output is "2012-03-01" -- I need the answer like "2012-02-29" 

    $date = date_create('2011-12-31');
    $date->modify("+2 month");
    echo $date->format("Y-m-d");
    // Output is "2012-03-02" -- I need the answer like "2012-02-29" 

The MySQL output is correct. I need the same output in PHP.

Nathaniel Waisbrot
  • 23,261
  • 7
  • 71
  • 99
Thambuleena
  • 253
  • 2
  • 7
  • 1
    http://stackoverflow.com/questions/3602405/php-datetimemodify-adding-and-subtracting-months –  Jan 03 '12 at 07:53
  • this might help you http://stackoverflow.com/questions/8085886/add-days-to-a-date-in-php and http://stackoverflow.com/questions/3812929/adding-months-to-a-existing-date – Arfeen Jan 03 '12 at 07:53
  • you are going to have to roll your own, because 2011-12-31 + 2 months is not 12-02-29... there isn't anything in PHP that will ready made round down if you are above 29. – dqhendricks Jan 03 '12 at 07:56
  • @Dagon that doesn't help the above question at all... – dqhendricks Jan 03 '12 at 07:59
  • looks practicality identical to me. –  Jan 03 '12 at 08:01

4 Answers4

2

If you use PHP5 >= 5.3, all you need to do is use

$date->modify("last day of +2 months");

as suggested in other answers. But if you use 5.2 you could try altering your code like this:

Class DateTimeM Extends DateTime
{
    public function modify ($modify)
    {
            $day = $this->format ('d');
            $buf = new DateTime ($this->format ('Y-m-01\TH:i:sO'));
            $buf->modify ($modify);
            if ($day > $buf->format ('t'))
            {
                    $this->setDate ($buf->format ('Y'), $buf->format ('m'), $buf->format ('t'));
            }
            else
            {
                    $this->setDate ($buf->format ('Y'), $buf->format ('m'), $day);
            }
            $this->setTime ($buf->format ('H'), $buf->format ('i'), $buf->format ('s'));

            return $this;
      }
}

$date = new DateTimeM ('2011-12-29');
$date->modify("+2 month");
echo $date->format("Y-m-d");

I suggest adding the class definition to a separate file and require_once() it. Switch from date_create() to using the new class's object constructor. The new class's modify() method will modify the date using the first day of the original given month instead of the last and check if the original given day of month is larger than the new month's number of days.

A benefit of this approach is that it will work for say $date->modify ('2 year 2 month') as well.

cmbuckley
  • 40,217
  • 9
  • 77
  • 91
zrvan
  • 7,533
  • 1
  • 22
  • 23
1

Here's a solution that might do the job for you:

function addMonths(DateTime $date, $months) {
    $last = clone $date;
    $last = $last->modify("last day of +$months months")->getTimestamp();

    $default = clone $date;
    $default = $default->modify("+$months months")->getTimestamp();

    return $date->setTimestamp(min($last, $default));
}

$date = new DateTime('2011-12-31');
$laterDate = addMonths($date, 2);

This will work regardless of which day of the month you start with.

cmbuckley
  • 40,217
  • 9
  • 77
  • 91
0

Hope it surely helps you.

I just try with adding days instead of adding months

$MonthAdded = strtotime("+60 days",strtotime('2011-12-31'));
echo "After adding month: ".date('Y-m-d', $MonthAdded)."<br>";

Output:

After adding month: 2012-02-29
Muthu Krishnan
  • 1,664
  • 2
  • 10
  • 15
  • That's just a lucky coincidence - January has 31 days, this February has 29 days, so 31 + 29 = 60. For `strtotime("+60 days",strtotime("2012-12-31"));` you should get 2013-03-01. – WWW Jan 03 '12 at 14:37
0

Read the link Dagon posted in the comments to your question. Extrapolating on the answer there, I tried this and it works:

$d = new DateTime("2011-12-31");
$d->modify("last day of +2 months");
echo $d->format("Y-m-d");
// result is 2012-02-29

$d = new DateTime("2012-12-31");
$d->modify("last day of +2 months");
echo $d->format("Y-m-d");
// result is 2013-02-28
WWW
  • 9,734
  • 1
  • 29
  • 33
  • Works fine if the last day is wanted, but chokes if `$d = new DateTime("2011-12-01");`, and the question seems to suggest it wants a solution for any date. – cmbuckley Jan 03 '12 at 15:02
  • I tested it on PHP 5.3.5 and it works fine if I use 2011-12-01 as a date. Judging from the first three examples the author gave (12/29, 12/30, and 12/31, all expecting the last day of February as the answer) I took it to mean that the author did, in fact, want the last day of the month two months from the given date. – WWW Jan 03 '12 at 15:08
  • Though I understand where you're coming from, cbuckley. – WWW Jan 03 '12 at 15:09
  • I think the OP's intention is to mimic MySQL's INTERVAL behaviour for all possible dates, but I may be mistaken. – cmbuckley Jan 03 '12 at 15:13