JavaScript Date() issue since Chrome 67

Rik Driever
Jul 13, 2018 · 4 min read

Recently we discovered a weird behavior in one of our applications. A control was showing a different value than it had been showing for years under the same circumstances.

Image for post
Image for post

The above control was supposed to show two blanks and 10 minutes, but instead it shows 23 hours and 29 minutes.

This was a piece of legacy code that hadn’t been touched for at least 3 years.

The issue

In our database (SQL Server) we have a DateTime field to store a duration. This field is filled by creating a new SqlDateTime object and then adding the required amount of time to the object.

This stores the value in the database as “1900–01–01 00:10:00.000”.

When we want to display the current value in the control, we retrieve it and convert it to JSON.

The value in the jsonOutput string is “/Date(-2208991800000)”.

Wow that’s a nice number, what the heck does it mean?

It’s the number of milliseconds since January 1 1970; the start of the Unix epoch. And because the number is negative, it actually represents the milliseconds before the Unix time.

If you’re reading this in Chrome, press F12 to open the Console and type this:

If you’re on Chrome 67 and in Western Europe you’ll likely see something like this:

What the … that’s not what we put it. What’s going on? (At least we know where the 23 hours and 29 minutes originates from.)

Well, it turns out back in 1900 we had a different time zone offset than in 1970 (and today) and Chrome has implemented a change that returns the time zone offset for the actual date in the Date object.

The fix

At first we tried to solve the problem in JavaScript.

We know that in january 1970 our timezone offset was GMT+0100 and we see that in 1900 it was GMT+0019, so surely if we add 41 minutes we get the correct time, right? Well, not exactly …

Copy/Paste that in your Chrome console and you’ll see this output:

It’s close, but it’s not correct. The timezone offset that’s returned is in minutes (hence the multiplication with 60000 in the correction variable). But apparently it wasn’t exactly 19 minutes.

Luckily there’s the toUTCString() function. Since we’re in the GMT+1 timezone, we need to add an hour before casting it to a UTC string.

The output is:

But now it’s a string and not a Date object. So we can’t use functions like getFullYear() so our code breaks. And if we cast this back to a Date, what do we get?


We really didn’t want to go into string parsing to get time parts. And you can’t just add an hour to any date passed into the function, so some logic would have to be added. Not to mention that for now browsers like IE, Safari and FireFox have not yet implemented this change, resulting in even more logic.

We reflected on the issue for a moment and realised the main issue is the incompatibility between the implementations of .net’s JavaScriptSerializer.Serialize() and Chrome’s Date() function.

Perhaps it would have been possible to customize the Serialize() function to return a string, but we opted to use Newtonsoft’s JsonConvert library instead, because it’s .SerializeObject() method serializes a date as a string by default.

So JSON output no longer has a value of “/Date(-2208991800000)” but “1900–01–01T00:10:00”. That in itself is already a welcome change, but let’s parse it to a Date in JavaScript and see what happens.

Excellent. We now have a Date object with the same date and time as we’ve stored in our database.

And that’s it, bug fixed, case closed. I hope this story will save others some time with this or similar issues.

As a final remark I’d like to say that saving a duration as a DateTime data type is probably not the best approach. I’d recommend to store a duration as an integer if you need second or minute precision or a long (BIGINT) to store Ticks if you need more precision.

The smallest unit of time is the tick, which is equal to 100 nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond. The value of the Ticks property can be negative or positive to represent a negative or positive time interval.

Image for post
Image for post

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store