Date
)This chapter describes JavaScript’s API for working with dates – the class Date
.
The JavaScript 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.
Additionally, TC39 is working on a new date API for JavaScript: temporal
.
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 (Coordinated Universal Time) and GMT (Greenwich Mean Time) are ways of specifying time that are similar, but subtly different:
UTC: 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.
GMT: 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.
Source: “The Difference Between GMT and UTC” at TimeAndDate.com
You can’t specify arbitrary time zones for JavaScript dates. Two time systems are used:
Instances of Date
store their time in UTC. Whenever you convert between dates and other data, you need to be mindful of whether UTC or the local time zone is 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.
Date operations: UTC vs. local time zone
For each operation documented in this chapter, that converts between dates and other data, it is noted whether UTC or the local time zone is used.
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. In this particular case, the input was interpreted as CET, while the output was in UTC. That’s why the days of the month differed (27 vs. 26).
Date time formats describe:
Date.parse()
new Date()
Date.prototype.toISOString()
The following is an example of a date time string returned by .toISOString()
:
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=time zone is UTC (the string 'Z'
)
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.
YYYY-MM-DDTHH:mm:ss.sssZ
Alternative to Z
– time zones relative to UTC:
+hh:mm
-hh:mm
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:
assert.equal(new Date('1972-05-03') < new Date('2001-12-23'), true);
// Internally:
assert.equal(73699200000 < 1009065600000, true);
The following methods create time values:
Date.now(): number
Returns the current time as a time value.
Date.parse(dateTimeStr: string): number
(time zone specified in string)
Parses 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
Returns the time value corresponding to the Date.
Date.prototype.setTime(timeValue)
Sets this
to the date encoded by timeValue
.
new Date(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number)
(local time zone)
Note how input (local time zone) and output (UTC) differ.
new Date(dateTimeStr: string)
(time zone specified in string)
new Date(timeValue: number)
new Date()
(same as new Date(Date.now())
)
The first variant of new Date()
receives two time units that are problematic:
For month
, 0 is January, etc.
If 0 ≤ year
≤ 99, then 1900 is added:
That’s why, elsewhere in this chapter, we always use the time unit fullYear
. But in this case, we have no choice.
Dates have getters and setters for time units. For example:
Date.prototype.getFullYear()
Date.prototype.setFullYear(num)
These getters and setters conform to the following patterns:
Date.prototype.get«Unit»()
Date.prototype.set«Unit»(num)
Date.prototype.getUTC«Unit»()
Date.prototype.setUTC«Unit»(num)
These are the time units that are supported:
FullYear
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:
Date.prototype.getTimezoneOffset()
Returns the time difference between local time and UTC in minutes. For example, for CET, it returns -60
.
Example Date:
Date.prototype.toTimeString()
(local time zone)
Date.prototype.toDateString()
(local time zone)
Date.prototype.toString()
(local time zone)
Date.prototype.toUTCString()
(UTC)
Date.prototype.toISOString()
(UTC)
The following three methods are not really part of ECMAScript, but rather of the ECMAScript internationalization API. That API has significant functionality for formatting dates (incl. support for time zones), but not for parsing them.
Date.prototype.toLocaleTimeString()
Date.prototype.toLocaleDateString()
Date.prototype.toLocaleString()
Exercise: Creating a date string
exercises/dates/create_date_string_test.mjs