Date API is cumbersome to use. Hence, it’s best to rely on a library for anything related to dates. Popular libraries include:
Consult the blog post “Why you shouldn’t use Moment.js…” for the pros and cons of these libraries.
Two things are important to keep in mind:
Tree-shaking can considerably reduce the size of a library. It is a technique of only deploying those exports of a library to a web server that are imported somewhere. Functions are much more amenable to tree-shaking than classes.
Support for time zones: As explained later,
Date does not support time zones, which introduces a number of pitfalls and is a key weakness. Make sure that your date library supports them.
UTC, Z, and GMT are ways of specifying time that are similar, but subtly different:
UTC (Coordinated Universal Time) is the time standard that all times zones are based on. They are specified relative to it. That is, no country or territory has UTC as its local time zone.
Z (Zulu Time Zone) is a military time zone that is often used in aviation and the military as another name for UTC+0.
GMT (Greenwich Mean Time) is a time zone used in some European and African countries. It is UTC plus zero hours and therefore has the same time as UTC.
Dates support the following time standards:
Depending on the operation, only some of those options are available. For example, when converting dates to strings or extracting time units such as the day of the month, you can only choose between the local time zone and UTC.
Internally, Dates are stored as UTC. When converting from or to the local time zone, the necessary offsets are determined via the date. In the following example, the local time zone is Europe/Paris:
Whenever you create or convert dates, you need to be mindful of the time standard being used – for example:
new Date() uses the local time zone while
.toISOString() uses UTC.
Dates interpret 0 as January. The day of the month is 27 in the local time zone, but 26 in UTC.
Documenting the time standards supported by each operation
In the remainder of this chapter, the supported time standards are noted for each operation.
Not being able to specify time zones has two downsides:
It makes it impossible to support multiple time zones.
It can lead to location-specific bugs. For example, the previous example produces different results depending on where it is executed. To be safe:
Zor a time offset when parsing strings (see the next section for more information).
Date time formats describe:
The following is an example of a date time string returned by
Date time formats have the following structures:
Date formats: Y=year; M=month; D=day
YYYY-MM-DD YYYY-MM YYYY
Time formats: T=separator (the string
'T'); H=hour; m=minute; s=second and millisecond; Z=Zulu Time Zone (the string
THH:mm:ss.sss THH:mm:ss.sssZ THH:mm:ss THH:mm:ssZ THH:mm THH:mmZ
Date time formats: are date formats followed by time formats.
Z (which is UTC+0), we can also specify time offsets relative to UTC:
Zto make date parsing deterministic
If you add a
Z to the end of a string, date parsing doesn’t produce different results at different locations:
Z: Input is January 27 (in the Europe/Paris time zone), output is January 26 (in UTC).
Z: Input is January 27, output is January 27.
A time value represents a date via the number of milliseconds since 1 January 1970 00:00:00 UTC.
Time values can be used to create Dates:
Coercing a Date to a number returns its time value:
Ordering operators coerce their operands to numbers. Therefore, you can use these operators to compare Dates:
The following methods create time values:
Date.now(): number (UTC)
Returns the current time as a time value.
Date.parse(dateTimeStr: string): number (local time zone, UTC, time offset)
dateTimeStr and returns the corresponding time value.
Date.UTC(year, month, date?, hours?, minutes?, seconds?, milliseconds?): number (UTC)
Returns the time value for the specified UTC date time.
Date.prototype.getTime(): number (UTC)
Returns the time value corresponding to the Date.
this to the date encoded by
new Date(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number) (local time zone)
Two of the parameters have pitfalls:
month, 0 is January, 1 is February, etc.
If 0 ≤
year ≤ 99, then 1900 is added:
That’s why, elsewhere in this chapter, we avoid the time unit
year and always use
fullYear. But in this case, we have no choice.
Note that the input hours (21) are different from the output hours (20). The former refer to the local time zone, the latter to UTC.
new Date(dateTimeStr: string) (local time zone, UTC, time offset)
If there is a
Z at the end, UTC is used:
If there is not
Z or time offset at the end, the local time zone is used:
If a string only contains a date, it is interpreted as UTC:
new Date(timeValue: number) (UTC)
new Date() (UTC)
The same as
Dates have getters and setters for time units – for example:
These getters and setters conform to the following patterns:
These are the time units that are supported:
Month: month (0–11). Pitfall: 0 is January, etc.
Date: day of the month (1–31)
Day(getter only): day of the week (0–6, 0 is Sunday)
Hours: hour (0–23)
Minutes: minutes (0–59)
Seconds: seconds (0–59)
Milliseconds: milliseconds (0–999)
There is one more getter that doesn’t conform to the previously mentioned patterns:
Returns the time difference between local time zone and UTC in minutes. For example, for Europe/Paris, it returns
-120 (CEST, Central European Summer Time) or
-60 (CET, Central European Time):
Date.prototype.toTimeString() (local time zone)
Date.prototype.toDateString() (local time zone)
Date.prototype.toString() (local time zone)
The following three methods are not really part of ECMAScript, but rather of the ECMAScript internationalization API. That API has much functionality for formatting dates (including support for time zones), but not for parsing them.
Exercise: Creating a date string