最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I add and subtract months from a date? - Stack Overflow

programmeradmin0浏览0评论

I am trying to add/subtract an integer to the element of array. my function is

var addToMonth = function (date, monthsToAdd) {
    var tempDate = date.split("-");
    tempDate[1] = parseInt(tempDate[1]) + monthsToAdd;
    tempDate[1] = 0 + tempDate[1];
    console.log("TempDate "+tempDate[1]);
    tempDate = tempDate.join("-");
    console.log("Added TempDate: "+tempDate);
    return tempDate;
}

The acceptable date string is: date = "2016-04-05". If call the function as addToMonth(date,1). The output is correct that is 2016-05-05. But when I call it as addToMonth(date, -1). It doesn't work. What is the correct way to do it?

I am trying to add/subtract an integer to the element of array. my function is

var addToMonth = function (date, monthsToAdd) {
    var tempDate = date.split("-");
    tempDate[1] = parseInt(tempDate[1]) + monthsToAdd;
    tempDate[1] = 0 + tempDate[1];
    console.log("TempDate "+tempDate[1]);
    tempDate = tempDate.join("-");
    console.log("Added TempDate: "+tempDate);
    return tempDate;
}

The acceptable date string is: date = "2016-04-05". If call the function as addToMonth(date,1). The output is correct that is 2016-05-05. But when I call it as addToMonth(date, -1). It doesn't work. What is the correct way to do it?

Share Improve this question edited Apr 5, 2016 at 8:01 Liam 29.8k28 gold badges139 silver badges203 bronze badges asked Apr 5, 2016 at 7:52 uvishereuvishere 4308 silver badges22 bronze badges 3
  • 2 What is not working? You getting errors? – void Commented Apr 5, 2016 at 7:55
  • This seems to work fine. Is your problem with padding the month with 0? – Jon Surrell Commented Apr 5, 2016 at 7:57
  • tempDate[1] = '' + 0 + tempDate[1]; to pad it with 0..Rest of things look good! – Rayon Commented Apr 5, 2016 at 7:58
Add a ment  | 

2 Answers 2

Reset to default 4

Original 2016

The selected answer is actually incorrect as the question asks how to add months, not days. The correct solution is:

   function addToMonth( date, months ) {
        var d = new Date( date || new Date() );
        d.setMonth( d.getMonth() + (months || 0), d.getDate());
        return d;      
    }

Show and then run the code snippet to view demo.

I've also up voted the question ... because it does show effort and dates are tricky to work with even for experienced coders (especially when time zones are involved). That's why there are libraries like monment.js and others. For more information on the Date object see: MDN Date

function addToMonth( date, months ) {
    var d = new Date( date || new Date() );
    d.setMonth( d.getMonth() + (months || 0), d.getDate());
    return d;      
}


// Test Data
var html = '', iso, step = 1;


[
  '4/5/2016',
  '4/5/2016 01:00 GMT', 
  '2016-04-05', 
  '2016-04-05T00:00:00', 
  '2016-04-05T23:59:59',
  '2016-04-05T23:59:59Z',
  '2016', 
  '4/5/2016',
  undefined, 
  null, 
  0, 
  '',
  (new Date())

].forEach(function(v,i) {
  iso = addToMonth( v, -1).toISOString().split('T').shift();
  html += '<tr><td>' + v + '</td><td>-1</td><td>' + iso + '</td></tr>';
  iso = addToMonth( v, 1).toISOString().split('T').shift();
  html += '<tr><td>' + v + '</td><td>+1</td><td>' + iso + '</td></tr>';


});

stdout.innerHTML = '<table>' + html + '</table>';
table {
  border-collapse: collapse;
  background-color: white;
}
td {
  max-width: 10em;
  min-width: 4em;
  border: 1px lightgray solid;
  padding: 2px;
  overflow: hidden;
  white-space: nowrap;
  font-family: monospace;
}
tr:nth-child(odd) {
  background-color: aliceblue;
}
<div id="stdout"></div>

Update 2023

A menter noted the edge case where the day of the month is greater than the target maximum. In this case the function uses the default Date.setMonth behavior, which can spill over into the following month, e.g., 31 Jan + 1 month = 3 Mar rather than 28 Feb. Since the question doesn't specify how to handle these cases it seems reasonable to use the expected behavior and not try to guess what OP wants.

The menter also noted that getDate is redundant in

d.setMonth( d.getMonth() + (months || 0), d.getDate())

True, and it can be shortened to

d.setMonth( d.getMonth() + (months || 0))

Interestingly, this change didn't appear to make any difference in performance (Chrome 100k loops).

Alternative code that incorporates menter suggestions:

function addToMonth( date, months ) {
  let d = new Date( date || new Date() ), n = d.getDate(); 
  d.setMonth( d.getMonth() + (months || 0));
  if (d.getDate() < n) d.setMonth( d.getMonth(), 0);
  return d;      
}

Yours is not a right approach:

  1. parseInt should always use base 10 if working with decimals.
  2. addToMonth("2016-31-03", 1) will give 2016-32-03. WRONG X.
  3. addToMonth("2016-01-03", -1) will give 2016-00-03. WRONG X.
  4. The way you are padding the 0 is not right. (Find out why.)

Use setDate and getDate functions on date instead.

var addToMonth = function (date, monthsToAdd) {
    var d = new Date(date);
    d.setDate(d.getDate()+monthsToAdd);
    return d;
}
发布评论

评论列表(0)

  1. 暂无评论