JavaScript Date: a Bad Part
We all know that JavaScript has some bad parts. However, one of them is usually forgotten, and skipped in most of "JavaScript Bad Parts" lists on the Internet. It is a Date
object. You can have hard time working with it, especially if you want to support time zones. In this post I would like to outline quircks of Date
in JavaScript.
Basics
In order to create a Date
object, you just do:
This will create a date set to now.
If you want to create Date
on specific day:
Here you encounter the first quirk: months are numbered from 0 to 11. January is 0, December is 11.
You can also specify hours, minutes, seconds, and milliseconds as additional parameters (no more pitfalls here):
For more details about creating Date
, check Date at MDN.
Formatting
If you want to display a date, there are a few available converters. Here are the most commonly used:
Be careful with 3 and 4. Both return different results, depended on user's machine settings and geographical location. This may cause UI issues (some date formats might be long).
Converters 5 and 6 are equivalent in all, most popular browsers. However toGMTString
is deprecated.
Converters 7 and 8 are also equivalent. Moreover, toJSON
use toISOString
underneath to return result.
There is no significant issues with displaying Date, but there is no way to format it with custom format (e.g., 'YYYY-MM-DD HH:mm') like in C# or Java.
Alternative for formatting is Intl.DateTimeFormat object from ECMAScript Internationalization API. However, this API is not yet supported by older browsers, most of mobile browsers, and Safari (check browser compatibility on MDN).
Parsing
More tricky than displaying dates, is parsing them. There are two common ways to parse date from string:
First returns Date
object, second - number 1425106597000 (milliseconds since January 1, 1970, 00:00:00 UTC).
There is one, very unpleasant detail in parsing:
Given a date string of "March 7, 2014", parse() assumes a local time zone, but given an ISO format such as "2014-03-07" it will assume a time zone of UTC. Therefore Date objects produced using those strings will represent different moments in time unless the system is set with a local time zone of UTC. This means that two date strings that appear equivalent may result in two different values depending on the format of the string that is being converted (this behavior is changed in ECMAScript ed 6 so that both will be treated as local).
This means that date1
and date2
below (created from machine located in Seattle, WA) are different:
Recommended format for parsing is: YYYY/MM/DD
- user local settings independent. It always assumes local timezone offset for date string given as a parameter.
Timezones
JavaScript Date
object always assumes local timezone offset for the machine on which it is displayed. What is important: JavaScript Date
does not support time zones, but only timezone offsets. This is a definition of both from Wikipedia:
A time zone is a geographical region where just about everybody observes the same standard time.
A time offset is an amount of time subtracted from or added to UTC to get the current civil time - whether it's standard time or Daylight saving time.
In other words: time zone is constant (as long as government does not changed it) for some place (e.g., San Francisco) all the time, while time zone offset changes (usually, twice a year - this is what we call 'daylight savings').
To get timezone offset:
The result is in minutes. Here is another quirk: timezones that are 'west' from UTC (offset = 0) have positive values (60 - 720), and timezones that are 'east' from UTC have negative values (-60 - -780). Thus, Pacific Standard Time (UTC -8:00), in JavaScript, has timezone offset 480, and Central European Time (UTC +1:00) has timezone offset -60.
One more pitfall: local timezone offset is always set depends on value of Date
object. Thus, for Computer located in Seattle, WA:
In this case your current 'local' timezone offset (for the time in which you are creating Date object) does not matter.
Even if you create Date object with date before the time change, and then you modify it to date after the time change - its timezone offset changes to reflect offset for the new (current) value:
Moment.js
Moment.js is a JavaScript library designed to work on the client side (in browser), and on the server side (in node.js). It has a lot of functions to parse, display and manipulate dates. This makes dealing with dates less painful.
Moment Timezone - a library built on top of Moment.js - supports real time zones (not only timezone offsets). The data for Moment Timezone comes from the IANA Time Zone Database - most popular time zone database. New versions are released periodically as timezone laws change in various countries.
Consider using Moment.js and Moment Timezone in your application when you are doing more complex operations with dates. Especially when you want to support time zones.
Summary
It is really surprising that working with dates in programming is still causing a lot of issues. However, we are getting better at that. To get a comprehensive overview of date/time in programming language I recommend Date and Time Fundamentals by Matt Johnson. You can also check Matt Johnson's blog. He blogs mainly about date/time in variety of environments. His article JavaScript Date type is horribly broken might be good supplement for this post.
To get a quick insight why dealing with time zones is very complex, check this video. It is also worth to check What Every Programmer Should know about Time.