Time Travel in Vanilla Javascript

Gabi Procell

Time Travel in Vanilla Javascript

Exploring the pains of date and time manipulation.

In one of our internal projects for learning tools and techniques, the team was using Jest and Enzyme to test drive the creation of a React app. We wanted to provide an interface to move forward or backward by one day and decided to tackle it using vanilla javascript. However, there is a lot of pomp and circumstance that comes along with changing a date by one day in js!

The app displays tasks for the current day by default, and when a task is added the task’s date is set to new Date() which returns a date/time object like so: 2017-11-16T01:27:29.427Z. This was definitely the simplest part of the date handling.

Finding tomorrow and yesterday the painful way

Finding the next and previous dates required a bit of math. In order to add time to the date, one must first convert the date object into milliseconds (Essentially, the Date instance returns a value that is equal to the number of milliseconds since January 1, 1970 UTC). The getTime() method will return the value of a given date in milliseconds:

const date = new Date();
=> 2017-11-16T01:27:29.427Z     // Our date-time object

const dateInMS = date.getTime();
=> 10795649427                 // A lot of milliseconds'

Next, we do some math to find how many milliseconds there are in a day.

  • There are 86,400 seconds in a day.
  • 1 millisecond = 0.0001 seconds
  • ms/day = 86,400 sec * 0.001 sec

Therefore, calculating yesterday or tomorrow would involve adding or subtracting the total milliseconds in a day to or from the number of milliseconds from a given date. For example:

 const tomorrow = date.getTime() + (86400 * 1000);
 => 1510882049427 ms

 const yesterday = date.getTime() - (86400 * 1000);
 => 1510709249427 ms

Converting milliseconds into dates

After getting the time of the date we are looking for, we then need to create a new instance of Date and use the setTime() method to set our Date object to the time that we calculated in milliseconds since January 1, 1970.

const yesterday = new Date(date.setTime(date.getTime() - (86400 * 1000)))
=> 2017-11-15T01:27:29.427Z

const tomorrow = new Date(date.setTime(date.getTime() + (86400 * 1000)))
=> 2017-11-17T01:27:29.427Z

After finding today’s, tomorrow’s, and yesterday’s dates, we also needed to be able to display the date and any tasks that were created on that date. For display purposes, dates were converted to strings.

const tasks = this.state.tasks.filter(item =>
    item.date.toDateString() === date.toDateString();
    =>  Returns item with date formatted as such : Tue Nov 14 2017

More issues arose with testing that our dates and tasks would return as expected when a user clicked the Tomorrow or Yesterday buttons. A roadblock when testing this appeared in the form of a type error that calling the toDateString() method was not a function. What wasn’t it a function of? That turned out to be an empty array. If our task list was free of tasks, our filter method wanted nothing to do with that. We would then have to account for this edge case in our code, along with multiple transformations of our data in order to perform a seemingly mundane task.

Less painful ways of handling time

In comparison, many members of our team have handled date and time with Rails’ Active Support Extensions via the DateTime class. According to the Rails documentation, DateTime comes with all of the methods that pair with the Date class, except they will always return dateTimes. Some of these methods include:

  • yesterday
  • tomorrow
  • advance
  • weeks_ago
  • years_since

Those are just a few of the many helpful methods that perform the same functions that we are trying to do with our buttons in vanilla Javascript but without the headache of calculating dates and times.

While it is nice to maintain a slim figure with your application and not relying heavily on importing libraries and tools, there is something to be said for considering if the effort of a task (such as finding the value of the next or previous day) is worth more of your time in the end. In this case, we ended up using Moment.js as it was more useful and intuitive in the long run. Testing became easier when we didn’t have to transform our date object multiple times. Quite frankly, it also reads nicely in the end, and other devs who touch your code may even thank you for it later.

For more information, check out the following links:

MDN Web Docs on Javascript’s Date Instance

Ruby on Rails Guide to Active Support Extension to Date

Moment.js, our Lord and Savior

Gabi Procell



The Weekly Manifest

Receive the latest design, development, and startup articles to stay updated!


Inquiry Sent!

Thanks so much for your interest in working with us, and for your time to fill out the form. We're passionate about what we do and would love the opportunity to create a successful solution for you.

Expect to hear back from us within the next 3 business days.

Work With Us

We can take on any type of project, but we don’t work with everyone. We only partner with clients that align with our business values, honestly benefit from our expertise, and embrace the systems we build in.

Fill out the form below to start a conversation see if you’re the right fit for us.

What type of project would you like to partner with us on?