
Things I learned about JavaScript’s Date
ce@neckar.it
JavaScript’s Date
does not stop to amaze me.
Probably every developer has encountered lots of problems when working with it.
Most projects use other date libraries like Moment.js or JS-Joda to cope with its shortcomings.
In case you want to or have to stick to JavaScript’s Date
here are some things I find useful to remember.
Time-Zones
The most important thing of all is that you can’t determine the time-zone of a Date
-object by simply looking at it.
You can only retrieve information related to the browser’s local time-zone or to the UTC-time-zone.
Date provides various getters to do that:
- getUTCHours / getHours
- getUTCMinutes / getMinutes
- getUTCSeconds / getSeconds
- …
The result of the UTC-getters will be the same all over the world whereas the result of the non-UTC-getters depends on the browser’s local time-zone.
Hence if you want to compare dates compare them using the UTC-time zone. This can be achieved by using the toISOString
-function.
If you want to compare dates always use toISOString!
Date-constructors
You need to take extra care when creating Date
-objects. Date
provides several constructor-signatures:
Constructor | toString | toISOString | getHours | getUTCHours | is a UTC date |
---|---|---|---|---|---|
new Date(1692967999168) | Fri Aug 25 2023 14:53:19 GMT+0200 (Central European Summer Time) | 2023-08-25T12:53:19.168Z | 14 | 12 | yes |
new Date(‚2023-08-25T12:53:19.168Z‘) | Fri Aug 25 2023 14:53:19 GMT+0200 (Central European Summer Time) | 2023-08-25T12:53:19.168Z | 14 | 12 | yes |
new Date(‚2023-08-25 12:53:19.168 UTC‘) | Fri Aug 25 2023 14:53:19 GMT+0200 (Central European Summer Time) | 2023-08-25T12:53:19.168Z | 14 | 12 | yes |
new Date(2023, 7, 25, 12, 53, 19, 168) | Fri Aug 25 2023 12:53:19 GMT+0200 (Central European Summer Time) | 2023-08-25T10:53:19.168Z | 12 | 10 | no |
As you can see there are constructors that interpret their arguments as a UTC date and constructors that interpret their arguments as a local date.
I recommend to use the constructors that interpret their arguments as a UTC date. Combined with the UTC-getters you can avoid the conversion to the browser’s local time-zone altogether.
Stick to UTC-dates as far as possible!
Formatting Dates
Most of the time human beings want to view the date in their time-zone (which is probably not UTC).
In that case try not to convert the Date
-object programmatically but use the Intl.DateTimeFormat
to format the date:
console.log(
new Intl.DateTimeFormat('en-GB', { dateStyle: 'full', timeStyle: 'long', timeZone: 'Australia/Sydney' }).format(new Date(1692967999168)),
);
// result: Friday, 25 August 2023 at 22:53:19 GMT+10
Use Intl.DateTimeFormat to format a date with a certain time-zone.
Invalid Dates
Sometimes you may encounter invalid Date
-objects. That may happen on purpose or by accident (e.g. an invalid user input).
An invalid Date
-object is still an object of type Date
but you may run into errors if you try to do something useful with it:
new Date('13-13-13').toISOString();
// will throw: Uncaught RangeError: Invalid time value at Date.toISOString
Fortunately, there is an easy way to detect an invalid date. Calling getTime
on an invalid date will return NaN (not a number):
const invalidDate = new Date('13-13-13');
const timestamp = invalidDate.getTime();
Number.isNaN(timestamp); // evaluates to true!
getTime will evaluate to Number.NaN if the date is invalid.
This implies that you can create an invalid date with new Date(Number.NaN)
.
Conclusion
It’s hard to work with JavaScript-Date
objects. Try to stick to UTC dates and use other time-zones only when formatting the date.
I hope you can use some of the provided insights.
Let me know if you find a bug or want something to be added.
Until then, happy coding!