JavaScript function to add X months to a date

后端 未结 19 2332
星月不相逢
星月不相逢 2020-11-22 02:44

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.<

19条回答
  •  日久生厌
    2020-11-22 03:07

    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')
    );
    

提交回复
热议问题