Rules of parsing dates with Date.parse

Rule of thumb: do not use it!

One of the projects I’ve been working on recently is resume.io — online resume builder. We have built the web service from the ground up and so far it is one of the best experiences I’ve ever had as a developer. However some strange emails appeared in our support inbox recently. People were complaining that they couldn’t change dates of their work experience and that «the system keeps changing correct dates on its own».

I tried to reproduce the bug several times, I even tested it in the exact same environment (luckily you don’t have to keep virtual machine on your laptop anymore for it) but it was hopeless — the interface was working as it supposed to do. I noticed that those emails were mostly from US users so I made a quick guess that it somehow might be related to their timezone. So it was!

This is how it looked like for people from New York 😨

Our application was built on React/Redux with Redux Form and we wrote a custom <Field /> component for date ranges. Except for normal dates we needed to handle special cases like «don’t show the date» or «show year only» so we used an adapter that would transform the data into UI-friendly format and transform it back when the value is changed. It is quite convenient for testing and luckily (or unfortunately) leads to some funny results if one piece of the transformation is broken.

So what was the problem?

It turned out we passed dates as 2016–10–01” strings from our Rails-backend to Date.parse function:

Read the documentation first!

MDN warns us that the use of this function is not recommended because it is browser-specific and may cause unexpected behaviour.

The reason is because browsers treat timezone here in a different way. For example, Chrome and Safari assume that the time is given in UTC, whereas others are expecting it to be in local format. Try to extract the day of month and you will notice the difference.

It is not summer yet in New York 😱

By the way if you worked with Date in Vanilla JavaScript before you probably noticed that month starts from zero (getMonth function will return an integer between 0 and 11) which makes everything even funnier.

The irony: because our dev team is located in Moscow’s timezone (it’s GMT+03 and Date.parse always gives us the same day) we simply couldn’t spot the bug in a first place.

How to avoid those awful mistakes in the future?

You should never use Date.parse function. There is a version of Date constructor that takes year, month and day integers instead:

You can also use an external library for date parsing. We already had moment.js in our project, but take into an account that it’s a pretty fat dependency.

Finally, consider using timestamps but what is most important — write acceptance tests for your interfaces.

Сonclusion

We’ve been lucky enough not to lose our clients because of this bug, however there is still some deep irritation left after this case. Because of the new tests this error won’t occur in our project and because of this article you can avoid it in yours. Cheers! 🤓

If you want an awesome resume done in 5 minutes, drop us a line at hello@theseguys.io and we’ll give you one week free access to resume.io!

About the author

Alexey Taktarov is a lead developer in a small design+dev team These Guys, where he works on complex single-page apps and MVPs. Alex writes Ruby and JavaScript and his swiss knife is Ruby on Rails, React, Redux and Redux Saga.

In the meantime he runs Code Hipsters community and does cool visualisations for ficus.io.

Married, has three cats.