Working with dates can get confusing. Depending on the time of day or the timezone in which your browser or server are located or whether you are working in a browser or in a Node.js environment, you could see different dates and times in the Date objects. Why is that? This page is an attempt to demystify the JavaScript Date object and to provide some solutions to this confusing mess.
2019-11-14T00:55:31.820Z
(See UTC vs ISO format for time.) So you can think of UTC as a time zone and ISO 8601 as a standardized format for displaying dates and times.toISOString()
method to convert all datetime objects to UTC time in both your browser and on your server. The timezone for toISOString()
is always UTC (MDN Date.prototype.toISOString()
). This will preserve the datetime and it can easily be converted to a Date object. (See Datetime difference on server and client side timezone.)toISOString()
method that returns a date string in ISO format (MDN Date.prototype.toISOString()
).Intl.DateTimeFormat()
method to format date objects into different locales, if necessary. Keep in mind that you will need to specifically set the timeZone
option to "UTC"
in order to preserve the UTC timezone.One idea is to convert all your (database) inputs and (browser) outputs involving dates to strings. If you need to manipulate a date, then you can convert it to an object, perform the manipulations, and then convert it back to a string before storing it in a database (an input) or displaying it in a browser (an output). For example:
toISOString()
method (an input).new Date()
constructor.getUTCDate()
, getUTCHours()
, setUTCDate()
, setUTCHours()
).toString
functions (e.g. date.toLocaleDateString()
, date.toLocaleString()
, date.toLocaleTimeString()
).Intl.DateTimeFormat()
) or string methods on the ISO-formatted date string (e.g. String.substring()
, String.split()
) to create the date string that you need.If you think of working with dates in terms of working with the string version of those dates, then you can avoid many of the pitfalls that are associated with Date objects. Remember that when creating or working with dates, it is probably best to always work with the UTC timezone and it is recommended to use the ISO format.
It is important to understand that the implementation of Date between browsers and Node.js is different. For example, Node.js uses ISO-formatted Date objects set in the UTC timezone (see this GitHub issue) while browsers use a Date object representing the date interpreted in the local timezone (MDN Date). There are a few things you can do to avoid these differences:
toISOString()
method will work in both browsers and Node.js and is transferrable between both environments without any conversion or formatting issues. Just be aware that if you pass the result of the toISOString()
method to a new Date()
constructor, then you will get different results depending on the environment.Note that you can use UTC JavaScript methods (date.setUTCHours()
instead of date.setHours()
) in an effort to ensure that all datetime objects use UTC time, but that still won’t work in browsers. The best options for working with dates inside browsers are the two options described above. However, in Node.js you can use UTC methods to get and set datetime objects in UTC time. You should use the UTC version of any date functions in Node.js when they are available.
Which ever option you choose, make sure to test your code and verify that it works as you expect.
You can test these examples in a browser console or a Node REPL window (open a terminal window, type node
, and press Enter) to see how they work and the results they return.
In a browser the new Date()
constructor will create a Date object that is evaluated to the local time zone. (See Individual date and time component values on the MDN Date()
constructor page.) But in Node.js the new Date()
constructor will create an ISO-formatted Date object with UTC time. So instead of creating a date with new Date()
, you can do this:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
In Node.js this will create a Date object that uses the UTC time zone and that is in ISO format. The new Date().toISOString()
method will return a string representing this date in ISO format and the timezone is always UTC, as denoted by the suffix Z
(Date.prototype.toISOString()). Passing an ISO formatted date string to the new Date()
constructor is standardized and will work reliably. (See Several ways to create a Date object.)
You can also use one of these options to create a Date string or Date object with a specific date:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
Instead of using setHours()
on a Date object, use the setUTCHours()
method. This will work in browsers and Node.js. The setUTCHours()
method will return a timestamp, but you can convert the timestamp into an ISO-formatted date string.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |