我正在寻找最简单、最干净的方法将X个月添加到JavaScript日期中。

我宁愿不处理一年的滚动,也不愿意自己写函数。

有什么内置的东西可以做到这一点吗?


当前回答

d = new Date();

alert(d.getMonth()+1);

月份有一个基于0的指数,它应该警报(4),这是5(五月);

其他回答

下面的函数在JavaScript中为日期添加月份(源代码)。它考虑了年的滚动和不同的月份长度:

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

上面的解决方案涵盖了从一个月移动的天数多于目标月份的边缘情况。如。

增加12个月至2020年2月29日(应该是2021年2月28日) 增加一个月至2020年8月31日(应该是2020年9月30日)

如果在应用setMonth时,月份的日期发生了变化,那么由于月份长度的差异,我们知道已经溢出到下一个月。在本例中,我们使用setDate(0)返回到上个月的最后一天。

注意:这个答案的这个版本取代了之前的版本(下面),之前的版本没有优雅地处理不同的月份长度。

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

考虑到这些答案中没有一个会在月份变化时解释当年的情况,你可以在下面找到我做的一个答案,它应该可以处理这个问题:

方法:

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;
}

用法:

return new Date().addMonths(2);

这个函数处理边缘情况,并且速度很快:

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
}

测试:

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

非utc日期更新:(由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
}

测试:

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

从上面的答案,唯一一个处理边缘情况(bmpasini的datejs库)有一个问题:

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)

好吧,但是:

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

更糟糕的是:

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"

这是由于时间没有设置,因此返回到00:00:00,然后可能由于时区或节省时间的更改或其他原因而故障到前一天…

下面是我提出的解决方案,它不存在这个问题,而且我认为它更优雅,因为它不依赖于硬编码的值。

/**
* @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];
};

单元测试成功,使用:

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')
);
var a=new Date();
a.setDate(a.getDate()+5);

如上所述的方法,您可以添加月到日期功能。