0

I am trying to create a function that will take in the current date using something like this:

    const currDate = new Date()

and I want to be able to pass that value into a function that subtracts the current date from a specific number of months and this function should return an the result using RFC 3399 format

I have looked at this post here and used a function from the post to do the subtraction of dates:

export function subtractMonths(numOfMonths: number, date: Date = new Date()) {
  date.setMonth(date.getMonth() - numOfMonths);

  return date;
}

the problem is when I call the function and format it. It doesn't keep the same results, and changes the date to the current date:

      const currDate = new Date(); // "2022-08-24T18:26:33.965Z"
      const endDate = subtractMonths(6, currDate) // this changes the value of currDate to "2022-02-24T19:26:33.965Z"
      
      const formattedStartDate = endDate.toISOString() // "2022-08-24T18:26:33.965Z"
      const formattedEndDate = currDate.toISOString() // "2022-08-24T18:26:33.965Z"

I am able to work around this by creating two instances of the Date object and doin the operation that way, but I feel as though there is a cleaner way to do this but don't know how I would go about doing that.

Edit: I understand why I have to make copies of the date. The issue as stated in the title was trying to find a cleaner way to write the function, as I already have code that works and solves the problem.

Spacecase
  • 37
  • 1
  • 1
  • 6
  • 1
    The *subtractMonths* function modifies and returns the passed in *Date* (if one is supplied), so both *currDate* and *endDate* reference the same *Date* instance. – RobG Aug 24 '22 at 22:48

2 Answers2

1

I have a similar code to figuring out if a date is on the last day of the month. Yes you have to start off by creating a new Date object because .setMonth(...) will update the object itself that it is called on. Same as .setDate(...) shown below.

function isLastDayOfMonth(date) {
    var n = new Date(date),
        d = n.getDate();
    n.setDate(d + 1);
    return n.getMonth() != date.getMonth();
}
maraaaaaaaa
  • 7,749
  • 2
  • 22
  • 37
1

You are mutating the date parameter of your function, that's why it does not work. You should clone the parameter so only it is mutated.

Here is a working version:

export function subtractMonths(numOfMonths: number, date: Date = new Date()) {
  const clonedDate = new Date(date);
  clonedDate.setMonth(date.getMonth() - numOfMonths);

  return clonedDate;
}

If you need to manipulate dates and can use external libs, I suggest to use date-fns

  • Code–only answers aren't that helpful. A good answer should explain why the OP has their issue and how the answer fixes it. This also doesn't fix the case where subtracting months lands on a date that doesn't exist in the resulting month, e.g. subtracting 1 month from 31 March gives 31 Feb, which results in a date for 2 or 3 March depending on whether it's a leap year or not. That result might be unexpected. – RobG Aug 25 '22 at 10:45
  • 1
    This answers my question, as I was only looking for a cleaner way to write the code I have. Since my date subtraction code works fine, I just felt like there was a better way to write it and this looks cleaner. So although it’s a “code only” answer, it answers the question. – Spacecase Aug 26 '22 at 10:50
  • @Spacecase—your code "works fine" only if you think 31 March minus 1 month should be 3 March. There is an explanation of why that happens and how to fix it at the duplicate, along with much better code. – RobG Aug 26 '22 at 11:13