1

I'm trying to find a method that reliably subtracts 1 month from a javascript date object.

I have this code:

    var shippedDate = new Date('12/31/2020');
    var tempDate = new Date(shippedDate.setMonth(shippedDate.getMonth() - 1)); //subtract 1 month
    alert(tempDate);

The value in tempDate after this code runs is 12/1/2020 when it should actually be 11/30/2020.

I checked my math with this online date calculator: https://www.timeanddate.com/date/dateadded.html?m1=12&d1=31&y1=2020&type=sub&ay=&am=1&aw=&ad=&rec=

Thanks.

bogus
  • 457
  • 5
  • 16

2 Answers2

5

December has 31 days so when you subtract 1 month, you get 31 November which doesn't exist, so it rolls over to 1 December.

You can test the date (day in month) to see if it's the same, and if not, set the date to 0 so it goes to the last day of the previous month.

Also, setDate modifies the Date object so no need to create a new one:

function subtractMonth(date, months) {
  let d = date.getDate();
  date.setMonth(date.getMonth() - months);
  if (date.getDate() != d) {
    date.setDate(0);
  }
  return date;
}

let d = new Date(2020, 11, 31); // 31 Dec 2020
console.log(subtractMonth(d, 1).toString()); // 30 Nov 2020

This has side effects so that sequentially subtracting 2 months may give a different result to subtracting 2 months in one go.

Also in regard to new Date('12/31/2020'), see see Why does Date.parse give incorrect results?

PS

I answered this before I remembered that there were plenty of questions about adding months that also cover subtracting. So I marked this question as a duplicate and rather than delete this answer, left it for posterity.

If you wish to vote for an answer, please go to one of the duplicates and vote for an answer there. :-)

Community
  • 1
  • 1
RobG
  • 142,382
  • 31
  • 172
  • 209
4

On my own experience, I may qualify all around Date calculation in javascript as completely unbearable pain.

Avoid as possible own crafted function to any Date manipulation. There are too many traits to lose mind at all. Timezones, wrong clocks, timezone on your own host vs. timezone on server, unexpected toString conversion according to local host timezone/clock.

If you rally need to make some dates calculation use battle tested library, like date-fns, moment.js, etc.

By the way your example almost correct, you just have chosen not suitable time to try to test it. The only one that I see problematic it's using setMonth that mutate original shippedDate.

Kyr
  • 887
  • 7
  • 11