Javascript函数添加X个月到一个date

我正在寻找最简单,最干净的方法来将X月添加到Javascriptdate。

我宁愿不处理今年的滚动,也不得不写我自己的function 。

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

我认为这应该做到这一点:

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

我相信它应该自动处理递增到适当的一年,并修改到适当的月份。

尝试一下

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

 var startDate = new Date(...); var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format endDateMoment.add(1, 'months'); 

这个function可以处理边缘情况,速度很快:

 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 } 

testing:

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

非UTCdate的更新:(由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 } 

testing:

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

考虑到这些答案都不会解释当月发生变化的那一年,你可以在下面find一个应该处理的答案:

方法:

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

简单的解决scheme: 2678400000是31天,以毫秒为单位

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

更新:

使用这些数据来build立我们自己的function:

  • 2678400000 – 31天
  • 2592000000 – 30天
  • 2505600000 – 29天
  • 2419200000 – 28天

采取@ 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); 
 d = new Date(); alert(d.getMonth()+1); 

月份有一个基于0的索引,它应该提醒(4)哪个是5(可能);

只是为了增加接受的答案和评论。

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

由于大部分答案突出显示,我们可以使用setMonth()方法和getMonth()方法将特定的月数添加到给定的date。

例如:(正如@ChadD在他的回答中所提到的)

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

但是我们应该小心使用这个解决scheme,因为我们会遇到边缘案例的麻烦。

为了处理边缘情况,回答下面的链接是有帮助的。

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

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

 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,然后可以因为时区或节省时间的变化或其他方面的原因,前一天…

这是我提出的解决scheme,它没有这个问题,而且,我认为,它更优雅,因为它不依赖于硬编码的值。

 /** * @param isoDate {string} in ISO 8601 format eg 2015-12-31 * @param numberMonths {number} eg 1, 2, 3... * @returns {string} in ISO 8601 format eg 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 testing成功:

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

所有这些看起来都太复杂了,我猜想它会引起关于“一个月”究竟是什么意思的争论。 这是否意味着30天? 这是否意味着从1日到1日? 从最后一天到最后一天?

如果是后者,那么在2月27日增加一个月会让你到3月27日,但是增加一个月到2月28日会让你到3月31日(闰年除外,这会让你到3月28日)。 然后从3月30日减去一个月,让你… 2月27日? 谁知道…

对于那些寻求简单的解决scheme,只需要添加毫秒并完成。

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

要么

 Date.prototype.addDays = function(days) { this = new Date(this.getTime() + (days * 86400000)); }; 

你可以使用我写的这个开源组件来实现这一点。 此解决scheme还妥善处理年度翻转和工作时生成的月份不具有相同的天数原来的月份(例如增加1个月到1月31日结果在2月28日,而不是3月3日或不存在的date2月31日

使用它非常简单:

 var originalDate = new Date('June 25, 2017 12:00:00'); var newDate = dateAdd(originalDate, 2, 'months'); // => August 25, 2017 12:00:00 

此解决scheme也适用于添加其他时间单位,如年,日等

你可以使用这个方法,而不用关心内部的工作方式,但是如果你感兴趣的话,下面是几个月的内容。

 // Get current date var oldDate = original.getDate(); // Increment months (handles year rollover) var newDate = new Date(original); newDate.setMonth(original.getMonth() + increment); // If new day and old day aren't equal, set new day to last day of last month // (handles edge case when adding month to Jan 31st for example. Now goes to Feb 28th) if (newDate.getDate() != oldDate) { newDate.setDate(0); } return newDate; 

以下是如何根据dateinput(membershipssignup_date)+通过表单字段添加月份(会员月数)计算未来date的示例。

membershipmonths字段具有默认值0

触发链接(可以是附加到会员期限字段的onchange事件):

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

正如许多复杂,丑陋的答案所表明的,date和时间对于使用任何语言的程序员来说都是一场噩梦。 我的做法是将date和'delta t'值转换为Epoch Time(以ms为单位),执行任何算术运算,然后转换回“人类时间”。

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

这是写一个稍微不同的用例,但你应该能够很容易地适应相关的任务。

编辑:完整的来源在这里 !

有时用BIRT参数中的一个操作符创builddate

我回来了1个月:

 new Date(new Date().setMonth(new Date().getMonth()-1)); 
 var a=new Date(); a.setDate(a.getDate()+5); 

如上所述,您可以添加月份到Date函数。