[javascript] Subtract days, months, years from a date in JavaScript

Does anybody know of a simple way of taking a date (e.g. Today) and going back X days, X months and X years?

I have tried that:

var date = new Date();
$("#searchDateFrom").val((date.getMonth() -1 ) + '/' + (date.getDate() - 6) + '/' + (date.getFullYear() - 1));

But I got a negative date, for example today the output was:

3/-3/2015

Any advise?

Thanks.

This question is related to javascript

The answer is


I implemented a function similar to the momentjs method subtract.

- If you use Javascript

function addDate(dt, amount, dateType) {
  switch (dateType) {
    case 'days':
      return dt.setDate(dt.getDate() + amount) && dt;
    case 'weeks':
      return dt.setDate(dt.getDate() + (7 * amount)) && dt;
    case 'months':
      return dt.setMonth(dt.getMonth() + amount) && dt;
    case 'years':
      return dt.setFullYear( dt.getFullYear() + amount) && dt;
  }
}

example:

let dt = new Date();
dt = addDate(dt, -1, 'months');// use -1 to subtract 

- If you use Typescript:

export enum dateAmountType {
  DAYS,
  WEEKS,
  MONTHS,
  YEARS,
}

export function addDate(dt: Date, amount: number, dateType: dateAmountType): Date {
  switch (dateType) {
    case dateAmountType.DAYS:
      return dt.setDate(dt.getDate() + amount) && dt;
    case dateAmountType.WEEKS:
      return dt.setDate(dt.getDate() + (7 * amount)) && dt;
    case dateAmountType.MONTHS:
      return dt.setMonth(dt.getMonth() + amount) && dt;
    case dateAmountType.YEARS:
      return dt.setFullYear( dt.getFullYear() + amount) && dt;
  }
}

example:

let dt = new Date();
dt = addDate(dt, -1, 'months'); // use -1 to subtract

Optional (unit-tests)

I also made some unit-tests for this function using Jasmine:

  it('addDate() should works properly', () => {
    for (const test of [
      { amount: 1,  dateType: dateAmountType.DAYS,   expect: '2020-04-13'},
      { amount: -1, dateType: dateAmountType.DAYS,   expect: '2020-04-11'},
      { amount: 1,  dateType: dateAmountType.WEEKS,  expect: '2020-04-19'},
      { amount: -1, dateType: dateAmountType.WEEKS,  expect: '2020-04-05'},
      { amount: 1,  dateType: dateAmountType.MONTHS, expect: '2020-05-12'},
      { amount: -1, dateType: dateAmountType.MONTHS, expect: '2020-03-12'},
      { amount: 1,  dateType: dateAmountType.YEARS,  expect: '2021-04-12'},
      { amount: -1, dateType: dateAmountType.YEARS,  expect: '2019-04-12'},
    ]) {
      expect(formatDate(addDate(new Date('2020-04-12'), test.amount, test.dateType))).toBe(test.expect);
    }

  });

To use this test you need this function:

// get format date as 'YYYY-MM-DD'
export function formatDate(date: Date): string {
  const d     = new Date(date);
  let month   = '' + (d.getMonth() + 1);
  let day     = '' + d.getDate();
  const year  = d.getFullYear();

  if (month.length < 2)  {
    month = '0' + month;
  }
  if (day.length < 2) {
    day = '0' + day;
  }

  return [year, month, day].join('-');
}

I'd recommend using the MomentJS libraries. They make all interactions with Dates a lot simpler.

If you use Moment, your code would be as simple as this:

var today = moment();
var nextMonth = today.add('month', 1);
// note that both variables `today` and `nextMonth` refer to 
// the next month at this point, because `add` mutates in-place

You can find MomentJS here: http://momentjs.com/

UPDATE:

In JavaScript, the Date.getDate() function returns the current day of the month from 1-31. You are subtracting 6 from this number, and it is currently the 3rd of the month. This brings the value to -3.


This does not answer the question fully, but for anyone who is able to calculate the number of days by which they would like to offset an initial date then the following method will work:

myDate.setUTCDate(myDate.getUTCDate() + offsetDays);

offsetDays can be positive or negative and the result will be correct for any given initial date with any given offset.


Use the moment.js library for time and date management.

import moment = require('moment');

const now = moment();

now.subtract(7, 'seconds'); // 7 seconds ago
now.subtract(7, 'days');    // 7 days and 7 seconds ago
now.subtract(7, 'months');  // 7 months, 7 days and 7 seconds ago
now.subtract(7, 'years');   // 7 years, 7 months, 7 days and 7 seconds ago
// because `now` has been mutated, it no longer represents the current time

I have a simpler answer, which works perfectly for days; for months, it's +-2 days:

let today=new Date();
const days_to_subtract=30;
let new_date= new Date(today.valueOf()-(days_to_subtract*24*60*60*1000));

You get the idea - for months, multiply by 30; but that will be +-2 days.


This is a pure-function which takes a passed-in starting date, building on Phil's answer:

function deltaDate(input, days, months, years) {
    return new Date(
      input.getFullYear() + years, 
      input.getMonth() + months, 
      Math.min(
        input.getDate() + days,
        new Date(input.getFullYear() + years, input.getMonth() + months + 1, 0).getDate()
      )
    );
}

e.g. writes the date one month ago to the console log:

console.log(deltaDate(new Date(), 0, -1, 0));

e.g. subtracts a month from March 30, 2020:

console.log(deltaDate(new Date(2020, 2, 30), 0, -1, 0)); // Feb 29, 2020

Note that this works even if you go past the end of the month or year.

Update: As the example above shows, this has been updated to handle variances in the number of days in a month.


As others have said you're subtracting from the numeric values returned from methods like date.getDate(), you need to reset those values on your date variable. I've created a method below that will do this for you. It creates a date using new Date() which will initialize with the current date, then sets the date, month, and year according to the values passed in. For example, if you want to go back 6 days then pass in -6 like so var newdate = createDate(-6,0,0). If you don't want to set a value pass in a zero (or you could set default values). The method will return the new date for you (tested in Chrome and Firefox).

function createDate(days, months, years) {
        var date = new Date(); 
        date.setDate(date.getDate() + days);
        date.setMonth(date.getMonth() + months);
        date.setFullYear(date.getFullYear() + years);
        return date;    
    }