1

I often encountered the situation where I want to add years, months, days, hours, minutes or seconds to a Date object in JavaScript. There are many ways described for each specific "add" (edit: as in add day for example) but I didn't find a complete solution on stackoverflow yet, so I decided to share my approach in Q&A style. My own answer is a way to deal with the problem without using a framework.


Other solutions to the Problem suggested in comments and answers:

Frameworks/Libraries dealing with the problem:

moment.js (thanks JonnyIrving/Eugene Mihaylin/Pac0)

https://blog.bitsrc.io/9-javascript-date-time-libraries-for-2018-12d82f37872d (thanks RobG)

fecha.js (thanks RobG)

Examples of specific add topics (thanks Pac0):

Days: Add days to JavaScript Date

Minutes: How to add 30 minutes to a JavaScript Date object?

Hours: Adding hours to Javascript Date object?

Months: JavaScript function to add X months to a date


(I will not mark any answer as accepted because in my opinion there are multiple valid ways)

MMMagic
  • 182
  • 2
  • 14
  • related: how-to-add-subtract-dates-with-javascript https://stackoverflow.com/questions/10931288/how-to-add-subtract-dates-with-javascript – Pac0 Nov 16 '18 at 13:01
  • related: incrementing-a-date-in-javascript https://stackoverflow.com/questions/3674539/incrementing-a-date-in-javascript – Pac0 Nov 16 '18 at 13:02
  • related: add-days-to-javascript-date https://stackoverflow.com/questions/563406/add-days-to-javascript-date – Pac0 Nov 16 '18 at 13:02
  • @Pac0 Yes I explicitly wrote "There are many ways decribed for each specific add"... You are just posting some of those... – MMMagic Nov 16 '18 at 13:03
  • Well, I think it's a good thing to reference some of them here. Anyway, I think that your question is actually a duplicate of the first linked, though. – Pac0 Nov 16 '18 at 13:05
  • related : adding-hours-to-javascript-date-object https://stackoverflow.com/questions/1050720/adding-hours-to-javascript-date-object – Pac0 Nov 16 '18 at 13:06
  • Possible duplicate of [Add days to JavaScript Date](https://stackoverflow.com/questions/563406/add-days-to-javascript-date) – Eugene Mihaylin Nov 16 '18 at 13:06
  • 1
    First one is also just adding days - but yes reference is actually fine. I will include some in the question. Thanks for contribution. – MMMagic Nov 16 '18 at 13:06
  • related : how-to-add-30-minutes-to-a-javascript-date-object https://stackoverflow.com/questions/1197928/how-to-add-30-minutes-to-a-javascript-date-object – Pac0 Nov 16 '18 at 13:07
  • related : javascript-function-to-add-x-months-to-a-date https://stackoverflow.com/questions/2706125/javascript-function-to-add-x-months-to-a-date/2706169 – Pac0 Nov 16 '18 at 13:08
  • related: how-to-add-months-to-a-date-in-javascript https://stackoverflow.com/questions/5645058/how-to-add-months-to-a-date-in-javascript – Pac0 Nov 16 '18 at 13:08
  • adjusted my question to include some of those examples. Thanks Pac0. However, the topic why the question has been marked as duplicate is really not the same... – MMMagic Nov 16 '18 at 13:26
  • Moment.js isn't a framework, it's a library. And there are many others, there are 9 listed in the article [*9 Javascript Time and Date Manipulation Libraries for 2018*](https://blog.bitsrc.io/9-javascript-date-time-libraries-for-2018-12d82f37872d). There is also [*fecha.js*](https://github.com/taylorhakes/fecha), which is a great parsing and formatting library that is very easy to extend with arithmetic methods. – RobG Nov 16 '18 at 14:12

4 Answers4

2

You may not be inclined to introduce a library to solve this problem and I understand sometimes it's better to do it vanilla, but personally, I find that all the headaches of dealing with dates and times in JS become a whole lot easier when you introduce the Moment.js library.

You can take a look at the doc here:https://momentjs.com/docs/#/parsing/date/

Below I have shown what it can do in terms of the adding of units of time but as you will see from the docs it does a whole lot more. It's really good at formatting date objects for example.

moment(new Date());

var nowPlusYear = moment().add(1, 'year');
var nowPlusMonth = moment().add(1, 'month');
var nowPlusMinute = moment().add(1, 'minute');

console.log("In 1 year it will be", nowPlusYear);
console.log("In 1 month it will be", nowPlusMonth);
console.log("In 1 minute it will be", nowPlusMinute);
<script src="https://cdn.jsdelivr.net/momentjs/2.10.6/moment-with-locales.min.js"></script>

Anyways check it out and see what you think.

Hope this helps!

JonnyIrving
  • 753
  • 2
  • 8
  • 18
  • Thanks for the contribution, I added the link in the original question. I think I will not mark any answer as accepted because in my opinion there are multiple valid ways (as of now I would mark this one and mine). Have an upvote tho. – MMMagic Nov 16 '18 at 13:53
  • Sure no problem! Great edits to the original question. – JonnyIrving Nov 16 '18 at 15:25
-1

Try to get out of JS date hell and use the widely used moment.js library :

moment('2018-01-01').add(1, 'day'); 

moment('2018-01-01').add(1, 'hour');

etc...

Pac0
  • 21,465
  • 8
  • 65
  • 74
-1

You can use moment.js

moment('2000-01-01').add(1, 'year');
moment('2000-01-01').add(1, 'month');
moment('2000-01-01').add(1, 'days');
moment('2000-01-01').add(1, 'hour');

or make it manually, like in this answer

Eugene Mihaylin
  • 1,736
  • 3
  • 16
  • 31
-4

My approach is extending the Date.prototype with the following add functionalities:

Date.prototype.addYears = Date.prototype.addYears || function (y, supressSet) {
    if (!supressSet) { this.setFullYear(this.getFullYear() + y); return this; }
    return new Date(this).addYears(y);
};
Date.prototype.addDays = Date.prototype.addDays || function (d, supressSet) {
    return this.addHours(d * 24, supressSet);
};
Date.prototype.addHours = Date.prototype.addHours || function (h, supressSet) {
    return this.addMinutes(h * 60, supressSet);
};
Date.prototype.addMinutes = Date.prototype.addMinutes || function (m, supressSet) {
    return this.addSeconds(m * 60, supressSet);
};
Date.prototype.addSeconds = Date.prototype.addSeconds || function (s, supressSet) {
    return this.addMilliseconds(s * 1000, supressSet);
};
Date.prototype.addMilliseconds = Date.prototype.addMilliseconds || function (ms, supressSet) {
    if (!supressSet) { this.setTime(this.getTime() + ms); return this; }
    return new Date(this).addMilliseconds(ms);
};

The supressSet parameter is optional and makes the respective function work as a getter without changing the object itself. If ommited, it is evaluated to false, which means the original date object will be modified.

As pointed out in comments I missed to take leap years into account. For that I took and adjusted the solution for months from Jazaret:

var DateHelper = {
    isLeapYear: function (year) {
        return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
    },
    getDaysInMonth: function (dateinput) {
        return [31, (DateHelper.isLeapYear(dateinput.getFullYear()) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][dateinput.getMonth()];
    }
};

Date.prototype.addMonths = function (m, supressSet) {
    var n = this.getDate(),nDate=new Date(this);
    nDate.setDate(1);
    nDate.setMonth(nDate.getMonth() + m);
    nDate.setDate(Math.min(n, DateHelper.getDaysInMonth(nDate)));
    if (!supressSet) {
        this.setDate(nDate.getDate()); this.setMonth(nDate.getMonth());
    }
    return nDate;
};
MMMagic
  • 182
  • 2
  • 14
  • 4
    Extending native prototypes isn't really helpful anymore these days where multiple libraries live in the same namespace. That's what broke popular libraries in the past because they were fighting over who could extend Date, Functiona nd Object with their version of addX. – Shilly Nov 16 '18 at 12:54
  • 2
    also, adding a day **is not always adding 24hours**. That would *somehow* depend on the timezone, and even in UTC you have leap seconds, which are not taken into account. – Pac0 Nov 16 '18 at 12:58
  • in what timezone doesnt a day have 24 hours? also I would be interested in a reference to the leap second statement please. If I can I will modify then to take that into account. Thank you! – MMMagic Nov 16 '18 at 13:55
  • 2
    This seems a rather pointless exercise, and wrong. Adding 1 day is not the same as adding 24 hours where you cross a daylight saving boundary. Also, the way you're adding months means 31 Jan + 1 month will be 2 or 3 March, depending on whether it's a leap year or not. Adding negative months will have similar results: 31 March + -1 month will be 2 or 3 March. You'll get similar results for months with 31 days vs 30. – RobG Nov 16 '18 at 14:00
  • 1
    If your computer is in a time zone that follows daylight savings time, you can try `.addDays(180)` and the result will be off by 1 hour. – JJJ Nov 16 '18 at 14:33
  • Leap Years added now. I live in germany and tried to add 100 days several times and the time stays correct... – MMMagic Nov 16 '18 at 14:39
  • @MMMagic Treating a day as = 24 hours isn't correct. https://gist.github.com/jleedev/ab7d17ba92669fab66ae6ec041ec8c1a – Josh Lee Nov 16 '18 at 16:00
  • 1
    also, adding a month is subjective, and business dependant. If you started some monthly subscription on the 10th of january, you expect your subscription to be renewed on 10th february, 10th march, 10th april etc... If you subscribed at the end of the month, 31st january, when would it need to be renewed ? 28th feb ? (29th for leap years ?) 1st march ? 2nd march ? – Pac0 Nov 16 '18 at 16:18
  • 1
    in a nutshell : date/calendar arithmetic is much much harder than it might appear, and rolling your own will make you fall in a lot of traps, that libraries (kinda) handle more or less smoothly. – Pac0 Nov 16 '18 at 16:20