Rules of parsing dates with Date.parse
Rule of thumb: don’t use it!
At resume.io — an online resume builder, we 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 telling us 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!
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 a UI-friendly format and transform it back when the value is changed. It’s 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:
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 timezones here differently. 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.
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 thefirst 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. What is most important — write acceptance tests for your interfaces.
Сonclusion
We’ve been lucky enough not to lose our users 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! 🤓
About the author
Alexey Taktarov is the Founder & CTO at Resume.io and 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.