[php] increment date by one month

Let's say I have a date in the following format: 2010-12-11 (year-mon-day)

With PHP, I want to increment the date by one month, and I want the year to be automatically incremented, if necessary (i.e. incrementing from December 2012 to January 2013).

Regards.

This question is related to php date

The answer is


I use this way:-

 $occDate='2014-01-28';
 $forOdNextMonth= date('m', strtotime("+1 month", strtotime($occDate)));
//Output:- $forOdNextMonth=02


/*****************more example****************/
$occDate='2014-12-28';

$forOdNextMonth= date('m', strtotime("+1 month", strtotime($occDate)));
//Output:- $forOdNextMonth=01

//***********************wrong way**********************************//
$forOdNextMonth= date('m', strtotime("+1 month", $occDate));
  //Output:- $forOdNextMonth=02; //instead of $forOdNextMonth=01;
//******************************************************************//

Thanks Jason, your post was very helpful. I reformatted it and added more comments to help me understand it all. In case that helps anyone, I have posted it here:

function cycle_end_date($cycle_start_date, $months) {
    $cycle_start_date_object = new DateTime($cycle_start_date);

    //Find the date interval that we will need to add to the start date
    $date_interval = find_date_interval($months, $cycle_start_date_object);

    //Add this date interval to the current date (the DateTime class handles remaining complexity like year-ends)
    $cycle_end_date_object = $cycle_start_date_object->add($date_interval);

    //Subtract (sub) 1 day from date
    $cycle_end_date_object->sub(new DateInterval('P1D')); 

    //Format final date to Y-m-d
    $cycle_end_date = $cycle_end_date_object->format('Y-m-d'); 

    return $cycle_end_date;
}

//Find the date interval we need to add to start date to get end date
function find_date_interval($n_months, DateTime $cycle_start_date_object) {
    //Create new datetime object identical to inputted one
    $date_of_last_day_next_month = new DateTime($cycle_start_date_object->format('Y-m-d'));

    //And modify it so it is the date of the last day of the next month
    $date_of_last_day_next_month->modify('last day of +'.$n_months.' month');

    //If the day of inputted date (e.g. 31) is greater than last day of next month (e.g. 28)
    if($cycle_start_date_object->format('d') > $date_of_last_day_next_month->format('d')) {
        //Return a DateInterval object equal to the number of days difference
        return $cycle_start_date_object->diff($date_of_last_day_next_month);
    //Otherwise the date is easy and we can just add a month to it
    } else {
        //Return a DateInterval object equal to a period (P) of 1 month (M)
        return new DateInterval('P'.$n_months.'M');
    }
}

$cycle_start_date = '2014-01-31'; // select date in Y-m-d format
$n_months = 1; // choose how many months you want to move ahead
$cycle_end_date = cycle_end_date($cycle_start_date, $n_months); // output: 2014-07-02

Please first you set your date format as like 12-12-2012

After use this function it's work properly;

$date =  date('d-m-Y',strtotime("12-12-2012 +2 Months");

Here 12-12-2012 is your date and +2 Months is increment of the month;

You also increment of Year, Date

strtotime("12-12-2012 +1 Year");

Ans is 12-12-2013


strtotime( "+1 month", strtotime( $time ) );

this returns a timestamp that can be used with the date function


 <?php
              $selectdata ="select fromd,tod  from register where username='$username'";
            $q=mysqli_query($conm,$selectdata);
            $row=mysqli_fetch_array($q);

            $startdate=$row['fromd']; 
            $stdate=date('Y', strtotime($startdate));  

            $endate=$row['tod']; 
            $enddate=date('Y', strtotime($endate));  

            $years = range ($stdate,$enddate);
            echo '<select name="years" class="form-control">';
            echo '<option>SELECT</option>';
            foreach($years as $year)
              {   echo '<option value="'.$year.'"> '.$year.' </option>';  }
                echo '</select>'; ?>

If you want to get the date of one month from now you can do it like this

echo date('Y-m-d', strtotime('1 month'));

If you want to get the date of two months from now, you can achieve that by doing this

echo date('Y-m-d', strtotime('2 month'));

And so on, that's all.


function dayOfWeek($date){
    return DateTime::createFromFormat('Y-m-d', $date)->format('N');
}

Usage examples:

echo dayOfWeek(2016-12-22);
// "4"
echo dayOfWeek(date('Y-m-d'));
// "4"

For anyone looking for an answer to any date format.

echo date_create_from_format('d/m/Y', '15/04/2017')->add(new DateInterval('P1M'))->format('d/m/Y');

Just change the date format.


Use DateTime::add.

$start = new DateTime("2010-12-11", new DateTimeZone("UTC"));
$month_later = clone $start;
$month_later->add(new DateInterval("P1M"));

I used clone because add modifies the original object, which might not be desired.


I needed similar functionality, except for a monthly cycle (plus months, minus 1 day). After searching S.O. for a while, I was able to craft this plug-n-play solution:

function add_months($months, DateTime $dateObject) 
    {
        $next = new DateTime($dateObject->format('Y-m-d'));
        $next->modify('last day of +'.$months.' month');

        if($dateObject->format('d') > $next->format('d')) {
            return $dateObject->diff($next);
        } else {
            return new DateInterval('P'.$months.'M');
        }
    }

function endCycle($d1, $months)
    {
        $date = new DateTime($d1);

        // call second function to add the months
        $newDate = $date->add(add_months($months, $date));

        // goes back 1 day from date, remove if you want same day of month
        $newDate->sub(new DateInterval('P1D')); 

        //formats final date to Y-m-d form
        $dateReturned = $newDate->format('Y-m-d'); 

        return $dateReturned;
    }

Example:

$startDate = '2014-06-03'; // select date in Y-m-d format
$nMonths = 1; // choose how many months you want to move ahead
$final = endCycle($startDate, $nMonths); // output: 2014-07-02

Just updating the answer with simple method for find the date after no of months. As the best answer marked doesn't give the correct solution.

<?php

    $date = date('2020-05-31');
    $current = date("m",strtotime($date));
    $next = date("m",strtotime($date."+1 month"));
    if($current==$next-1){
        $needed = date('Y-m-d',strtotime($date." +1 month"));
    }else{
        $needed = date('Y-m-d', strtotime("last day of next month",strtotime($date)));
    }
    echo "Date after 1 month from 2020-05-31 would be : $needed";

?>

You can use DateTime::modify like this :

$date = new DateTime('2010-12-11');
$date->modify('+1 month');

See documentations :

http://php.net/manual/fr/datetime.modify.php

http://php.net/manual/fr/class.datetime.php


UPDATE january 2021 : correct mistakes raised by comments

This solution has some problems for months with 31 days like May etc.

Exemple : this jumps from 31st May to 1st July which is incorrect.

To correct that, you can create this custom function

function addMonths($date,$months){
    
    $init=clone $date;
    $modifier=$months.' months';
    $back_modifier =-$months.' months';
   
    $date->modify($modifier);
    $back_to_init= clone $date;
    $back_to_init->modify($back_modifier);
   
    while($init->format('m')!=$back_to_init->format('m')){
        $date->modify('-1 day')    ;
        $back_to_init= clone $date;
        $back_to_init->modify($back_modifier);   
    }
}

Then you can use it like that :

$date = new DateTime('2010-05-31');
addMonths($date, 1);
print_r($date);
//DateTime Object ( [date] => 2010-06-30 00:00:00.000000 [timezone_type] => 3 [timezone] => Europe/Berlin ) 

This solution was found in PHP.net posted by jenspj : https://www.php.net/manual/fr/datetime.modify.php#107592


(date('d') > 28) ? date("mdY", strtotime("last day of next month")) : date("mdY", strtotime("+1 month"));

This will compensate for February and the other 31 day months. You could of course do a lot more checking to to get more exact for 'this day next month' relative date formats (which does not work sadly, see below), and you could just as well use DateTime.

Both DateInterval('P1M') and strtotime("+1 month") are essentially blindly adding 31 days regardless of the number of days in the following month.

  • 2010-01-31 => March 3rd
  • 2012-01-31 => March 2nd (leap year)

//ECHO MONTHS BETWEEN TWO TIMESTAMPS
$my_earliest_timestamp = 1532095200;
$my_latest_timestamp = 1554991200;

echo '<pre>';
echo "Earliest timestamp: ". date('c',$my_earliest_timestamp) ."\r\n";
echo "Latest timestamp: " .date('c',$my_latest_timestamp) ."\r\n\r\n";

echo "Month start of earliest timestamp: ". date('c',strtotime('first day of '. date('F Y',$my_earliest_timestamp))) ."\r\n";
echo "Month start of latest timestamp: " .date('c',strtotime('first day of '. date('F Y',$my_latest_timestamp))) ."\r\n\r\n";

echo "Month end of earliest timestamp: ". date('c',strtotime('last day of '. date('F Y',$my_earliest_timestamp)) + 86399) ."\r\n";
echo "Month end of latest timestamp: " .date('c',strtotime('last day of '. date('F Y',$my_latest_timestamp)) + 86399) ."\r\n\r\n";

$sMonth = strtotime('first day of '. date('F Y',$my_earliest_timestamp));
$eMonth = strtotime('last day of '. date('F Y',$my_earliest_timestamp)) + 86399;
$xMonth = strtotime('+1 month', strtotime('first day of '. date('F Y',$my_latest_timestamp)));

while ($eMonth < $xMonth) {
    echo "Things from ". date('Y-m-d',$sMonth) ." to ". date('Y-m-d',$eMonth) ."\r\n\r\n";
    $sMonth = $eMonth + 1; //add 1 second to bring forward last date into first second of next month.
    $eMonth = strtotime('last day of '. date('F Y',$sMonth)) + 86399;
}

All presented solutions are not working properly.
strtotime() and DateTime::add or DateTime::modify give sometime invalid results.
Examples:
- 31.08.2019 + 1 month gives 01.10.2019 instead 30.09.2019
- 29.02.2020 + 1 year gives 01.03.2021 instead 28.02.2021
(tested on PHP 5.5, PHP 7.3)

Below is my function based on idea posted by Angelo that solves the problem:

// $time - unix time or date in any format accepted by strtotime() e.g. 2020-02-29  
// $days, $months, $years - values to add
// returns new date in format 2021-02-28
function addTime($time, $days, $months, $years)
{
    // Convert unix time to date format
    if (is_numeric($time))
    $time = date('Y-m-d', $time);

    try
    {
        $date_time = new DateTime($time);
    }
    catch (Exception $e)
    {
        echo $e->getMessage();
        exit;
    }

    if ($days)
    $date_time->add(new DateInterval('P'.$days.'D'));

    // Preserve day number
    if ($months or $years)
    $old_day = $date_time->format('d');

    if ($months)
    $date_time->add(new DateInterval('P'.$months.'M'));

    if ($years)
    $date_time->add(new DateInterval('P'.$years.'Y'));

    // Patch for adding months or years    
    if ($months or $years)
    {
        $new_day = $date_time->format("d");

        // The day is changed - set the last day of the previous month
        if ($old_day != $new_day)
        $date_time->sub(new DateInterval('P'.$new_day.'D'));
    }
    // You can chage returned format here
    return $date_time->format('Y-m-d');
}

Usage examples:

echo addTime('2020-02-29', 0, 0, 1); // add 1 year (result: 2021-02-28)
echo addTime('2019-08-31', 0, 1, 0); // add 1 month (result: 2019-09-30)
echo addTime('2019-03-15', 12, 2, 1); // add 12 days, 2 months, 1 year (result: 2019-09-30)

$date = strtotime("2017-12-11");
$newDate = date("Y-m-d", strtotime("+1 month", $date));

If you want to increment by days you can also do it

$date = strtotime("2017-12-11");
$newDate = date("Y-m-d", strtotime("+5 day", $date));

put a date in input box then click the button get day from date in jquery

$(document).ready( function() {
    $("button").click(function(){   
    var day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
    var a = new Date();
    $(".result").text(day[a.getDay()]);

    });  
             });