JavaScript for impatient programmers (ES2022 edition)
Please support this book: buy it or donate
(Ad, please don’t block.)

44 Dates (Date)



This chapter describes JavaScript’s API for working with dates – the class Date.

44.1 Best practice: avoid the built-in 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.

44.1.1 Things to look for in a date library

Two things are important to keep in mind:

44.2 Time standards

44.2.1 Background: UTC vs. Z vs. GMT

UTC, Z, and GMT are ways of specifying time that are similar, but subtly different:

Sources:

44.2.2 Dates do not support time zones

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:

// CEST (Central European Summer Time)
assert.equal(
  new Date('2122-06-29').getTimezoneOffset(), -120);
  
// CET (Central European Time)
assert.equal(
  new Date('2122-12-29').getTimezoneOffset(), -60);

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.

> new Date(2077, 0, 27).toISOString()
'2077-01-26T23:00:00.000Z'

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.

44.2.2.1 The downsides of not being able to specify time zones

Not being able to specify time zones has two downsides:

44.3 Background: date time formats (ISO)

Date time formats describe:

The following is an example of a date time string returned by .toISOString():

'2033-05-28T15:59:59.123Z'

Date time formats have the following structures:

Instead of Z (which is UTC+0), we can also specify time offsets relative to UTC:

44.3.1 Tip: append a Z to 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:

44.4 Time values

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:

const timeValue = 0;
assert.equal(
  new Date(timeValue).toISOString(),
  '1970-01-01T00:00:00.000Z');

Coercing a Date to a number returns its time value:

> Number(new Date(123))
123

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);

44.4.1 Creating time values

The following methods create time values:

44.4.2 Getting and setting time values

44.5 Creating Dates

44.5.1 Creating dates via numbers

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:

Example:

> new Date(2077,0,27, 21,49).toISOString() // CET (UTC+1)
'2077-01-27T20:49:00.000Z'

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.

44.5.2 Parsing dates from strings

new Date(dateTimeStr: string) (local time zone, UTC, time offset)

If there is a Z at the end, UTC is used:

> new Date('2077-01-27T00:00Z').toISOString()
'2077-01-27T00:00:00.000Z'

If there is not Z or time offset at the end, the local time zone is used:

> new Date('2077-01-27T00:00').toISOString() // CET (UTC+1)
'2077-01-26T23:00:00.000Z'

If a string only contains a date, it is interpreted as UTC:

> new Date('2077-01-27').toISOString()
'2077-01-27T00:00:00.000Z'

44.5.3 Other ways of creating dates

44.6 Getters and setters

44.6.1 Time unit getters and setters

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:

There is one more getter that doesn’t conform to the previously mentioned patterns:

44.7 Converting Dates to strings

Example Date:

const d = new Date(0);

44.7.1 Strings with times

44.7.2 Strings with dates

44.7.3 Strings with dates and times

44.7.4 Other methods

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

exercises/dates/create_date_string_test.mjs