Subtract days, months, years from a date in JavaScript

Javascript

Javascript Problem Overview


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.

Javascript Solutions


Solution 1 - Javascript

You are simply reducing the values from a number. So substracting 6 from 3 (date) will return -3 only.

You need to individually add/remove unit of time in date object

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

Solution 2 - Javascript

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

Solution 3 - Javascript

2021 Update:

MomentJS has been replaced/improved with LuxonJS, a much more up-to-date and newer version. You can find it here: https://moment.github.io/luxon/#/

I'll leave the old post for now, since it could sitll help others.

Old post:

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.

Solution 4 - Javascript

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.

Solution 5 - Javascript

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

Solution 6 - Javascript

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

Solution 7 - Javascript

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.

Solution 8 - Javascript

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.

Solution 9 - Javascript

The oneliner to get for instance the date of yesterday would be:

const yesterday = ((date) => date.setDate(date.getDate() - 1) && date)(new Date());

It will define an arrow function which receives the new Date() as a parameter (date). The reason to make an arrow function is that the new Date object will be used multiple times. First to retrieve the current days (getDate), then to set the days (setDate) and also to return it as a result. So it will return the mutated date, not the original date.

Now this arrow function is defined and will be called immediately with the new Date() in order to return the date of yesterday.

Solution 10 - Javascript

Vanilla JS Date saves the time as milliseconds from Epoch time (1970), so all we need to do is subtract in milliseconds. if we want to subtract 10 days we would subtract 1000(ms) * 60(s) * 60(m) * 24(h) * 10(d)

A simple Vanilla function to subtract from a date (notice the years exception):

subtractFromDate(new Date(), { hours: 15 }) // now - 15 hours
subtractFromDate(new Date(), { days: 15 }) // now - 15 days
subtractFromDate(new Date(), { years: 15 }) // now - 15 years
const subtractFromDate = (
    date,
    { years, days, hours, minutes, seconds, milliseconds } = {}
) => {
    const millisecondsOffset = milliseconds ?? 0
    const secondsOffset = seconds ? 1000 * seconds : 0
    const minutesOffset = minutes ? 1000 * 60 * minutes : 0
    const hoursOffset = hours ? 1000 * 60 * 60 * hours : 0
    const daysOffset = days ? 1000 * 60 * 60 * 24 * days : 0
    const dateOffset =
        millisecondsOffset +
        secondsOffset +
        minutesOffset +
        hoursOffset +
        daysOffset

    let newDate = date
    if (years) newDate = date.setFullYear(date.getFullYear() - years)
    newDate = new Date(newDate - dateOffset)

    return newDate
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3378165View Question on Stackoverflow
Solution 1 - Javascriptgurvinder372View Answer on Stackoverflow
Solution 2 - JavascriptPhilView Answer on Stackoverflow
Solution 3 - JavascriptFvBView Answer on Stackoverflow
Solution 4 - JavascriptN8allanView Answer on Stackoverflow
Solution 5 - JavascriptStefano BorzìView Answer on Stackoverflow
Solution 6 - JavascriptYounes Henni View Answer on Stackoverflow
Solution 7 - JavascriptVinayak ThatteView Answer on Stackoverflow
Solution 8 - JavascriptAlan GeeView Answer on Stackoverflow
Solution 9 - JavascriptBob SiefkesView Answer on Stackoverflow
Solution 10 - JavascriptEdan ChetritView Answer on Stackoverflow