Incrementing and Decrementing Dates in Javascript
In my day job for a London Council, I recently I had to build the front end for a reservation system where users could reserve appointment slots for a Covid-19 test. I was going to build it using Vanilla Javascript and ES6. How it was going to work, was that the backend, where the appointment slots were created would be provided to me as a JSON feed, so I just needed to be able to find a way to consume the feed and then build out the front end with the data.
This was all relatively straightforward to do, I fetched the JSON feed and was able to build out the relative parts of the application, until I came to the part where I had to build the date controls. The date controls would use a set of 'previous' and 'next' buttons, where clicking 'previous' would decrement the date by 1 day and the 'next' button would increment the date by 1 day. The url for the JSON feed would have a date in ISO-8601 format (YYYY-MM-DD) as a variable that if incremented or decremented, the updated url would be used to fetch the new JSON data.
Having never really worked much with dates in the past, and having used dayJS the few times when I had, my initial thought was to reach for it again. DayJS exists because working with dates in Javascript is usually a nightmare for most devs. However dayJS didn't seem to offer what I was looking for, and would have been overkill anyway, given the extra weight it would have added to my bundle. I had tried searching Stack Overflow for an answer and couldn't quite find an example for my use case. In the end I used the native Javascript Date Object, but knowing where to start with it and knowing which of the pitfalls surrounding Javascript Dates to avoid was initially tricky. I spent a few hours reading MDN and W3CSchools to better understand the myriad of methods that can be used with dates. Whether or not daylight saving was going to affect what I wanted to do. And how to add/subtract 1 day in Javascript. All things that have to be considered when handling dates.
With the lack of examples of what I was trying to achieve, available on Stack Overflow, medium or elsewhere on the Internet I decided I'd document how I solved this issue for what I felt would be fairly common use case.
Below is what my fetch call with the typical url would look like, or so I thought initially...
fetch(
https://www.some-url/apps/bookings/calendar-json.php?todaysDate=${year}-${month}-${day})
let today = new Date();
let yyyy = today.getFullYear();
let mm = today.getMonth()+1; // getMonth() is zero-based
let dd = today.getDate();
Initially, I tried to have 3 separate variables for the day, month & year and then increment them individually. Since what I was trying to do, was effectively a counter only with dates, I started by building a simple counter in Javascript. I could then increment or decrement the day variable. However, what I found was that manipulating the day separately, meant that the month wouldn't increment/decrement in tandem with when you reach the end of/beginning of the month.
I realised I would need to use the setTime and getTime methods to achieve what I wanted.
Rather than separate out day, month & year as individual variables I set it as just one. So now my fetch call looked like this...
fetch(
https://www.some-url/apps/bookings/calendar-json.php?todaysDate=${date})
First I simply get the date, :
let date = new Date();
console.log(date);
// returns Mon Nov 01 2021 17:28:54 GMT+0000 (Greenwich Mean Time)
Then call the setTime method on the date variable. The setTime() method sets a date and time by adding or subtracting a specified number of milliseconds to/from midnight January 1, 1970. Then I pass the getTime method on the date variable in to the setTime method. The getTime() method returns the number of milliseconds since January 1, 1970.
Doing this will give us today's date in milliseconds since January 1, 1970.
let today = date.setTime(date.getTime());
console.log(today)
Then I needed to have a variable that represented a full day in milliseconds, in order to add or subtract. 1 day in milliseconds can be calculated like so:
let day = 24 * 60 * 60 * 1000;
I also initialise 2 variables for setting the dates.
let dateVal;
let urlDate;
dateVal will store the result from adding together today in milliseconds and 1 day in milliseconds. urlDate will store the dateVal result in a human readable formatted date form.
Then in order to increment or decrement I need an eventListener on the set of controls and inside them I do my addition and subtraction respectively. That looks like this:
const next = document.querySelector(".next");
next.addEventListener("click", (e) => {
dateVal = today += day;
urlDate = new Date(dateVal);
let formattedDate = urlDate.toISOString().slice(0, 10);
console.log(formattedDate);
});
const prev = document.querySelector(".prev");
prev.addEventListener("click", (e) => {
dateVal = today -= day;
urlDate = new Date(dateVal);
let formattedDate = urlDate.toISOString().slice(0, 10);
console.log(formattedDate);
});
Once I have the result from adding/subtracting today in milliseconds to/from 1 day in milliseconds, I then need to pass that in to the date object constructor to get back an actual formatted date which will be stored in urlDate.
Once I have the incremented or decremented date from the eventListener, then it will need to be converted to ISO-8601 format, I can do that by calling the toISOString() method on urlDate. ISOString() method returns a time with it, but as I don't need this, it can be removed by .slicing the string at the 10th character (see above).
fetch(
https://www.some-url/apps/bookings/calendar-json.php?todaysDate=${formattedDate})
Boom! And there we have it. Something which is actually pretty easy to solve, but my fear of working with dates in Javascript initially held me back. Before reaching for a date plugin or module in your next project, why not have a go at it using the Date object natively.
And here's a working codesandbox:
<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Frecursing-booth-js57o%3Ffontsize%3D14%26hidenavigation%3D1%26theme%3Ddark&display_name=CodeSandbox&url=https%3A%2F%2Fcodesandbox.io%2Fs%2Fh02ul&key=a19fcc184b9711e1b4764040d3dc5c07&type=text%2Fhtml&schema=codesandbox" title="" height="500" width="1000"></iframe>This story is also available @ https://www.nmk.dev/post/incrementing-decrementing-dates-in-javascript-3af8dc13f797