257

I’m looking for the easiest, cleanest way to add X months to a JavaScript date.

I’d rather not handle the rolling over of the year or have to write my own function.

Is there something built in that can do this?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Chad
  • 23,658
  • 51
  • 191
  • 321
  • 4
    Try adding a method the the date's prototype object, like so---------------Date.prototype.addMonth = function(n) { return new Date(this.setMonth(this.getMonth()+n)); }; – Moises Hidalgo Feb 02 '15 at 17:38
  • 1
    @kr37, Moises Hidalgo's answer will not work correctly if the target month does not have today's day number. bmpasini's answer handles this as well – Alexandru Severin Jan 27 '16 at 14:00
  • Answers here are not very good, better answers are at [*Adding months to a Date in JavaScript*](https://stackoverflow.com/questions/12793045/adding-months-to-a-date-in-javascript). – RobG Mar 04 '20 at 06:32

24 Answers24

365

The following function adds months to a date in JavaScript (source). It takes into account year roll-overs and varying month lengths:

function addMonths(date, months) {
    var d = date.getDate();
    date.setMonth(date.getMonth() + +months);
    if (date.getDate() != d) {
      date.setDate(0);
    }
    return date;
}

// Add 12 months to 29 Feb 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,1,29),12).toString());

// Subtract 1 month from 1 Jan 2017 -> 1 Dec 2016
console.log(addMonths(new Date(2017,0,1),-1).toString());

// Subtract 2 months from 31 Jan 2017 -> 30 Nov 2016
console.log(addMonths(new Date(2017,0,31),-2).toString());

// Add 2 months to 31 Dec 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,11,31),2).toString());

The above solution covers the edge case of moving from a month with a greater number of days than the destination month. eg.

  • Add twelve months to February 29th 2020 (should be February 28th 2021)
  • Add one month to August 31st 2020 (should be September 30th 2020)

If the day of the month changes when applying setMonth, then we know we have overflowed into the following month due to a difference in month length. In this case, we use setDate(0) to move back to the last day of the previous month.

Note: this version of this answer replaces an earlier version (below) that did not gracefully handle different month lengths.

var x = 12; //or whatever offset
var CurrentDate = new Date();
console.log("Current date:", CurrentDate);
CurrentDate.setMonth(CurrentDate.getMonth() + x);
console.log("Date after " + x + " months:", CurrentDate);
Ben Aston
  • 53,718
  • 65
  • 205
  • 331
Chad
  • 23,658
  • 51
  • 191
  • 321
  • 1
    +1 - It does indeed handle the addition of years in the event that `setMonth()` is greater than 11 (remember month ints are zero-based). – Andy E Apr 24 '10 at 21:20
  • 134
    Careful -- this does not work for edge cases, such as adding to the 31st day of most months. For example, Oct 31 2011 + 1 month using this method is Dec 01 2011 using Javascript's standard Date object. – tad Sep 21 '11 at 16:37
  • 7
    Good catch, tad. I'm surprised that I didn't see that. Note that the T-SQL select DATEADD (month , 1, '2011-10-31') yields '2011-11-30', which to me is reasonable. I got 10 up votes with a bad answer. Cool. :-) – Chad Nov 26 '11 at 03:53
  • 2
    Also watch leap years - adding 1 year to Feb 29th in a leap year will give you unpredictable results depending on what language you are using (as a general answer). This is what took down the Microsoft Azure cloud platform for several hours in 2012 – Ben Walding Apr 08 '12 at 21:50
  • 15
    There is an `addMonths` function [here](http://stackoverflow.com/questions/12793045/adding-2-months-to-an-end-date-in-php-javascript) that respects end of month (e.g. `2012-01-31 + 1 month = 2012-02-29` and so on). – RobG Oct 09 '12 at 05:29
  • 4
    just add to set 1st date of every month: today.setHours(0, 0, 0, 0); today.setDate(1); – Mando Apr 04 '14 at 20:28
  • To take care of the issue that @tad raised, you can just do something like `CurrentDate.setDate(Math.min(CurrentDate.getDate(), daysInMonth(CurrentDate.getFullYear(), targetMonth)))` where `daysInMonth` can be defined as something like `new Date(currentDate.GetFullYear, targetMonth + 1, 0).getDate()` – Treviño Nov 30 '16 at 14:26
  • 1
    is '+ +month' a typo? If not ... what is this about? – Mick May 27 '21 at 23:44
  • 2
    @Mick it is an [unary plus](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Unary_plus) and it is the equivalent of `Number(months)` – AlexanderD Dec 21 '21 at 13:09
  • Careful - this function mutates the passed date parameter. – Jannie Theunissen Mar 14 '23 at 15:26
  • Adding 1 month to `new Date(2022, 12, 1)` is returning `Feb 01 2023` – Koray Tugay May 02 '23 at 14:02
67

I'm using moment.js library for date-time manipulations. Sample code to add one month:

var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
anre
  • 3,617
  • 26
  • 33
35

This function handles edge cases and is fast:

function addMonthsUTC (date, count) {
  if (date && count) {
    var m, d = (date = new Date(+date)).getUTCDate()

    date.setUTCMonth(date.getUTCMonth() + count, 1)
    m = date.getUTCMonth()
    date.setUTCDate(d)
    if (date.getUTCMonth() !== m) date.setUTCDate(0)
  }
  return date
}

test:

> d = new Date('2016-01-31T00:00:00Z');
Sat Jan 30 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Sun Feb 28 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Mon Mar 28 2016 18:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T00:00:00.000Z"

Update for non-UTC dates: (by A.Hatchkins)

function addMonths (date, count) {
  if (date && count) {
    var m, d = (date = new Date(+date)).getDate()

    date.setMonth(date.getMonth() + count, 1)
    m = date.getMonth()
    date.setDate(d)
    if (date.getMonth() !== m) date.setDate(0)
  }
  return date
}

test:

> d = new Date(2016,0,31);
Sun Jan 31 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Mon Feb 29 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Tue Mar 29 2016 00:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T06:00:00.000Z"
aMarCruz
  • 2,434
  • 1
  • 16
  • 14
15

Taken from @bmpsini and @Jazaret responses, but not extending prototypes: using plain functions (Why is extending native objects a bad practice?):

function isLeapYear(year) { 
    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 
}

function getDaysInMonth(year, month) {
    return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}

function addMonths(date, value) {
    var d = new Date(date),
        n = date.getDate();
    d.setDate(1);
    d.setMonth(d.getMonth() + value);
    d.setDate(Math.min(n, getDaysInMonth(d.getFullYear(), d.getMonth())));
    return d;
}

Use it:

var nextMonth = addMonths(new Date(), 1);
Community
  • 1
  • 1
Miquel
  • 8,339
  • 11
  • 59
  • 82
13

Considering none of these answers will account for the current year when the month changes, you can find one I made below which should handle it:

The method:

Date.prototype.addMonths = function (m) {
    var d = new Date(this);
    var years = Math.floor(m / 12);
    var months = m - (years * 12);
    if (years) d.setFullYear(d.getFullYear() + years);
    if (months) d.setMonth(d.getMonth() + months);
    return d;
}

Usage:

return new Date().addMonths(2);
Control Freak
  • 12,965
  • 30
  • 94
  • 145
  • This answer doesn't account for adding months were there is no corresponding date in the resulting month (e.g. Jan 31 + 1 month => 2 or 3 Mar). It also seems to think there's a problem with adding more than 12 months to a Date: there isn't. There is no need when adding, say, 13 months, to add 1 year and 1 month. Just add 13 months. – RobG Mar 04 '20 at 06:27
6

From the answers above, the only one that handles the edge cases (bmpasini's from datejs library) has an issue:

var date = new Date("03/31/2015");
var newDate = date.addMonths(1);
console.log(newDate);
// VM223:4 Thu Apr 30 2015 00:00:00 GMT+0200 (CEST)

ok, but:

newDate.toISOString()
//"2015-04-29T22:00:00.000Z"

worse :

var date = new Date("01/01/2015");
var newDate = date.addMonths(3);
console.log(newDate);
//VM208:4 Wed Apr 01 2015 00:00:00 GMT+0200 (CEST)
newDate.toISOString()
//"2015-03-31T22:00:00.000Z"

This is due to the time not being set, thus reverting to 00:00:00, which then can glitch to previous day due to timezone or time-saving changes or whatever...

Here's my proposed solution, which does not have that problem, and is also, I think, more elegant in that it does not rely on hard-coded values.

/**
* @param isoDate {string} in ISO 8601 format e.g. 2015-12-31
* @param numberMonths {number} e.g. 1, 2, 3...
* @returns {string} in ISO 8601 format e.g. 2015-12-31
*/
function addMonths (isoDate, numberMonths) {
    var dateObject = new Date(isoDate),
        day = dateObject.getDate(); // returns day of the month number

    // avoid date calculation errors
    dateObject.setHours(20);

    // add months and set date to last day of the correct month
    dateObject.setMonth(dateObject.getMonth() + numberMonths + 1, 0);

    // set day number to min of either the original one or last day of month
    dateObject.setDate(Math.min(day, dateObject.getDate()));

    return dateObject.toISOString().split('T')[0];
};

Unit tested successfully with:

function assertEqual(a,b) {
    return a === b;
}
console.log(
    assertEqual(addMonths('2015-01-01', 1), '2015-02-01'),
    assertEqual(addMonths('2015-01-01', 2), '2015-03-01'),
    assertEqual(addMonths('2015-01-01', 3), '2015-04-01'),
    assertEqual(addMonths('2015-01-01', 4), '2015-05-01'),
    assertEqual(addMonths('2015-01-15', 1), '2015-02-15'),
    assertEqual(addMonths('2015-01-31', 1), '2015-02-28'),
    assertEqual(addMonths('2016-01-31', 1), '2016-02-29'),
    assertEqual(addMonths('2015-01-01', 11), '2015-12-01'),
    assertEqual(addMonths('2015-01-01', 12), '2016-01-01'),
    assertEqual(addMonths('2015-01-01', 24), '2017-01-01'),
    assertEqual(addMonths('2015-02-28', 12), '2016-02-28'),
    assertEqual(addMonths('2015-03-01', 12), '2016-03-01'),
    assertEqual(addMonths('2016-02-29', 12), '2017-02-28')
);
pansay
  • 687
  • 8
  • 11
  • Be careful! `setMonth(month+1, 0)` won't give you the last day of the `month`, at least not on node and v8. `addMonths('2016-01-31', 1)` returns `2016-03-01`, instead of `2016-02-29` as expected. – ushuz Jan 02 '22 at 00:14
4
d = new Date();

alert(d.getMonth()+1);

Months have a 0-based index, it should alert(4) which is 5 (may);

Ben
  • 16,275
  • 9
  • 45
  • 63
4

Simple solution: 2678400000 is 31 day in milliseconds

var oneMonthFromNow = new Date((+new Date) + 2678400000);

Update:

Use this data to build our own function:

  • 2678400000 - 31 day
  • 2592000000 - 30 days
  • 2505600000 - 29 days
  • 2419200000 - 28 days
dr.dimitru
  • 2,645
  • 1
  • 27
  • 36
3

As most of the answers highlighted, we could use setMonth() method together with getMonth() method to add specific number of months to a given date.

Example: (as mentioned by @ChadD in his answer. )

var x = 12; //or whatever offset 
var CurrentDate = new Date();
CurrentDate.setMonth(CurrentDate.getMonth() + x);

But we should carefully use this solution as we will get trouble with edge cases.

To handle edge cases, answer which is given in following link is helpful.

https://stackoverflow.com/a/13633692/3668866

Community
  • 1
  • 1
Sampath Dilhan
  • 749
  • 6
  • 17
2

Just to add on to the accepted answer and the comments.

var x = 12; //or whatever offset
var CurrentDate = new Date();

//For the very rare cases like the end of a month
//eg. May 30th - 3 months will give you March instead of February
var date = CurrentDate.getDate();
CurrentDate.setDate(1);
CurrentDate.setMonth(CurrentDate.getMonth()+X);
CurrentDate.setDate(date);
iamjt
  • 79
  • 6
2

I wrote this alternative solution which works fine to me. It is useful when you wish calculate the end of a contract. For example, start=2016-01-15, months=6, end=2016-7-14 (i.e. last day - 1):

<script>
function daysInMonth(year, month)
{
    return new Date(year, month + 1, 0).getDate();
}

function addMonths(date, months)
{
    var target_month = date.getMonth() + months;
    var year = date.getFullYear() + parseInt(target_month / 12);
    var month = target_month % 12;
    var day = date.getDate();
    var last_day = daysInMonth(year, month);
    if (day > last_day)
    {
        day = last_day;
    }
    var new_date = new Date(year, month, day);
    return new_date;
}

var endDate = addMonths(startDate, months);
</script>

Examples:

addMonths(new Date("2016-01-01"), 1); // 2016-01-31
addMonths(new Date("2016-01-01"), 2); // 2016-02-29 (2016 is a leap year)
addMonths(new Date("2016-01-01"), 13); // 2017-01-31
addMonths(new Date("2016-01-01"), 14); // 2017-02-28
Trevor
  • 16,080
  • 9
  • 52
  • 83
David Ragazzi
  • 300
  • 2
  • 6
2

This works for all edge cases. The weird calculation for newMonth handles negative months input. If the new month does not match the expected month (like 31 Feb), it will set the day of month to 0, which translates to "end of previous month":

function dateAddCalendarMonths(date, months) {
    monthSum = date.getMonth() + months;
    newMonth = (12 + (monthSum % 12)) % 12;
    newYear = date.getFullYear() + Math.floor(monthSum / 12);
    newDate = new Date(newYear, newMonth, date.getDate());
    return (newDate.getMonth() != newMonth)
        ? new Date(newDate.setDate(0))
        : newDate;
}
Riegardt Steyn
  • 5,431
  • 2
  • 34
  • 49
2

I changed the accepted answer a bit to keep the original date intact, as I think it should in a function like this.

function addMonths(date, months) {
    let newDate = new Date(date);
    var day = newDate.getDate();
    newDate.setMonth(newDate.getMonth() + +months);
    if (newDate.getDate() != day)
        newDate.setDate(0);
    return newDate;
}
pbotas
  • 349
  • 3
  • 13
0

The following is an example of how to calculate a future date based on date input (membershipssignup_date) + added months (membershipsmonths) via form fields.

The membershipsmonths field has a default value of 0

Trigger link (can be an onchange event attached to membership term field):

<a href="#" onclick="calculateMshipExp()"; return false;">Calculate Expiry Date</a>

function calculateMshipExp() {

var calcval = null;

var start_date = document.getElementById("membershipssignup_date").value;
var term = document.getElementById("membershipsmonths").value;  // Is text value

var set_start = start_date.split('/');  

var day = set_start[0];  
var month = (set_start[1] - 1);  // January is 0 so August (8th month) is 7
var year = set_start[2];
var datetime = new Date(year, month, day);
var newmonth = (month + parseInt(term));  // Must convert term to integer
var newdate = datetime.setMonth(newmonth);

newdate = new Date(newdate);
//alert(newdate);

day = newdate.getDate();
month = newdate.getMonth() + 1;
year = newdate.getFullYear();

// This is British date format. See below for US.
calcval = (((day <= 9) ? "0" + day : day) + "/" + ((month <= 9) ? "0" + month : month) + "/" + year);

// mm/dd/yyyy
calcval = (((month <= 9) ? "0" + month : month) + "/" + ((day <= 9) ? "0" + day : day) + "/" + year);

// Displays the new date in a <span id="memexp">[Date]</span> // Note: Must contain a value to replace eg. [Date]
document.getElementById("memexp").firstChild.data = calcval;

// Stores the new date in a <input type="hidden" id="membershipsexpiry_date" value="" name="membershipsexpiry_date"> for submission to database table
document.getElementById("membershipsexpiry_date").value = calcval;
}
j0k
  • 22,600
  • 28
  • 79
  • 90
John G
  • 9
  • 4
0

As demonstrated by many of the complicated, ugly answers presented, Dates and Times can be a nightmare for programmers using any language. My approach is to convert dates and 'delta t' values into Epoch Time (in ms), perform any arithmetic, then convert back to "human time."

// Given a number of days, return a Date object
//   that many days in the future. 
function getFutureDate( days ) {

    // Convert 'days' to milliseconds
    var millies = 1000 * 60 * 60 * 24 * days;

    // Get the current date/time
    var todaysDate = new Date();

    // Get 'todaysDate' as Epoch Time, then add 'days' number of mSecs to it
    var futureMillies = todaysDate.getTime() + millies;

    // Use the Epoch time of the targeted future date to create
    //   a new Date object, and then return it.
    return new Date( futureMillies );
}

// Use case: get a Date that's 60 days from now.
var twoMonthsOut = getFutureDate( 60 );

This was written for a slightly different use case, but you should be able to easily adapt it for related tasks.

EDIT: Full source here!

Dan Ahlquist
  • 161
  • 1
  • 6
0

Sometimes useful create date by one operator like in BIRT parameters

I made 1 month back with:

new Date(new Date().setMonth(new Date().getMonth()-1));   
Peter O.
  • 32,158
  • 14
  • 82
  • 96
0

Easy, simplest

function addMonths(date, months) {date.setMonth(date.getMonth() + months); return date;};

Use it as

 alert(new Date().toLocaleString()); //will say today
 alert(addMonths(new Date(),12).toLocaleString()); //will say next year, same day and month
Devmyselz
  • 346
  • 3
  • 13
0

Looking for something in typescript?

export const addMonths = (inputDate: Date | string, monthsToAdd: number): Date => {
  const date = new Date(inputDate);
  if (!monthsToAdd) {
    return date;
  }
  const dayOfMonth = date.getDate(); 
  const endOfDesiredMonth = new Date(date.getTime());
  endOfDesiredMonth.setMonth(date.getMonth() + monthsToAdd + 1, 0);
  const daysInMonth = endOfDesiredMonth.getDate();
  if (dayOfMonth >= daysInMonth) {
    return endOfDesiredMonth;
  } else {
    date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
    return date;
  }
}
Segun Kess
  • 243
  • 4
  • 7
0

A simple answer can be :

function addMonthsToDate(date, numMonths){
    // Add months
    date.setMonth(date.getMonth() + numMonths);
    
    // Zero the time component
    date.setHours(0, 0, 0, 0);
    return date;
}

This can be called - to add two months:

console.log(addMonthsToDate(new Date(),2));
Uday Shankar
  • 438
  • 1
  • 3
  • 16
-1
addDateMonate : function( pDatum, pAnzahlMonate )
{
    if ( pDatum === undefined )
    {
        return undefined;
    }

    if ( pAnzahlMonate === undefined )
    {
        return pDatum;
    }

    var vv = new Date();

    var jahr = pDatum.getFullYear();
    var monat = pDatum.getMonth() + 1;
    var tag = pDatum.getDate();

    var add_monate_total = Math.abs( Number( pAnzahlMonate ) );

    var add_jahre = Number( Math.floor( add_monate_total / 12.0 ) );
    var add_monate_rest = Number( add_monate_total - ( add_jahre * 12.0 ) );

    if ( Number( pAnzahlMonate ) > 0 )
    {
        jahr += add_jahre;
        monat += add_monate_rest;

        if ( monat > 12 )
        {
            jahr += 1;
            monat -= 12;
        }
    }
    else if ( Number( pAnzahlMonate ) < 0 )
    {
        jahr -= add_jahre;
        monat -= add_monate_rest;

        if ( monat <= 0 )
        {
            jahr = jahr - 1;
            monat = 12 + monat;
        }
    }

    if ( ( Number( monat ) === 2 ) && ( Number( tag ) === 29 ) )
    {
        if ( ( ( Number( jahr ) % 400 ) === 0 ) || ( ( Number( jahr ) % 100 ) > 0 ) && ( ( Number( jahr ) % 4 ) === 0 ) )
        {
            tag = 29;
        }
        else
        {
            tag = 28;
        }
    }

    return new Date( jahr, monat - 1, tag );
}


testAddMonate : function( pDatum , pAnzahlMonate )
{
    var datum_js = fkDatum.getDateAusTTMMJJJJ( pDatum );
    var ergebnis = fkDatum.addDateMonate( datum_js, pAnzahlMonate );

    app.log( "addDateMonate( \"" + pDatum + "\", " + pAnzahlMonate + " ) = \"" + fkDatum.getStringAusDate( ergebnis ) + "\"" );
},


test1 : function()
{
    app.testAddMonate( "15.06.2010",    10 );
    app.testAddMonate( "15.06.2010",   -10 );
    app.testAddMonate( "15.06.2010",    37 );
    app.testAddMonate( "15.06.2010",   -37 );
    app.testAddMonate( "15.06.2010",  1234 );
    app.testAddMonate( "15.06.2010", -1234 );
    app.testAddMonate( "15.06.2010",  5620 );
    app.testAddMonate( "15.06.2010", -5120 );

}
ea234
  • 1
  • 2
-1

All these seem way too complicated and I guess it gets into a debate about what exactly adding "a month" means. Does it mean 30 days? Does it mean from the 1st to the 1st? From the last day to the last day?

If the latter, then adding a month to Feb 27th gets you to March 27th, but adding a month to Feb 28th gets you to March 31st (except in leap years, where it gets you to March 28th). Then subtracting a month from March 30th gets you... Feb 27th? Who knows...

For those looking for a simple solution, just add milliseconds and be done.

function getDatePlusDays(dt, days) {
  return new Date(dt.getTime() + (days * 86400000));
}

or

Date.prototype.addDays = function(days) {
  this = new Date(this.getTime() + (days * 86400000));
};
jdforsythe
  • 1,057
  • 12
  • 22
  • I feel like it is clear that "adding X months" means the month increases by X. It's true that your answer has less algorithmic steps to code, but unfortunately I feel that accuracy trumps simplicity. When people look for an answer, they'll want 'July 31 2016' to become 'Augest 31 2016'. And this wouldn't do that. Besides, if you really want simplicity at the cost of accuracy, why not stick with `d.setMonth(d.getMonth()+1)`? So this isn't even the simplest idea. – Alexander Bird Jun 06 '16 at 02:36
  • This also doesn't accommodate daylight saving, where not all days are 24 hours (or 8.64e7 milliseconds) long. – RobG Jan 11 '17 at 20:19
-1

Easiest solution is:

const todayDate = Date.now();
return new Date(todayDate + 1000 * 60 * 60 * 24 * 30* X); 

where X is the number of months we want to add.

Armen Stepanyan
  • 1,618
  • 13
  • 29
RameshD
  • 912
  • 7
  • 6
-1

I have done by using Moment Js Library Refs: https://momentjs.com/

   startDate = new Date()
   endDate = moment(startDate).add(2, "Months").format("YYYY-MM-DD")
   endDate= new Date (endDate)
Zahid
  • 54
  • 2
  • 4
  • 2
    Please add some details. I tried `getToday()` and it returns an error. The function `moment()` is unknown as well. Are you using a library to have these functions? – surfmuggle Dec 16 '22 at 23:30
  • @surfmuggle getToday() = = new Date() also Please use Moment JS Library – Zahid Dec 18 '22 at 19:14
-3
var a=new Date();
a.setDate(a.getDate()+5);

As above stated method, you can add month to Date function.

user1791574
  • 1,729
  • 2
  • 16
  • 30