将 X 个月添加到日期的 JavaScript 函数

IT技术 javascript date
2021-01-30 15:31:13

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

我宁愿不处理年份的滚动或必须编写自己的函数

是否有内置的东西可以做到这一点?

6个回答

以下函数将月份添加到 JavaScript 中的日期 ( source )。它考虑了年份滚动和不同的月份长度:

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

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

  • 将 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);
很好的捕获,一点点。我很惊讶我没有看到。请注意,T-SQL select DATEADD (month , 1, '2011-10-31') 产生 '2011-11-30',这对我来说是合理的。我得到了 10 票,但答案很差。凉爽的。:-)
2021-03-12 15:31:13
有一个addMonths功能,在这里,尊重(如月末2012-01-31 + 1 month = 2012-02-29等)。
2021-03-28 15:31:13
还要注意闰年 - 在闰年中将 1 年添加到 2 月 29 日会给您带来不可预测的结果,具体取决于您使用的语言(作为一般答案)。这就是 2012 年 Microsoft Azure 云平台关闭数小时的原因
2021-03-30 15:31:13
小心——这不适用于边缘情况,例如添加到大多数月份的第 31 天。例如,使用此方法的 Oct 31 2011 + 1 个月是使用 Javascript 的标准 Date 对象的 Dec 01 2011。
2021-04-03 15:31:13
只需添加设置每个月的第一个日期:today.setHours(0, 0, 0, 0); 今天.setDate(1);
2021-04-05 15:31:13

我正在使用moment.js库进行日期时间操作添加一个月的示例代码:

var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
这很好。我在网上找到的其他插件都没有比这更好的了。
2021-03-19 15:31:13
为了您自己的理智,请使用 moment.js。
2021-03-23 15:31:13
返回时刻(日期变量)。减去(1,'天');//解决了我的生活!
2021-03-23 15:31:13
我同意这是最干净的方法,但问题是“是否有内置的东西可以做到这一点?” Moment 将页面大小增加了数十 Kb
2021-03-28 15:31:13
绝对同意@garry:使用moment.js。
2021-04-06 15:31:13

此函数处理边缘情况并且速度很快:

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"
我建议要么删除“返回日期”行,要么添加一个本地变量。
2021-03-15 15:31:13
使用局部变量和分离测试更新。
2021-03-17 15:31:13
感谢安东尼,局部变量是有道理的。
2021-03-18 15:31:13
这里唯一合理的答案。但必须注意非 UTC 日期。它可能会带来意想不到的结果(例如,UTC+1 时区午夜,1 月 31 日 + 1 个月 = 3 月 1 日)
2021-04-08 15:31:13
另一个问题是它既修改原始日期又返回修改后的值。也许将它添加到日期原型或在函数中为更改的日期使用局部变量是有意义的?
2021-04-09 15:31:13

考虑到这些答案都不会在月份发生变化时考虑当前年份,您可以在下面找到我制作的应该处理它的答案:

方法:

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);
如果结果月份中没有相应的日期(例如,1 月 31 日 + 1 个月 => 2 月 2 日或 3 月 3 日),则此答案不考虑添加月份。它似乎也认为将超过 12 个月的日期添加到日期存在问题:没有。添加时没有必要,比如说,13 个月,添加 1 年零 1 个月。只需添加 13 个月。
2021-03-25 15:31:13

取自@bmpsini@Jazaret 的回复,但没有扩展原型:使用普通函数(为什么扩展本机对象是一种不好的做法?):

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

用它:

var nextMonth = addMonths(new Date(), 1);