Stage 3 Draft / March 26, 2024

Temporal proposal

Introduction

The venerable ECMAScript Date object has a number of challenges, including lack of immutability, lack of support for time zones, lack of support for use cases that require dates only or times only, a confusing and non-ergonomic API, and many other challenges.

The Temporal set of types addresses these challenges with a built-in date and time API for ECMAScript that includes:

Figure 1: Temporal Object Relationships
Figure 2: Temporal String Persistence

This specification consists of three parts:

1 The Temporal Object

The Temporal object:

  • is the intrinsic object %Temporal%.
  • is the initial value of the "Temporal" property of the global object.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is not a function object.
  • does not have a [[Construct]] internal method; it cannot be used as a constructor with the new operator.
  • does not have a [[Call]] internal method; it cannot be invoked as a function.

1.1 Value Properties of the Temporal Object

1.1.1 Temporal [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

1.2 Constructor Properties of the Temporal Object

1.2.1 Temporal.Calendar ( . . . )

See 12.

1.2.2 Temporal.Instant ( . . . )

See 8.

1.2.3 Temporal.PlainDateTime ( . . . )

See 5.

1.2.4 Temporal.PlainDate ( . . . )

See 3.

1.2.5 Temporal.PlainTime ( . . . )

See 4.

1.2.6 Temporal.PlainYearMonth ( . . . )

See 9.

1.2.7 Temporal.PlainMonthDay ( . . . )

See 10.

1.2.8 Temporal.TimeZone ( . . . )

See 11.

1.2.9 Temporal.Duration ( . . . )

See 7.

1.2.10 Temporal.ZonedDateTime ( . . . )

See 6.

1.3 Other Properties of the Temporal Object

1.3.1 Temporal.Now

See 2.

2 The Temporal.Now Object

The Temporal.Now object:

  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is not a function object.
  • does not have a [[Construct]] internal method; it cannot be used as a constructor with the new operator.
  • does not have a [[Call]] internal method; it cannot be invoked as a function.

2.1 Value Properties of the Temporal.Now Object

2.1.1 Temporal.Now [ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.Now".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

2.2 Function Properties of the Temporal.Now Object

2.2.1 Temporal.Now.timeZoneId ( )

This function performs the following steps when called:

  1. Return SystemTimeZoneIdentifier().

2.2.2 Temporal.Now.instant ( )

This function performs the following steps when called:

  1. Return ! SystemInstant().

2.2.3 Temporal.Now.plainDateTime ( calendarLike [ , temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Return ? SystemDateTime(temporalTimeZoneLike, calendarLike).

2.2.4 Temporal.Now.plainDateTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Return ? SystemDateTime(temporalTimeZoneLike, "iso8601").

2.2.5 Temporal.Now.zonedDateTime ( calendarLike [ , temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Return ? SystemZonedDateTime(temporalTimeZoneLike, calendarLike).

2.2.6 Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Return ? SystemZonedDateTime(temporalTimeZoneLike, "iso8601").

2.2.7 Temporal.Now.plainDate ( calendarLike [ , temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, calendarLike).
  2. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]).

2.2.8 Temporal.Now.plainDateISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, "iso8601").
  2. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], "iso8601").

2.2.9 Temporal.Now.plainTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let dateTime be ? SystemDateTime(temporalTimeZoneLike, "iso8601").
  2. Return ! CreateTemporalTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).

2.3 Abstract Operations

2.3.1 HostSystemUTCEpochNanoseconds ( global )

The host-defined abstract operation HostSystemUTCEpochNanoseconds takes argument global (a global object) and returns an integer. It allows host environments to reduce the precision of the result. In particular, web browsers artificially limit it to prevent abuse of security flaws (e.g., Spectre) and to avoid certain methods of fingerprinting.

An implementation of HostSystemUTCEpochNanoseconds must conform to the following requirements:

Note

This requirement is necessary if the system clock is set to a time outside the range that Temporal.Instant can represent. This is not expected to affect implementations in practice.

The default implementation of HostSystemUTCEpochNanoseconds performs the following steps when called:

  1. Let ns be the approximate current UTC date and time, in nanoseconds since the epoch.
  2. Return the result of clamping ns between nsMinInstant and nsMaxInstant.

ECMAScript hosts that are not web browsers must use the default implementation of HostSystemUTCEpochNanoseconds.

2.3.2 SystemUTCEpochMilliseconds ( )

  1. Let global be GetGlobalObject().
  2. Let nowNs be HostSystemUTCEpochNanoseconds(global).
  3. Return 𝔽(floor(nowNs / 106)).

2.3.3 SystemUTCEpochNanoseconds ( )

  1. Let global be GetGlobalObject().
  2. Let nowNs be HostSystemUTCEpochNanoseconds(global).
  3. Return (nowNs).

2.3.4 SystemInstant ( )

  1. Let ns be ! SystemUTCEpochNanoseconds().
  2. Return ! CreateTemporalInstant(ns).

2.3.5 SystemDateTime ( temporalTimeZoneLike, calendarLike )

  1. If temporalTimeZoneLike is undefined, then
    1. Let timeZone be SystemTimeZoneIdentifier().
  2. Else,
    1. Let timeZone be ? ToTemporalTimeZoneSlotValue(temporalTimeZoneLike).
  3. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  4. Let instant be ! SystemInstant().
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for »).
  6. Return ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).

2.3.6 SystemZonedDateTime ( temporalTimeZoneLike, calendarLike )

  1. If temporalTimeZoneLike is undefined, then
    1. Let timeZone be SystemTimeZoneIdentifier().
  2. Else,
    1. Let timeZone be ? ToTemporalTimeZoneSlotValue(temporalTimeZoneLike).
  3. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  4. Let ns be ! SystemUTCEpochNanoseconds().
  5. Return ! CreateTemporalZonedDateTime(ns, timeZone, calendar).

3 Temporal.PlainDate Objects

A Temporal.PlainDate object is an Object that contains integers corresponding to a particular year, month, and day in the ISO8601 calendar, as well as an Object value used to interpret those integers in a particular calendar.

3.1 The Temporal.PlainDate Constructor

The Temporal.PlainDate constructor:

  • creates and initializes a new Temporal.PlainDate object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.PlainDate behaviour must include a super call to the %Temporal.PlainDate% constructor to create and initialize subclass instances with the necessary internal slots.

3.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendarLike ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let y be ? ToIntegerWithTruncation(isoYear).
  3. Let m be ? ToIntegerWithTruncation(isoMonth).
  4. Let d be ? ToIntegerWithTruncation(isoDay).
  5. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  6. Return ? CreateTemporalDate(y, m, d, calendar, NewTarget).

3.2 Properties of the Temporal.PlainDate Constructor

The Temporal.PlainDate constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

3.2.1 Temporal.PlainDate.prototype

The initial value of Temporal.PlainDate.prototype is %Temporal.PlainDate.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

3.2.2 Temporal.PlainDate.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. If Type(item) is Object and item has an [[InitializedTemporalDate]] internal slot, then
    1. Perform ? ToTemporalOverflow(options).
    2. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]]).
  3. Return ? ToTemporalDate(item, options).

3.2.3 Temporal.PlainDate.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalDate(one).
  2. Set two to ? ToTemporalDate(two).
  3. Return 𝔽(! CompareISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]])).

3.3 Properties of the Temporal.PlainDate Prototype Object

The Temporal.PlainDate prototype object

  • is itself an ordinary object.
  • is not a Temporal.PlainDate instance and does not have a [[InitializedTemporalDate]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

3.3.1 Temporal.PlainDate.prototype.constructor

The initial value of Temporal.PlainDate.prototype.constructor is %Temporal.PlainDate%.

3.3.2 Temporal.PlainDate.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.PlainDate".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

3.3.3 get Temporal.PlainDate.prototype.calendarId

Temporal.PlainDate.prototype.calendarId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ? ToTemporalCalendarIdentifier(temporalDate.[[Calendar]]).

3.3.4 get Temporal.PlainDate.prototype.year

Temporal.PlainDate.prototype.year is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarYear(calendar, temporalDate)).

3.3.5 get Temporal.PlainDate.prototype.month

Temporal.PlainDate.prototype.month is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarMonth(calendar, temporalDate)).

3.3.6 get Temporal.PlainDate.prototype.monthCode

Temporal.PlainDate.prototype.monthCode is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return ? CalendarMonthCode(calendar, temporalDate).

3.3.7 get Temporal.PlainDate.prototype.day

Temporal.PlainDate.prototype.day is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « day »).
  4. Return 𝔽(? CalendarDay(calendarRec, temporalDate)).

3.3.8 get Temporal.PlainDate.prototype.dayOfWeek

Temporal.PlainDate.prototype.dayOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarDayOfWeek(calendar, temporalDate)).

3.3.9 get Temporal.PlainDate.prototype.dayOfYear

Temporal.PlainDate.prototype.dayOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarDayOfYear(calendar, temporalDate)).

3.3.10 get Temporal.PlainDate.prototype.weekOfYear

Temporal.PlainDate.prototype.weekOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarWeekOfYear(calendar, temporalDate)).

3.3.11 get Temporal.PlainDate.prototype.yearOfWeek

Temporal.PlainDate.prototype.yearOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarYearOfWeek(calendar, temporalDate)).

3.3.12 get Temporal.PlainDate.prototype.daysInWeek

Temporal.PlainDate.prototype.daysInWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInWeek(calendar, temporalDate)).

3.3.13 get Temporal.PlainDate.prototype.daysInMonth

Temporal.PlainDate.prototype.daysInMonth is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInMonth(calendar, temporalDate)).

3.3.14 get Temporal.PlainDate.prototype.daysInYear

Temporal.PlainDate.prototype.daysInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInYear(calendar, temporalDate)).

3.3.15 get Temporal.PlainDate.prototype.monthsInYear

Temporal.PlainDate.prototype.monthsInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return 𝔽(? CalendarMonthsInYear(calendar, temporalDate)).

3.3.16 get Temporal.PlainDate.prototype.inLeapYear

Temporal.PlainDate.prototype.inLeapYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be temporalDate.[[Calendar]].
  4. Return ? CalendarInLeapYear(calendar, temporalDate).

3.3.17 Temporal.PlainDate.prototype.toPlainYearMonth ( )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « fields, year-month-from-fields »).
  4. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  5. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»).
  6. Return ? CalendarYearMonthFromFields(calendarRec, fields).
  7. NOTE: The call to CalendarYearMonthFromFields is necessary in order to create a PlainYearMonth object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

3.3.18 Temporal.PlainDate.prototype.toPlainMonthDay ( )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « fields, month-day-from-fields »).
  4. Let fieldNames be ? CalendarFields(calendarRec, « "day", "monthCode" »).
  5. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»).
  6. Return ? CalendarMonthDayFromFields(calendarRec, fields).
  7. NOTE: The call to CalendarMonthDayFromFields is necessary in order to create a PlainMonthDay object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

3.3.19 Temporal.PlainDate.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", temporalDate.[[Calendar]]).
  5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(temporalDate.[[ISODay]])).
  6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(temporalDate.[[ISOMonth]])).
  7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(temporalDate.[[ISOYear]])).
  8. Return fields.

3.3.20 Temporal.PlainDate.prototype.getCalendar ( )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ToTemporalCalendarObject(temporalDate.[[Calendar]]).

3.3.21 Temporal.PlainDate.prototype.add ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let duration be ? ToTemporalDuration(temporalDurationLike).
  4. Set options to ? GetOptionsObject(options).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « date-add »).
  6. Return ? AddDate(calendarRec, temporalDate, duration, options).

3.3.22 Temporal.PlainDate.prototype.subtract ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let duration be ? ToTemporalDuration(temporalDurationLike).
  4. Set options to ? GetOptionsObject(options).
  5. Let negatedDuration be ! CreateNegatedTemporalDuration(duration).
  6. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « date-add »).
  7. Return ? AddDate(calendarRec, temporalDate, negatedDuration, options).

3.3.23 Temporal.PlainDate.prototype.with ( temporalDateLike [ , options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. If ? IsPartialTemporalObject(temporalDateLike) is false, throw a TypeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « date-from-fields, fields, merge-fields »).
  6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
  7. Let fields be ? PrepareTemporalFields(temporalDate, fieldNames, «»).
  8. Let partialDate be ? PrepareTemporalFields(temporalDateLike, fieldNames, partial).
  9. Set fields to ? CalendarMergeFields(calendarRec, fields, partialDate).
  10. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»).
  11. Return ? CalendarDateFromFields(calendarRec, fields, resolvedOptions).

3.3.24 Temporal.PlainDate.prototype.withCalendar ( calendarLike )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  4. Return ! CreateTemporalDate(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], calendar).

3.3.25 Temporal.PlainDate.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ? DifferenceTemporalPlainDate(until, temporalDate, other, options).

3.3.26 Temporal.PlainDate.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ? DifferenceTemporalPlainDate(since, temporalDate, other, options).

3.3.27 Temporal.PlainDate.prototype.equals ( other )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Set other to ? ToTemporalDate(other).
  4. If temporalDate.[[ISOYear]]other.[[ISOYear]], return false.
  5. If temporalDate.[[ISOMonth]]other.[[ISOMonth]], return false.
  6. If temporalDate.[[ISODay]]other.[[ISODay]], return false.
  7. Return ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]).

3.3.28 Temporal.PlainDate.prototype.toPlainDateTime ( [ temporalTime ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. If temporalTime is undefined, then
    1. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], 0, 0, 0, 0, 0, 0, temporalDate.[[Calendar]]).
  4. Set temporalTime to ? ToTemporalTime(temporalTime).
  5. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]).

3.3.29 Temporal.PlainDate.prototype.toZonedDateTime ( item )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalTimeZone]] internal slot, then
      1. Let timeZone be item.
      2. Let temporalTime be undefined.
    2. Else,
      1. Let timeZoneLike be ? Get(item, "timeZone").
      2. If timeZoneLike is undefined, then
        1. Let timeZone be ? ToTemporalTimeZoneSlotValue(item).
        2. Let temporalTime be undefined.
      3. Else,
        1. Let timeZone be ? ToTemporalTimeZoneSlotValue(timeZoneLike).
        2. Let temporalTime be ? Get(item, "plainTime").
  4. Else,
    1. Let timeZone be ? ToTemporalTimeZoneSlotValue(item).
    2. Let temporalTime be undefined.
  5. If temporalTime is undefined, then
    1. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], 0, 0, 0, 0, 0, 0, temporalDate.[[Calendar]]).
  6. Else,
    1. Set temporalTime to ? ToTemporalTime(temporalTime).
    2. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]).
  7. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  8. Let instant be ? GetInstantFor(timeZoneRec, temporalDateTime, "compatible").
  9. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, temporalDate.[[Calendar]]).

3.3.30 Temporal.PlainDate.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Set options to ? GetOptionsObject(options).
  4. Let showCalendar be ? ToCalendarNameOption(options).
  5. Return ? TemporalDateToString(temporalDate, showCalendar).

3.3.31 Temporal.PlainDate.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ? TemporalDateToString(temporalDate, "auto").

3.3.32 Temporal.PlainDate.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Return ? TemporalDateToString(temporalDate, "auto").

3.3.33 Temporal.PlainDate.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

3.4 Properties of Temporal.PlainDate Instances

Temporal.PlainDate instances are ordinary objects that inherit properties from the %Temporal.PlainDate.prototype% intrinsic object. Temporal.PlainDate instances are initially created with the internal slots described in Table 1.

Table 1: Internal Slots of Temporal.PlainDate Instances
Internal Slot Description
[[InitializedTemporalDate]] The only specified use of this slot is for distinguishing Temporal.PlainDate instances from other objects.
[[ISOYear]] An integer representing the year in the ISO 8601 calendar.
[[ISOMonth]] An integer between 1 and 12, inclusive, representing the month of the year in the ISO 8601 calendar.
[[ISODay]] An integer between 1 and ISODaysInMonth([[ISOYear]], [[ISOMonth]]), inclusive, representing the day of the month in the ISO 8601 calendar.
[[Calendar]] A String or Object representing the calendar.

3.5 Abstract Operations for Temporal.PlainDate Objects

3.5.1 ISO Date Records

An ISO Date Record is a Record value used to represent a valid calendar date in the ISO 8601 calendar, although the year may be outside of the allowed range for Temporal. ISO Date Records are produced by the abstract operation CreateISODateRecord.

ISO Date Records have the fields listed in Table 2.

Table 2: ISO Date Record Fields
Field Name Value Meaning
[[Year]] an integer The year in the ISO 8601 calendar.
[[Month]] an integer between 1 and 12, inclusive The number of the month in the ISO 8601 calendar.
[[Day]] an integer between 1 and 31, inclusive The number of the day of the month in the ISO 8601 calendar.

3.5.2 CreateISODateRecord ( year, month, day )

The abstract operation CreateISODateRecord takes arguments year (an integer), month (an integer between 1 and 12 inclusive), and day (an integer between 1 and 31 inclusive) and returns an ISO Date Record. It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }.

3.5.3 CreateTemporalDate ( isoYear, isoMonth, isoDay, calendar [ , newTarget ] )

The abstract operation CreateTemporalDate takes arguments isoYear (an integer), isoMonth (an integer), isoDay (an integer), and calendar (a String or Object) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainDate, or an abrupt completion. It creates a Temporal.PlainDate instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a RangeError exception.
  2. If ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0) is false, throw a RangeError exception.
  3. If newTarget is not present, set newTarget to %Temporal.PlainDate%.
  4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDate.prototype%", « [[InitializedTemporalDate]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »).
  5. Set object.[[ISOYear]] to isoYear.
  6. Set object.[[ISOMonth]] to isoMonth.
  7. Set object.[[ISODay]] to isoDay.
  8. Set object.[[Calendar]] to calendar.
  9. Return object.
Note

Deferring to ISODateTimeWithinLimits with an hour of 12 avoids trouble at the extremes of the representable range of dates, which stop just before midnight on each end.

3.5.4 ToTemporalDate ( item [ , options ] )

The abstract operation ToTemporalDate takes argument item (an ECMAScript language value) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainDate, or a throw completion. It returns its argument item if it is already a Temporal.PlainDate instance, converts item to a new Temporal.PlainDate instance if possible, and throws otherwise. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. If options is not undefined, set options to ? SnapshotOwnProperties(! GetOptionsObject(options), null).
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalDate]] internal slot, then
      1. Return item.
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Perform ? ToTemporalOverflow(options).
      2. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]).
      3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(item.[[TimeZone]], « get-offset-nanoseconds-for »).
      4. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, item.[[Calendar]]).
      5. Return ! CreateTemporalDate(plainDateTime.[[ISOYear]], plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]], plainDateTime.[[Calendar]]).
    3. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Perform ? ToTemporalOverflow(options).
      2. Return ! CreateTemporalDate(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]]).
    4. Let calendar be ? GetTemporalCalendarSlotValueWithISODefault(item).
    5. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « date-from-fields, fields »).
    6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
    7. Let fields be ? PrepareTemporalFields(item, fieldNames, «»).
    8. Return ? CalendarDateFromFields(calendarRec, fields, options).
  4. If item is not a String, throw a TypeError exception.
  5. Let result be ? ParseTemporalDateString(item).
  6. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
  7. Let calendar be result.[[Calendar]].
  8. If calendar is undefined, set calendar to "iso8601".
  9. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
  10. Set calendar to the ASCII-lowercase of calendar.
  11. Perform ? ToTemporalOverflow(options).
  12. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar).

3.5.5 ISODateSurpasses ( sign, y1, m1, d1, y2, m2, d2 )

The abstract operation ISODateSurpasses takes arguments sign (-1 or 1), y1 (an integer), m1 (an integer), d1 (an integer), y2 (an integer), m2 (an integer in the inclusive interval from 1 to 12), and d2 (an integer in the inclusive interval from 1 to ISODaysInMonth(m2)) and returns a Boolean. The return value indicates whether the date denoted by y1, m1, d1 surpasses that denoted by y2, m2, d2 in the direction denoted by sign. The former date does not have to exist. Note that this operation is specific to date difference calculations and is not the same as CompareISODate. It performs the following steps when called:

  1. Let comparison be CompareISODate(y1, m1, d1, y2, m2, d2).
  2. If sign × comparison is 1, return true.
  3. Return false.

3.5.6 DifferenceISODate ( y1, m1, d1, y2, m2, d2, largestUnit )

The abstract operation DifferenceISODate takes arguments y1 (an integer), m1 (an integer), d1 (an integer), y2 (an integer), m2 (an integer), d2 (an integer), and largestUnit ("year", "month", "week", or "day") and returns a Date Duration Record. The return value is the elapsed duration from a first date until a second date, according to the reckoning of the ISO 8601 calendar. No fields larger than largestUnit will be non-zero in the resulting Date Duration Record. It performs the following steps when called:

  1. Assert: IsValidISODate(y1, m1, d1) is true.
  2. Assert: IsValidISODate(y2, m2, d2) is true.
  3. Let sign be -CompareISODate(y1, m1, d1, y2, m2, d2).
  4. If sign = 0, return ! CreateDateDurationRecord(0, 0, 0, 0).
  5. Let years be 0.
  6. If largestUnit is "year", then
    1. Let candidateYears be sign.
    2. Repeat, while ISODateSurpasses(sign, y1 + candidateYears, m1, d1, y2, m2, d2) is false,
      1. Set years to candidateYears.
      2. Set candidateYears to candidateYears + sign.
  7. Let months be 0.
  8. If largestUnit is "year" or largestUnit is "month", then
    1. Let candidateMonths be sign.
    2. Let intermediate be BalanceISOYearMonth(y1 + years, m1 + candidateMonths).
    3. Repeat, while ISODateSurpasses(sign, intermediate.[[Year]], intermediate.[[Month]], d1, y2, m2, d2) is false,
      1. Set months to candidateMonths.
      2. Set candidateMonths to candidateMonths + sign.
      3. Set intermediate to BalanceISOYearMonth(intermediate.[[Year]], intermediate.[[Month]] + sign).
  9. Set intermediate to BalanceISOYearMonth(y1 + years, m1 + months).
  10. Let constrained be ! RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], d1, "constrain").
  11. Let weeks be 0.
  12. If largestUnit is "week", then
    1. Let candidateWeeks be sign.
    2. Set intermediate to BalanceISODate(constrained.[[Year]], constrained.[[Month]], constrained.[[Day]] + 7 × candidateWeeks).
    3. Repeat, while ISODateSurpasses(sign, intermediate.[[Year]], intermediate.[[Month]], intermediate.[[Day]], y2, m2, d2) is false,
      1. Set weeks to candidateWeeks.
      2. Set candidateWeeks to candidateWeeks + sign.
      3. Set intermediate to BalanceISODate(intermediate.[[Year]], intermediate.[[Month]], intermediate.[[Day]] + 7 × sign).
  13. Let days be 0.
  14. Let candidateDays be sign.
  15. Set intermediate to BalanceISODate(constrained.[[Year]], constrained.[[Month]], constrained.[[Day]] + 7 × weeks + candidateDays).
  16. Repeat, while ISODateSurpasses(sign, intermediate.[[Year]], intermediate.[[Month]], intermediate.[[Day]], y2, m2, d2) is false,
    1. Set days to candidateDays.
    2. Set candidateDays to candidateDays + sign.
    3. Set intermediate to BalanceISODate(intermediate.[[Year]], intermediate.[[Month]], intermediate.[[Day]] + sign).
  17. Return ! CreateDateDurationRecord(years, months, weeks, days).

3.5.7 DifferenceDate ( calendarRec, one, two, options )

The abstract operation DifferenceDate takes arguments calendarRec (a Calendar Methods Record), one (a Temporal.PlainDate), two (a Temporal.PlainDate), and options (an Object) and returns either a normal completion containing a Temporal.Duration, or an abrupt completion. It determines the difference between the dates one and two. Usually this is accomplished by calling the dateUntil method of the given calendar as in CalendarDateUntil, but if the dates are equal or no units greater than days are needed in the difference, the computation will not cause an observable method call. It performs the following steps when called:

  1. Assert: one.[[Calendar]] and two.[[Calendar]] have been determined to be equivalent as with CalendarEquals.
  2. Assert: options is an ordinary Object.
  3. Assert: options.[[Prototype]] is null.
  4. Assert: options has a "largestUnit" data property.
  5. If one.[[ISOYear]] = two.[[ISOYear]] and one.[[ISOMonth]] = two.[[ISOMonth]] and one.[[ISODay]] = two.[[ISODay]], then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  6. If ! Get(options, "largestUnit") is "day", then
    1. Let days be DaysUntil(one, two).
    2. Return ! CreateTemporalDuration(0, 0, 0, days, 0, 0, 0, 0, 0, 0).
  7. Return ? CalendarDateUntil(calendarRec, one, two, options).

3.5.8 RegulateISODate ( year, month, day, overflow )

The abstract operation RegulateISODate takes arguments year (an integer), month (an integer), day (an integer), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record, or an abrupt completion. It performs the overflow correction given by overflow on the values year, month, and day, in order to arrive at a valid date in the ISO 8601 calendar, as determined by IsValidISODate. For "reject", values that do not form a valid date cause an exception to be thrown. For "constrain", values that do not form a valid date are clamped to the correct range. It performs the following steps when called:

  1. If overflow is "constrain", then
    1. Set month to the result of clamping month between 1 and 12.
    2. Let daysInMonth be ISODaysInMonth(year, month).
    3. Set day to the result of clamping day between 1 and daysInMonth.
    4. Return CreateISODateRecord(year, month, day).
  2. Else,
    1. Assert: overflow is "reject".
    2. If IsValidISODate(year, month, day) is false, throw a RangeError exception.
    3. Return CreateISODateRecord(year, month, day).

3.5.9 IsValidISODate ( year, month, day )

The abstract operation IsValidISODate takes arguments year (an integer), month (an integer), and day (an integer) and returns a Boolean. The return value is true if its arguments form a valid date in the ISO 8601 calendar, and false otherwise. This includes dates that may fall outside of the allowed range for Temporal. It performs the following steps when called:

  1. If month < 1 or month > 12, then
    1. Return false.
  2. Let daysInMonth be ISODaysInMonth(year, month).
  3. If day < 1 or day > daysInMonth, then
    1. Return false.
  4. Return true.

3.5.10 BalanceISODate ( year, month, day )

The abstract operation BalanceISODate takes arguments year (an integer), month (an integer), and day (an integer) and returns an ISO Date Record. It converts the given year, month, and day into a valid calendar date in the ISO 8601 calendar as given by IsValidISODate, by overflowing out-of-range month or day values into the next-highest unit. This date may be outside the range given by ISODateTimeWithinLimits. It performs the following steps when called:

  1. Let epochDays be ISODateToEpochDays(year, month - 1, day).
  2. Let ms be EpochDaysToEpochMs(epochDays, 0).
  3. Return CreateISODateRecord(EpochTimeToEpochYear(ms), EpochTimeToMonthInYear(ms) + 1, EpochTimeToDate(ms)).

3.5.11 PadISOYear ( y )

  1. Assert: y is an integer.
  2. If y ≥ 0 and y ≤ 9999, then
    1. Return ToZeroPaddedDecimalString(y, 4).
  3. If y > 0, let yearSign be "+"; otherwise, let yearSign be "-".
  4. Let year be ToZeroPaddedDecimalString(abs(y), 6).
  5. Return the string-concatenation of yearSign and year.

3.5.12 TemporalDateToString ( temporalDate, showCalendar )

  1. Assert: Type(temporalDate) is Object.
  2. Assert: temporalDate has an [[InitializedTemporalDate]] internal slot.
  3. Let year be PadISOYear(temporalDate.[[ISOYear]]).
  4. Let month be ToZeroPaddedDecimalString(temporalDate.[[ISOMonth]], 2).
  5. Let day be ToZeroPaddedDecimalString(temporalDate.[[ISODay]], 2).
  6. Let calendar be ? MaybeFormatCalendarAnnotation(temporalDate.[[Calendar]], showCalendar).
  7. Return the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), month, the code unit 0x002D (HYPHEN-MINUS), day, and calendar.

3.5.13 AddISODate ( year, month, day, years, months, weeks, days, overflow )

  1. Assert: year, month, day, years, months, weeks, and days are integers.
  2. Assert: overflow is either "constrain" or "reject".
  3. Let intermediate be ! BalanceISOYearMonth(year + years, month + months).
  4. Set intermediate to ? RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], day, overflow).
  5. Set days to days + 7 × weeks.
  6. Let d be intermediate.[[Day]] + days.
  7. Return BalanceISODate(intermediate.[[Year]], intermediate.[[Month]], d).

3.5.14 AddDate ( calendarRec, plainDate, duration [ , options ] )

The abstract operation AddDate takes arguments calendarRec (a Calendar Methods Record), plainDate (a Temporal.PlainDate), and duration (a Temporal.Duration) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainDate, or an abrupt completion. It adds duration to plainDate. Usually this is accomplished by calling the dateAdd method of the given calendar as in CalendarDateAdd, but if the duration only contains days, the computation will not cause an observable method call. It performs the following steps when called:

  1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-add) is true.
  2. If options is not present, set options to undefined.
  3. If duration.[[Years]] ≠ 0, or duration.[[Months]] ≠ 0, or duration.[[Weeks]] ≠ 0, then
    1. Return ? CalendarDateAdd(calendarRec, plainDate, duration, options).
  4. Let overflow be ? ToTemporalOverflow(options).
  5. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  6. Let days be duration.[[Days]] + BalanceTimeDuration(norm, "day").[[Days]].
  7. Let result be ? AddISODate(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], 0, 0, 0, days, overflow).
  8. Return ! CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendarRec.[[Receiver]]).

3.5.15 CompareISODate ( y1, m1, d1, y2, m2, d2 )

  1. Assert: y1, m1, d1, y2, m2, and d2 are integers.
  2. If y1 > y2, return 1.
  3. If y1 < y2, return -1.
  4. If m1 > m2, return 1.
  5. If m1 < m2, return -1.
  6. If d1 > d2, return 1.
  7. If d1 < d2, return -1.
  8. Return 0.

3.5.16 DifferenceTemporalPlainDate ( operation, temporalDate, other, options )

The abstract operation DifferenceTemporalPlainDate takes arguments operation (since or until), temporalDate (a Temporal.PlainDate), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by temporalDate and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalDate(other).
  3. If ? CalendarEquals(temporalDate.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « », "day", "day").
  6. If temporalDate.[[ISOYear]] = other.[[ISOYear]], and temporalDate.[[ISOMonth]] = other.[[ISOMonth]], and temporalDate.[[ISODay]] = other.[[ISODay]], then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  7. Let calendarRec be ? CreateCalendarMethodsRecord(temporalDate.[[Calendar]], « date-add, date-until »).
  8. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]).
  9. Let result be ? DifferenceDate(calendarRec, temporalDate, other, resolvedOptions).
  10. If settings.[[SmallestUnit]] is "day" and settings.[[RoundingIncrement]] = 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
  11. If roundingGranularityIsNoop is false, then
    1. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], ZeroTimeDuration(), settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], temporalDate, calendarRec).
    2. Let roundResult be roundRecord.[[NormalizedDuration]].
    3. Set result to ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], settings.[[LargestUnit]], settings.[[SmallestUnit]], temporalDate, calendarRec).
  12. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], sign × result.[[Weeks]], sign × result.[[Days]], 0, 0, 0, 0, 0, 0).

4 Temporal.PlainTime Objects

A Temporal.PlainTime object is an Object that contains integers corresponding to a particular hour, minute, second, millisecond, microsecond, and nanosecond.

4.1 The Temporal.PlainTime Constructor

The Temporal.PlainTime constructor:

  • creates and initializes a new Temporal.PlainTime object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.PlainTime behaviour must include a super call to the %Temporal.PlainTime% constructor to create and initialize subclass instances with the necessary internal slots.

4.1.1 Temporal.PlainTime ( [ hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond ] ] ] ] ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If hour is undefined, set hour to 0; else set hour to ? ToIntegerWithTruncation(hour).
  3. If minute is undefined, set minute to 0; else set minute to ? ToIntegerWithTruncation(minute).
  4. If second is undefined, set second to 0; else set second to ? ToIntegerWithTruncation(second).
  5. If millisecond is undefined, set millisecond to 0; else set millisecond to ? ToIntegerWithTruncation(millisecond).
  6. If microsecond is undefined, set microsecond to 0; else set microsecond to ? ToIntegerWithTruncation(microsecond).
  7. If nanosecond is undefined, set nanosecond to 0; else set nanosecond to ? ToIntegerWithTruncation(nanosecond).
  8. Return ? CreateTemporalTime(hour, minute, second, millisecond, microsecond, nanosecond, NewTarget).

4.2 Properties of the Temporal.PlainTime Constructor

The value of the [[Prototype]] internal slot of the Temporal.PlainTime constructor is the intrinsic object %Function.prototype%.

The Temporal.PlainTime constructor has the following properties:

4.2.1 Temporal.PlainTime.prototype

The initial value of Temporal.PlainTime.prototype is %Temporal.PlainTime.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

4.2.2 Temporal.PlainTime.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. Let overflow be ? ToTemporalOverflow(options).
  3. If Type(item) is Object and item has an [[InitializedTemporalTime]] internal slot, then
    1. Return ! CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]]).
  4. Return ? ToTemporalTime(item, overflow).

4.2.3 Temporal.PlainTime.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalTime(one).
  2. Set two to ? ToTemporalTime(two).
  3. Return 𝔽(! CompareTemporalTime(one.[[ISOHour]], one.[[ISOMinute]], one.[[ISOSecond]], one.[[ISOMillisecond]], one.[[ISOMicrosecond]], one.[[ISONanosecond]], two.[[ISOHour]], two.[[ISOMinute]], two.[[ISOSecond]], two.[[ISOMillisecond]], two.[[ISOMicrosecond]], two.[[ISONanosecond]])).

4.3 Properties of the Temporal.PlainTime Prototype Object

The Temporal.PlainTime prototype object

  • is itself an ordinary object.
  • is not a Temporal.PlainTime instance and does not have a [[InitializedTemporalTime]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.

4.3.1 Temporal.PlainTime.prototype.constructor

The initial value of Temporal.PlainTime.prototype.constructor is %Temporal.PlainTime%.

4.3.2 Temporal.PlainTime.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.PlainTime".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

4.3.3 get Temporal.PlainTime.prototype.hour

Temporal.PlainTime.prototype.hour is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISOHour]]).

4.3.4 get Temporal.PlainTime.prototype.minute

Temporal.PlainTime.prototype.minute is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISOMinute]]).

4.3.5 get Temporal.PlainTime.prototype.second

Temporal.PlainTime.prototype.second is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISOSecond]]).

4.3.6 get Temporal.PlainTime.prototype.millisecond

Temporal.PlainTime.prototype.millisecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISOMillisecond]]).

4.3.7 get Temporal.PlainTime.prototype.microsecond

Temporal.PlainTime.prototype.microsecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISOMicrosecond]]).

4.3.8 get Temporal.PlainTime.prototype.nanosecond

Temporal.PlainTime.prototype.nanosecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(temporalTime.[[ISONanosecond]]).

4.3.9 Temporal.PlainTime.prototype.add ( temporalDurationLike )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainTime(add, temporalTime, temporalDurationLike).

4.3.10 Temporal.PlainTime.prototype.subtract ( temporalDurationLike )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainTime(subtract, temporalTime, temporalDurationLike).

4.3.11 Temporal.PlainTime.prototype.with ( temporalTimeLike [ , options ] )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. If ? IsPartialTemporalObject(temporalTimeLike) is false, throw a TypeError exception.
  4. Set options to ? GetOptionsObject(options).
  5. Let overflow be ? ToTemporalOverflow(options).
  6. Let partialTime be ? ToTemporalTimeRecord(temporalTimeLike, partial).
  7. If partialTime.[[Hour]] is not undefined, then
    1. Let hour be partialTime.[[Hour]].
  8. Else,
    1. Let hour be temporalTime.[[ISOHour]].
  9. If partialTime.[[Minute]] is not undefined, then
    1. Let minute be partialTime.[[Minute]].
  10. Else,
    1. Let minute be temporalTime.[[ISOMinute]].
  11. If partialTime.[[Second]] is not undefined, then
    1. Let second be partialTime.[[Second]].
  12. Else,
    1. Let second be temporalTime.[[ISOSecond]].
  13. If partialTime.[[Millisecond]] is not undefined, then
    1. Let millisecond be partialTime.[[Millisecond]].
  14. Else,
    1. Let millisecond be temporalTime.[[ISOMillisecond]].
  15. If partialTime.[[Microsecond]] is not undefined, then
    1. Let microsecond be partialTime.[[Microsecond]].
  16. Else,
    1. Let microsecond be temporalTime.[[ISOMicrosecond]].
  17. If partialTime.[[Nanosecond]] is not undefined, then
    1. Let nanosecond be partialTime.[[Nanosecond]].
  18. Else,
    1. Let nanosecond be temporalTime.[[ISONanosecond]].
  19. Let result be ? RegulateTime(hour, minute, second, millisecond, microsecond, nanosecond, overflow).
  20. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).

4.3.12 Temporal.PlainTime.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ? DifferenceTemporalPlainTime(until, temporalTime, other, options).

4.3.13 Temporal.PlainTime.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ? DifferenceTemporalPlainTime(since, temporalTime, other, options).

4.3.14 Temporal.PlainTime.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. If roundTo is undefined, then
    1. Throw a TypeError exception.
  4. If Type(roundTo) is String, then
    1. Let paramString be roundTo.
    2. Set roundTo to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
  5. Else,
    1. Set roundTo to ? GetOptionsObject(roundTo).
  6. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  7. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
  8. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
  9. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required).
  10. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  11. Assert: maximum is not undefined.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  13. Let result be RoundTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode).
  14. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).

4.3.15 Temporal.PlainTime.prototype.equals ( other )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Set other to ? ToTemporalTime(other).
  4. If temporalTime.[[ISOHour]]other.[[ISOHour]], return false.
  5. If temporalTime.[[ISOMinute]]other.[[ISOMinute]], return false.
  6. If temporalTime.[[ISOSecond]]other.[[ISOSecond]], return false.
  7. If temporalTime.[[ISOMillisecond]]other.[[ISOMillisecond]], return false.
  8. If temporalTime.[[ISOMicrosecond]]other.[[ISOMicrosecond]], return false.
  9. If temporalTime.[[ISONanosecond]]other.[[ISONanosecond]], return false.
  10. Return true.

4.3.16 Temporal.PlainTime.prototype.toPlainDateTime ( temporalDate )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Set temporalDate to ? ToTemporalDate(temporalDate).
  4. Return ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]).

4.3.17 Temporal.PlainTime.prototype.toZonedDateTime ( item )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. If Type(item) is not Object, then
    1. Throw a TypeError exception.
  4. Let temporalDateLike be ? Get(item, "plainDate").
  5. If temporalDateLike is undefined, then
    1. Throw a TypeError exception.
  6. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  7. Let temporalTimeZoneLike be ? Get(item, "timeZone").
  8. If temporalTimeZoneLike is undefined, then
    1. Throw a TypeError exception.
  9. Let timeZone be ? ToTemporalTimeZoneSlotValue(temporalTimeZoneLike).
  10. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]).
  11. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  12. Let instant be ? GetInstantFor(timeZoneRec, temporalDateTime, "compatible").
  13. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, temporalDate.[[Calendar]]).

4.3.18 Temporal.PlainTime.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(temporalTime.[[ISOHour]])).
  5. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(temporalTime.[[ISOMicrosecond]])).
  6. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(temporalTime.[[ISOMillisecond]])).
  7. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(temporalTime.[[ISOMinute]])).
  8. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(temporalTime.[[ISONanosecond]])).
  9. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(temporalTime.[[ISOSecond]])).
  10. Return fields.

4.3.19 Temporal.PlainTime.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Set options to ? GetOptionsObject(options).
  4. NOTE: The following steps read options and perform independent validation in alphabetical order (ToFractionalSecondDigits reads "fractionalSecondDigits" and ToTemporalRoundingMode reads "roundingMode").
  5. Let digits be ? ToFractionalSecondDigits(options).
  6. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  7. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", time, undefined).
  8. If smallestUnit is "hour", throw a RangeError exception.
  9. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  10. Let roundResult be RoundTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  11. Return ! TemporalTimeToString(roundResult.[[Hour]], roundResult.[[Minute]], roundResult.[[Second]], roundResult.[[Millisecond]], roundResult.[[Microsecond]], roundResult.[[Nanosecond]], precision.[[Precision]]).

4.3.20 Temporal.PlainTime.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ! TemporalTimeToString(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], "auto").

4.3.21 Temporal.PlainTime.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Return ! TemporalTimeToString(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], "auto").

4.3.22 Temporal.PlainTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

4.4 Properties of Temporal.PlainTime Instances

Temporal.PlainTime instances are ordinary objects that inherit properties from the %Temporal.PlainTime.prototype% intrinsic object. Temporal.PlainTime instances are initially created with the internal slots described in Table 3.

Table 3: Internal Slots of Temporal.PlainTime Instances
Internal Slot Description
[[InitializedTemporalTime]] The only specified use of this slot is for distinguishing Temporal.PlainTime instances from other objects.
[[ISOHour]] An integer between 0 and 23, inclusive, representing the hour of the day.
[[ISOMinute]] An integer between 0 and 59, inclusive, representing the minute of the hour.
[[ISOSecond]] An integer between 0 and 59, inclusive, representing the second within the minute.
[[ISOMillisecond]] An integer between 0 and 999, inclusive, representing the millisecond within the second.
[[ISOMicrosecond]] An integer between 0 and 999, inclusive, representing the microsecond within the millisecond.
[[ISONanosecond]] An integer between 0 and 999, inclusive, representing the nanosecond within the microsecond.

4.5 Abstract Operations

4.5.1 Time Records

A Time Record is a Record value used to represent a valid clock time, together with a number of overflow days such as might occur in BalanceTime. For any Time Record t, IsValidTime(t.[[Hour]], t.[[Minute]], t.[[Second]], t.[[Millisecond]], t.[[Microsecond]], t.[[Nanosecond]]) must return true.

Time Records have the fields listed in Table 4.

Table 4: Time Record Fields
Field Name Value Meaning
[[Days]] an integer ≥ 0 A number of overflow days.
[[Hour]] an integer in the inclusive range 0 to 23 The number of the hour.
[[Minute]] an integer in the inclusive range 0 to 59 The number of the minute.
[[Second]] an integer in the inclusive range 0 to 59 The number of the second.
[[Millisecond]] an integer in the inclusive range 0 to 999 The number of the millisecond.
[[Microsecond]] an integer in the inclusive range 0 to 999 The number of the microsecond.
[[Nanosecond]] an integer in the inclusive range 0 to 999 The number of the nanosecond.

4.5.2 DifferenceTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 )

The abstract operation DifferenceTime takes arguments h1 (an integer between 0 and 23 inclusive), min1 (an integer between 0 and 59 inclusive), s1 (an integer between 0 and 59 inclusive), ms1 (an integer between 0 and 999 inclusive), mus1 (an integer between 0 and 999 inclusive), ns1 (an integer between 0 and 999 inclusive), h2 (an integer between 0 and 23 inclusive), min2 (an integer between 0 and 59 inclusive), s2 (an integer between 0 and 59 inclusive), ms2 (an integer between 0 and 999 inclusive), mus2 (an integer between 0 and 999 inclusive), and ns2 (an integer between 0 and 999 inclusive). It returns a Normalized Time Duration Record with the elapsed duration from a first wall-clock time, until a second wall-clock time. It performs the following steps when called:

  1. Let hours be h2 - h1.
  2. Let minutes be min2 - min1.
  3. Let seconds be s2 - s1.
  4. Let milliseconds be ms2 - ms1.
  5. Let microseconds be mus2 - mus1.
  6. Let nanoseconds be ns2 - ns1.
  7. Let norm be NormalizeTimeDuration(hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
  8. Assert: NormalizedTimeDurationAbs(norm).[[TotalNanoseconds]] < nsPerDay.
  9. Return norm.

4.5.3 ToTemporalTime ( item [ , overflow ] )

The abstract operation ToTemporalTime returns its argument item if it is already a Temporal.PlainTime instance, converts item to a new Temporal.PlainTime instance if possible, and throws otherwise.

  1. If overflow is not present, set overflow to "constrain".
  2. Assert: overflow is either "constrain" or "reject".
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalTime]] internal slot, then
      1. Return item.
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]).
      2. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(item.[[TimeZone]], « get-offset-nanoseconds-for »).
      3. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, item.[[Calendar]]).
      4. Return ! CreateTemporalTime(plainDateTime.[[ISOHour]], plainDateTime.[[ISOMinute]], plainDateTime.[[ISOSecond]], plainDateTime.[[ISOMillisecond]], plainDateTime.[[ISOMicrosecond]], plainDateTime.[[ISONanosecond]]).
    3. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Return ! CreateTemporalTime(item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]]).
    4. Let result be ? ToTemporalTimeRecord(item).
    5. Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], overflow).
  4. Else,
    1. If item is not a String, throw a TypeError exception.
    2. Let result be ? ParseTemporalTimeString(item).
    3. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
  5. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).

4.5.4 RegulateTime ( hour, minute, second, millisecond, microsecond, nanosecond, overflow )

  1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers.
  2. Assert: overflow is either "constrain" or "reject".
  3. If overflow is "constrain", then
    1. Return ! ConstrainTime(hour, minute, second, millisecond, microsecond, nanosecond).
  4. Else,
    1. Assert: overflow is "reject".
    2. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
    3. Return the Record { [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond  }.

4.5.5 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation IsValidTime takes arguments hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), and nanosecond (an integer) and returns a Boolean. The return value is true if its arguments form a valid time of day, and false otherwise. Leap seconds are not taken into account. It performs the following steps when called:

  1. If hour < 0 or hour > 23, then
    1. Return false.
  2. If minute < 0 or minute > 59, then
    1. Return false.
  3. If second < 0 or second > 59, then
    1. Return false.
  4. If millisecond < 0 or millisecond > 999, then
    1. Return false.
  5. If microsecond < 0 or microsecond > 999, then
    1. Return false.
  6. If nanosecond < 0 or nanosecond > 999, then
    1. Return false.
  7. Return true.

4.5.6 BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation BalanceTime takes arguments hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), and nanosecond (an integer) and returns a Time Record. It performs the following steps when called:

  1. Set microsecond to microsecond + floor(nanosecond / 1000).
  2. Set nanosecond to nanosecond modulo 1000.
  3. Set millisecond to millisecond + floor(microsecond / 1000).
  4. Set microsecond to microsecond modulo 1000.
  5. Set second to second + floor(millisecond / 1000).
  6. Set millisecond to millisecond modulo 1000.
  7. Set minute to minute + floor(second / 60).
  8. Set second to second modulo 60.
  9. Set hour to hour + floor(minute / 60).
  10. Set minute to minute modulo 60.
  11. Let days be floor(hour / 24).
  12. Set hour to hour modulo 24.
  13. Return the Record { [[Days]]: days, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond  }.

4.5.7 ConstrainTime ( hour, minute, second, millisecond, microsecond, nanosecond )

  1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers.
  2. Set hour to the result of clamping hour between 0 and 23.
  3. Set minute to the result of clamping minute between 0 and 59.
  4. Set second to the result of clamping second between 0 and 59.
  5. Set millisecond to the result of clamping millisecond between 0 and 999.
  6. Set microsecond to the result of clamping microsecond between 0 and 999.
  7. Set nanosecond to the result of clamping nanosecond between 0 and 999.
  8. Return the Record { [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond  }.

4.5.8 CreateTemporalTime ( hour, minute, second, millisecond, microsecond, nanosecond [ , newTarget ] )

The abstract operation CreateTemporalTime takes arguments hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), and nanosecond (an integer) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainTime, or an abrupt completion. It creates a new Temporal.PlainTime instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.PlainTime%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainTime.prototype%", « [[InitializedTemporalTime]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]] »).
  4. Set object.[[ISOHour]] to hour.
  5. Set object.[[ISOMinute]] to minute.
  6. Set object.[[ISOSecond]] to second.
  7. Set object.[[ISOMillisecond]] to millisecond.
  8. Set object.[[ISOMicrosecond]] to microsecond.
  9. Set object.[[ISONanosecond]] to nanosecond.
  10. Return object.

4.5.9 ToTemporalTimeRecord ( temporalTimeLike [ , completeness ] )

The abstract operation ToTemporalTimeRecord takes argument temporalTimeLike (an Object) and optional argument completeness (partial or complete) and returns either a normal completion containing a TemporalTimeLike Record, or an abrupt completion. It performs the following steps when called:

  1. If completeness is not present, set completeness to complete.
  2. Let partial be ? PrepareTemporalFields(temporalTimeLike, « "hour", "microsecond", "millisecond", "minute", "nanosecond", "second" », partial).
  3. If completeness is complete, then
    1. Let result be a new TemporalTimeLike Record with each field set to 0.
  4. Else,
    1. Let result be a new TemporalTimeLike Record with each field set to undefined.
  5. Let hourDesc be OrdinaryGetOwnProperty(partial, "hour").
  6. If hourDesc is not undefined, then
    1. Assert: hourDesc is a data Property Descriptor.
    2. Set result.[[Hour]] to (hourDesc.[[Value]]).
  7. Let minuteDesc be OrdinaryGetOwnProperty(partial, "minute").
  8. If minuteDesc is not undefined, then
    1. Assert: minuteDesc is a data Property Descriptor.
    2. Set result.[[Minute]] to (minuteDesc.[[Value]]).
  9. Let secondDesc be OrdinaryGetOwnProperty(partial, "second").
  10. If secondDesc is not undefined, then
    1. Assert: secondDesc is a data Property Descriptor.
    2. Set result.[[Second]] to (secondDesc.[[Value]]).
  11. Let millisecondDesc be OrdinaryGetOwnProperty(partial, "millisecond").
  12. If millisecondDesc is not undefined, then
    1. Assert: millisecondDesc is a data Property Descriptor.
    2. Set result.[[Millisecond]] to (millisecondDesc.[[Value]]).
  13. Let microsecondDesc be OrdinaryGetOwnProperty(partial, "microsecond").
  14. If microsecondDesc is not undefined, then
    1. Assert: microsecondDesc is a data Property Descriptor.
    2. Set result.[[Microsecond]] to (microsecondDesc.[[Value]]).
  15. Let nanosecondDesc be OrdinaryGetOwnProperty(partial, "nanosecond").
  16. If nanosecondDesc is not undefined, then
    1. Assert: nanosecondDesc is a data Property Descriptor.
    2. Set result.[[Nanosecond]] to (nanosecondDesc.[[Value]]).
  17. Return result.
Table 5: TemporalTimeLike Record Fields
Field Name Property Name
[[Hour]] "hour"
[[Minute]] "minute"
[[Second]] "second"
[[Millisecond]] "millisecond"
[[Microsecond]] "microsecond"
[[Nanosecond]] "nanosecond"

4.5.10 TemporalTimeToString ( hour, minute, second, millisecond, microsecond, nanosecond, precision )

  1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers.
  2. Let subSecondNanoseconds be millisecond × 106 + microsecond × 103 + nanosecond.
  3. Return FormatTimeString(hour, minute, second, subSecondNanoseconds, precision).

4.5.11 CompareTemporalTime ( h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2 )

  1. Assert: h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, and ns2 are integers.
  2. If h1 > h2, return 1.
  3. If h1 < h2, return -1.
  4. If min1 > min2, return 1.
  5. If min1 < min2, return -1.
  6. If s1 > s2, return 1.
  7. If s1 < s2, return -1.
  8. If ms1 > ms2, return 1.
  9. If ms1 < ms2, return -1.
  10. If mus1 > mus2, return 1.
  11. If mus1 < mus2, return -1.
  12. If ns1 > ns2, return 1.
  13. If ns1 < ns2, return -1.
  14. Return 0.

4.5.12 AddTime ( hour, minute, second, millisecond, microsecond, nanosecond, norm )

The abstract operation AddTime takes arguments hour (an integer in the inclusive range 0 to 23), minute (an integer in the inclusive range 0 to 59), second (an integer in the inclusive range 0 to 59), millisecond (an integer in the inclusive range 0 to 999), microsecond (an integer in the inclusive range 0 to 999), nanosecond (an integer in the inclusive range 0 to 999), and norm (a Normalized Time Duration Record) and returns a Time Record. It performs the following steps when called:

  1. Set second to second + NormalizedTimeDurationSeconds(norm).
  2. Set nanosecond to nanosecond + NormalizedTimeDurationSubseconds(norm).
  3. Return BalanceTime(hour, minute, second, millisecond, microsecond, nanosecond).

4.5.13 RoundTime ( hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode [ , dayLengthNs ] )

The abstract operation RoundTime takes arguments hour (an integer in the inclusive range 0 to 23), minute (an integer in the inclusive range 0 to 59), second (an integer in the inclusive range 0 to 59), millisecond (an integer in the inclusive range 0 to 999), microsecond (an integer in the inclusive range 0 to 999), nanosecond (an integer in the inclusive range 0 to 999), increment (an integer), unit ("day", "hour", "minute", "second", "millisecond", "microsecond", or "nanosecond"), and roundingMode (a String from the Identifier column of Table 19) and optional argument dayLengthNs (an integer) and returns a Time Record. It rounds a time to the given increment, optionally adjusting for a non-24-hour day. It performs the following steps when called:

  1. Let fractionalSecond be nanosecond × 10-9 + microsecond × 10-6 + millisecond × 10-3 + second.
  2. If unit is "day", then
    1. If dayLengthNs is not present, set dayLengthNs to nsPerDay.
    2. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + millisecond) × 1000 + microsecond) × 1000 + nanosecond) / dayLengthNs.
  3. Else if unit is "hour", then
    1. Let quantity be (fractionalSecond / 60 + minute) / 60 + hour.
  4. Else if unit is "minute", then
    1. Let quantity be fractionalSecond / 60 + minute.
  5. Else if unit is "second", then
    1. Let quantity be fractionalSecond.
  6. Else if unit is "millisecond", then
    1. Let quantity be nanosecond × 10-6 + microsecond × 10-3 + millisecond.
  7. Else if unit is "microsecond", then
    1. Let quantity be nanosecond × 10-3 + microsecond.
  8. Else,
    1. Assert: unit is "nanosecond".
    2. Let quantity be nanosecond.
  9. Let result be RoundNumberToIncrement(quantity, increment, roundingMode).
  10. If unit is "day", then
    1. Return the Record { [[Days]]: result, [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0  }.
  11. If unit is "hour", then
    1. Return BalanceTime(result, 0, 0, 0, 0, 0).
  12. If unit is "minute", then
    1. Return BalanceTime(hour, result, 0, 0, 0, 0).
  13. If unit is "second", then
    1. Return BalanceTime(hour, minute, result, 0, 0, 0).
  14. If unit is "millisecond", then
    1. Return BalanceTime(hour, minute, second, result, 0, 0).
  15. If unit is "microsecond", then
    1. Return BalanceTime(hour, minute, second, millisecond, result, 0).
  16. Assert: unit is "nanosecond".
  17. Return BalanceTime(hour, minute, second, millisecond, microsecond, result).

4.5.14 DifferenceTemporalPlainTime ( operation, temporalTime, other, options )

The abstract operation DifferenceTemporalPlainTime takes arguments operation (since or until), temporalTime (a Temporal.PlainTime), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by temporalTime and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalTime(other).
  3. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », "nanosecond", "hour").
  5. Let norm be ! DifferenceTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]]).
  6. If settings.[[SmallestUnit]] is not "nanosecond" or settings.[[RoundingIncrement]] ≠ 1, then
    1. Let roundRecord be ! RoundDuration(0, 0, 0, 0, norm, settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
    2. Set norm to roundRecord.[[NormalizedDuration]].[[NormalizedTime]].
  7. Let result be BalanceTimeDuration(norm, settings.[[LargestUnit]]).
  8. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]).

4.5.15 AddDurationToOrSubtractDurationFromPlainTime ( operation, temporalTime, temporalDurationLike )

The abstract operation AddDurationToOrSubtractDurationFromPlainTime takes arguments operation (add or subtract), temporalTime (a Temporal.PlainTime), and temporalDurationLike (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainTime or an abrupt completion. It adds/subtracts temporalDurationLike to/from temporalTime, returning a point in time that is in the future/past relative to temporalTime. It performs the following steps when called:

  1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
  2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
  3. Let norm be NormalizeTimeDuration(sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
  4. Let result be AddTime(temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], norm).
  5. Return ! CreateTemporalTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).

5 Temporal.PlainDateTime Objects

A Temporal.PlainDateTime object is an Object that contains integers corresponding to a particular year, month, day, hour, minute, second, millisecond, microsecond, and nanosecond.

5.1 The Temporal.PlainDateTime Constructor

The Temporal.PlainDateTime constructor:

  • creates and initializes a new Temporal.PlainDateTime object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.PlainDateTime behaviour must include a super call to the %Temporal.PlainDateTime% constructor to create and initialize subclass instances with the necessary internal slots.

5.1.1 Temporal.PlainDateTime ( isoYear, isoMonth, isoDay [ , hour [ , minute [ , second [ , millisecond [ , microsecond [ , nanosecond [ , calendarLike ] ] ] ] ] ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. Set isoYear to ? ToIntegerWithTruncation(isoYear).
  3. Set isoMonth to ? ToIntegerWithTruncation(isoMonth).
  4. Set isoDay to ? ToIntegerWithTruncation(isoDay).
  5. If hour is undefined, set hour to 0; else set hour to ? ToIntegerWithTruncation(hour).
  6. If minute is undefined, set minute to 0; else set minute to ? ToIntegerWithTruncation(minute).
  7. If second is undefined, set second to 0; else set second to ? ToIntegerWithTruncation(second).
  8. If millisecond is undefined, set millisecond to 0; else set millisecond to ? ToIntegerWithTruncation(millisecond).
  9. If microsecond is undefined, set microsecond to 0; else set microsecond to ? ToIntegerWithTruncation(microsecond).
  10. If nanosecond is undefined, set nanosecond to 0; else set nanosecond to ? ToIntegerWithTruncation(nanosecond).
  11. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  12. Return ? CreateTemporalDateTime(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, NewTarget).

5.2 Properties of the Temporal.PlainDateTime Constructor

The value of the [[Prototype]] internal slot of the Temporal.PlainDateTime constructor is the intrinsic object %Function.prototype%.

The Temporal.PlainDateTime constructor has the following properties:

5.2.1 Temporal.PlainDateTime.prototype

The initial value of Temporal.PlainDateTime.prototype is %Temporal.PlainDateTime.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

5.2.2 Temporal.PlainDateTime.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. If Type(item) is Object and item has an [[InitializedTemporalDateTime]] internal slot, then
    1. Perform ? ToTemporalOverflow(options).
    2. Return ! CreateTemporalDateTime(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], item.[[ISOHour]], item.[[ISOMinute]], item.[[ISOSecond]], item.[[ISOMillisecond]], item.[[ISOMicrosecond]], item.[[ISONanosecond]], item.[[Calendar]]).
  3. Return ? ToTemporalDateTime(item, options).

5.2.3 Temporal.PlainDateTime.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalDateTime(one).
  2. Set two to ? ToTemporalDateTime(two).
  3. Return 𝔽(! CompareISODateTime(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], one.[[ISOHour]], one.[[ISOMinute]], one.[[ISOSecond]], one.[[ISOMillisecond]], one.[[ISOMicrosecond]], one.[[ISONanosecond]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], two.[[ISOHour]], two.[[ISOMinute]], two.[[ISOSecond]], two.[[ISOMillisecond]], two.[[ISOMicrosecond]], two.[[ISONanosecond]])).

5.3 Properties of the Temporal.PlainDateTime Prototype Object

The Temporal.PlainDateTime prototype object

  • is the intrinsic object %Temporal.PlainDateTime.prototype%.
  • is itself an ordinary object.
  • is not a Temporal.PlainDateTime instance and does not have a [[InitializedTemporalDateTime]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

5.3.1 Temporal.PlainDateTime.prototype.constructor

The initial value of Temporal.PlainDateTime.prototype.constructor is %Temporal.PlainDateTime%.

5.3.2 Temporal.PlainDateTime.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.PlainDateTime".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

5.3.3 get Temporal.PlainDateTime.prototype.calendarId

Temporal.PlainDateTime.prototype.calendarId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? ToTemporalCalendarIdentifier(dateTime.[[Calendar]]).

5.3.4 get Temporal.PlainDateTime.prototype.year

Temporal.PlainDateTime.prototype.year is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarYear(calendar, dateTime)).

5.3.5 get Temporal.PlainDateTime.prototype.month

Temporal.PlainDateTime.prototype.month is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarMonth(calendar, dateTime)).

5.3.6 get Temporal.PlainDateTime.prototype.monthCode

Temporal.PlainDateTime.prototype.monthCode is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return ? CalendarMonthCode(calendar, dateTime).

5.3.7 get Temporal.PlainDateTime.prototype.day

Temporal.PlainDateTime.prototype.day is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « day »).
  4. Return 𝔽(? CalendarDay(calendarRec, dateTime)).

5.3.8 get Temporal.PlainDateTime.prototype.hour

Temporal.PlainDateTime.prototype.hour is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISOHour]]).

5.3.9 get Temporal.PlainDateTime.prototype.minute

Temporal.PlainDateTime.prototype.minute is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISOMinute]]).

5.3.10 get Temporal.PlainDateTime.prototype.second

Temporal.PlainDateTime.prototype.second is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISOSecond]]).

5.3.11 get Temporal.PlainDateTime.prototype.millisecond

Temporal.PlainDateTime.prototype.millisecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISOMillisecond]]).

5.3.12 get Temporal.PlainDateTime.prototype.microsecond

Temporal.PlainDateTime.prototype.microsecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISOMicrosecond]]).

5.3.13 get Temporal.PlainDateTime.prototype.nanosecond

Temporal.PlainDateTime.prototype.nanosecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(dateTime.[[ISONanosecond]]).

5.3.14 get Temporal.PlainDateTime.prototype.dayOfWeek

Temporal.PlainDateTime.prototype.dayOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarDayOfWeek(calendar, dateTime)).

5.3.15 get Temporal.PlainDateTime.prototype.dayOfYear

Temporal.PlainDateTime.prototype.dayOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarDayOfYear(calendar, dateTime)).

5.3.16 get Temporal.PlainDateTime.prototype.weekOfYear

Temporal.PlainDateTime.prototype.weekOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarWeekOfYear(calendar, dateTime)).

5.3.17 get Temporal.PlainDateTime.prototype.yearOfWeek

Temporal.PlainDateTime.prototype.yearOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarYearOfWeek(calendar, dateTime)).

5.3.18 get Temporal.PlainDateTime.prototype.daysInWeek

Temporal.PlainDateTime.prototype.daysInWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInWeek(calendar, dateTime)).

5.3.19 get Temporal.PlainDateTime.prototype.daysInMonth

Temporal.PlainDateTime.prototype.daysInMonth is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInMonth(calendar, dateTime)).

5.3.20 get Temporal.PlainDateTime.prototype.daysInYear

Temporal.PlainDateTime.prototype.daysInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInYear(calendar, dateTime)).

5.3.21 get Temporal.PlainDateTime.prototype.monthsInYear

Temporal.PlainDateTime.prototype.monthsInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return 𝔽(? CalendarMonthsInYear(calendar, dateTime)).

5.3.22 get Temporal.PlainDateTime.prototype.inLeapYear

Temporal.PlainDateTime.prototype.inLeapYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be dateTime.[[Calendar]].
  4. Return ? CalendarInLeapYear(calendar, dateTime).

5.3.23 Temporal.PlainDateTime.prototype.with ( temporalDateTimeLike [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. If ? IsPartialTemporalObject(temporalDateTimeLike) is false, throw a TypeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « date-from-fields, fields, merge-fields »).
  6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
  7. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»).
  8. Perform ! CreateDataPropertyOrThrow(fields, "hour", dateTime.[[ISOHour]]).
  9. Perform ! CreateDataPropertyOrThrow(fields, "minute", dateTime.[[ISOMinute]]).
  10. Perform ! CreateDataPropertyOrThrow(fields, "second", dateTime.[[ISOSecond]]).
  11. Perform ! CreateDataPropertyOrThrow(fields, "millisecond", dateTime.[[ISOMillisecond]]).
  12. Perform ! CreateDataPropertyOrThrow(fields, "microsecond", dateTime.[[ISOMicrosecond]]).
  13. Perform ! CreateDataPropertyOrThrow(fields, "nanosecond", dateTime.[[ISONanosecond]]).
  14. Append "hour", "microsecond", "millisecond", "minute", "nanosecond", and "second" to fieldNames.
  15. Let partialDateTime be ? PrepareTemporalFields(temporalDateTimeLike, fieldNames, partial).
  16. Set fields to ? CalendarMergeFields(calendarRec, fields, partialDateTime).
  17. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»).
  18. Let result be ? InterpretTemporalDateTimeFields(calendarRec, fields, resolvedOptions).
  19. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
  20. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
  21. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendarRec.[[Receiver]]).

5.3.24 Temporal.PlainDateTime.prototype.withPlainTime ( [ plainTimeLike ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. If plainTimeLike is undefined, then
    1. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, dateTime.[[Calendar]]).
  4. Let plainTime be ? ToTemporalTime(plainTimeLike).
  5. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], plainTime.[[ISOHour]], plainTime.[[ISOMinute]], plainTime.[[ISOSecond]], plainTime.[[ISOMillisecond]], plainTime.[[ISOMicrosecond]], plainTime.[[ISONanosecond]], dateTime.[[Calendar]]).

5.3.25 Temporal.PlainDateTime.prototype.withPlainDate ( plainDateLike )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let plainDate be ? ToTemporalDate(plainDateLike).
  4. Let calendar be ? ConsolidateCalendars(dateTime.[[Calendar]], plainDate.[[Calendar]]).
  5. Return ? CreateTemporalDateTime(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendar).

5.3.26 Temporal.PlainDateTime.prototype.withCalendar ( calendarLike )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  4. Return ? CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendar).

5.3.27 Temporal.PlainDateTime.prototype.add ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(add, dateTime, temporalDurationLike, options).

5.3.28 Temporal.PlainDateTime.prototype.subtract ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainDateTime(subtract, dateTime, temporalDurationLike, options).

5.3.29 Temporal.PlainDateTime.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? DifferenceTemporalPlainDateTime(until, dateTime, other, options).

5.3.30 Temporal.PlainDateTime.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? DifferenceTemporalPlainDateTime(since, dateTime, other, options).

5.3.31 Temporal.PlainDateTime.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. If roundTo is undefined, then
    1. Throw a TypeError exception.
  4. If Type(roundTo) is String, then
    1. Let paramString be roundTo.
    2. Set roundTo to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
  5. Else,
    1. Set roundTo to ? GetOptionsObject(roundTo).
  6. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  7. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
  8. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
  9. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required, « "day" »).
  10. If smallestUnit is "day", then
    1. Let maximum be 1.
    2. Let inclusive be true.
  11. Else,
    1. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
    2. Assert: maximum is not undefined.
    3. Let inclusive be false.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, inclusive).
  13. If smallestUnit is "nanosecond" and roundingIncrement is 1, then
    1. Return ! CreateTemporalDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]]).
  14. Let result be RoundISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode).
  15. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]).

5.3.32 Temporal.PlainDateTime.prototype.equals ( other )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Set other to ? ToTemporalDateTime(other).
  4. Let result be ! CompareISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]]).
  5. If result is not 0, return false.
  6. Return ? CalendarEquals(dateTime.[[Calendar]], other.[[Calendar]]).

5.3.33 Temporal.PlainDateTime.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Set options to ? GetOptionsObject(options).
  4. NOTE: The following steps read options and perform independent validation in alphabetical order (ToCalendarNameOption reads "calendarName", ToFractionalSecondDigits reads "fractionalSecondDigits", and ToTemporalRoundingMode reads "roundingMode").
  5. Let showCalendar be ? ToCalendarNameOption(options).
  6. Let digits be ? ToFractionalSecondDigits(options).
  7. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  8. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", time, undefined).
  9. If smallestUnit is "hour", throw a RangeError exception.
  10. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  11. Let result be RoundISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  12. Return ? TemporalDateTimeToString(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]], precision.[[Precision]], showCalendar).

5.3.34 Temporal.PlainDateTime.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], "auto", "auto").

5.3.35 Temporal.PlainDateTime.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ? TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], "auto", "auto").

5.3.36 Temporal.PlainDateTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

5.3.37 Temporal.PlainDateTime.prototype.toZonedDateTime ( temporalTimeZoneLike [ , options ] )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let timeZone be ? ToTemporalTimeZoneSlotValue(temporalTimeZoneLike).
  4. Set options to ? GetOptionsObject(options).
  5. Let disambiguation be ? ToTemporalDisambiguation(options).
  6. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  7. Let instant be ? GetInstantFor(timeZoneRec, dateTime, disambiguation).
  8. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, dateTime.[[Calendar]]).

5.3.38 Temporal.PlainDateTime.prototype.toPlainDate ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]).

5.3.39 Temporal.PlainDateTime.prototype.toPlainYearMonth ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « fields, year-month-from-fields »).
  4. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  5. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»).
  6. Return ? CalendarYearMonthFromFields(calendarRec, fields).
  7. NOTE: The call to CalendarYearMonthFromFields is necessary in order to create a PlainYearMonth object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

5.3.40 Temporal.PlainDateTime.prototype.toPlainMonthDay ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « fields, month-day-from-fields »).
  4. Let fieldNames be ? CalendarFields(calendarRec, « "day", "monthCode" »).
  5. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, «»).
  6. Return ? CalendarMonthDayFromFields(calendarRec, fields).
  7. NOTE: The call to CalendarMonthDayFromFields is necessary in order to create a PlainMonthDay object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

5.3.41 Temporal.PlainDateTime.prototype.toPlainTime ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ! CreateTemporalTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).

5.3.42 Temporal.PlainDateTime.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", dateTime.[[Calendar]]).
  5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(dateTime.[[ISODay]])).
  6. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(dateTime.[[ISOHour]])).
  7. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(dateTime.[[ISOMicrosecond]])).
  8. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(dateTime.[[ISOMillisecond]])).
  9. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(dateTime.[[ISOMinute]])).
  10. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(dateTime.[[ISOMonth]])).
  11. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(dateTime.[[ISONanosecond]])).
  12. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(dateTime.[[ISOSecond]])).
  13. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(dateTime.[[ISOYear]])).
  14. Return fields.

5.3.43 Temporal.PlainDateTime.prototype.getCalendar ( )

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Return ToTemporalCalendarObject(dateTime).

5.4 Properties of Temporal.PlainDateTime Instances

Temporal.PlainDateTime instances are ordinary objects that inherit properties from the %Temporal.PlainDateTime.prototype% intrinsic object. Temporal.PlainDateTime instances are initially created with the internal slots described in Table 6.

Table 6: Internal Slots of Temporal.PlainDateTime Instances
Internal Slot Description
[[InitializedTemporalDateTime]] The only specified use of this slot is for distinguishing Temporal.PlainDateTime instances from other objects.
[[ISOYear]] An integer representing the year in the ISO 8601 calendar.
[[ISOMonth]] An integer between 1 and 12, inclusive, representing the month of the year in the ISO 8601 calendar.
[[ISODay]] An integer between 1 and ISODaysInMonth([[ISOYear]], [[ISOMonth]]), inclusive, representing the day of the month in the ISO 8601 calendar.
[[ISOHour]] An integer between 0 and 23, inclusive, representing the hour of the day.
[[ISOMinute]] An integer between 0 and 59, inclusive, representing the minute of the hour.
[[ISOSecond]] An integer between 0 and 59, inclusive, representing the second within the minute.
[[ISOMillisecond]] An integer between 0 and 999, inclusive, representing the millisecond within the second.
[[ISOMicrosecond]] An integer between 0 and 999, inclusive, representing the microsecond within the millisecond.
[[ISONanosecond]] An integer between 0 and 999, inclusive, representing the nanosecond within the microsecond.
[[Calendar]] A String or Object representing the calendar.

5.5 Abstract Operations

5.5.1 ISO Date-Time Records

An ISO Date-Time Record is a Record value used to represent a valid calendar date in the ISO 8601 calendar together with a clock time. For any ISO Date-Time Record r, IsValidISODate(r.[[Year]], r.[[Month]], r.[[Day]]) must return true, and IsValidTime(r.[[Hour]], r.[[Minute]], r.[[Second]], r.[[Millisecond]], r.[[Microsecond]], r.[[Nanosecond]]) must return true. It is not necessary for ISODateTimeWithinLimits(r.[[Year]], r.[[Month]], r.[[Day]], r.[[Hour]], r.[[Minute]], r.[[Second]], r.[[Millisecond]], r.[[Microsecond]], r.[[Nanosecond]]) to return true.

ISO Date-Time Records have the fields listed in Table 7.

Table 7: ISO Date-Time Record Fields
Field Name Value Meaning
[[Year]] an integer The year in the ISO 8601 calendar.
[[Month]] an integer between 1 and 12, inclusive The number of the month in the ISO 8601 calendar.
[[Day]] an integer between 1 and 31, inclusive The number of the day of the month in the ISO 8601 calendar.
[[Hour]] an integer in the inclusive range 0 to 23 The number of the hour.
[[Minute]] an integer in the inclusive range 0 to 59 The number of the minute.
[[Second]] an integer in the inclusive range 0 to 59 The number of the second.
[[Millisecond]] an integer in the inclusive range 0 to 999 The number of the millisecond.
[[Microsecond]] an integer in the inclusive range 0 to 999 The number of the microsecond.
[[Nanosecond]] an integer in the inclusive range 0 to 999 The number of the nanosecond.

5.5.2 ISODateTimeWithinLimits ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation ISODateTimeWithinLimits takes arguments year (an integer), month (an integer between 1 and 12 inclusive), day (an integer between 1 and 31 inclusive), hour (an integer between 0 and 23 inclusive), minute (an integer between 0 and 59 inclusive), second (an integer between 0 and 59 inclusive), millisecond (an integer between 0 and 999 inclusive), microsecond (an integer between 0 and 999 inclusive), and nanosecond (an integer between 0 and 999 inclusive) and returns a Boolean. The return value is true if the combination of a date in the ISO 8601 calendar with a wall-clock time, given by the arguments, is within the representable range of Temporal.PlainDateTime, and false otherwise.

Note

Temporal.PlainDateTime objects can represent points in time within 24 hours (8.64 × 1013 nanoseconds) of the Temporal.Instant boundaries. This ensures that a Temporal.Instant object can be converted into a Temporal.PlainDateTime object using any time zone.

It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. If abs(ISODateToEpochDays(year, month - 1, day)) > 108 + 1, return false.
  3. Let ns be (GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)).
  4. If nsnsMinInstant - nsPerDay, then
    1. Return false.
  5. If nsnsMaxInstant + nsPerDay, then
    1. Return false.
  6. Return true.

5.5.3 InterpretTemporalDateTimeFields ( calendarRec, fields, options )

The abstract operation InterpretTemporalDateTimeFields takes arguments calendarRec (a Calendar Methods Record), fields (an Object), and options (an Object) and returns either a normal completion containing an ISO Date-Time Record, or a throw completion. It interprets the date/time fields in the object fields using the given calendar, and returns a Record with the fields according to the ISO 8601 calendar. It performs the following steps when called:

  1. Assert: options is an ordinary extensible Object that is not directly observable from ECMAScript code and for which the value of the [[Prototype]] internal slot is null and every property is a configurable data property.
  2. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-from-fields) is true.
  3. Let timeResult be ? ToTemporalTimeRecord(fields).
  4. Let overflow be ? ToTemporalOverflow(options).
  5. NOTE: The following step is guaranteed to complete normally despite the "overflow" property existing, because of the assertion in the first step.
  6. Perform ! CreateDataPropertyOrThrow(options, "overflow", overflow).
  7. Let temporalDate be ? CalendarDateFromFields(calendarRec, fields, options).
  8. Set timeResult to ? RegulateTime(timeResult.[[Hour]], timeResult.[[Minute]], timeResult.[[Second]], timeResult.[[Millisecond]], timeResult.[[Microsecond]], timeResult.[[Nanosecond]], overflow).
  9. Return the Record { [[Year]]: temporalDate.[[ISOYear]], [[Month]]: temporalDate.[[ISOMonth]], [[Day]]: temporalDate.[[ISODay]], [[Hour]]: timeResult.[[Hour]], [[Minute]]: timeResult.[[Minute]], [[Second]]: timeResult.[[Second]], [[Millisecond]]: timeResult.[[Millisecond]], [[Microsecond]]: timeResult.[[Microsecond]], [[Nanosecond]]: timeResult.[[Nanosecond]]  }.

5.5.4 ToTemporalDateTime ( item [ , options ] )

The abstract operation ToTemporalDateTime takes argument item (an ECMAScript language value) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainDateTime, or a throw completion. It returns its argument item if it is already a Temporal.PlainDateTime instance, converts item to a new Temporal.PlainDateTime instance if possible, and throws otherwise. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let resolvedOptions be ? SnapshotOwnProperties(! GetOptionsObject(options), null).
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Return item.
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Perform ? ToTemporalOverflow(resolvedOptions).
      2. Let instant be ! CreateTemporalInstant(item.[[Nanoseconds]]).
      3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(item.[[TimeZone]], « get-offset-nanoseconds-for »).
      4. Return ? GetPlainDateTimeFor(timeZoneRec, instant, item.[[Calendar]]).
    3. If item has an [[InitializedTemporalDate]] internal slot, then
      1. Perform ? ToTemporalOverflow(resolvedOptions).
      2. Return ? CreateTemporalDateTime(item.[[ISOYear]], item.[[ISOMonth]], item.[[ISODay]], 0, 0, 0, 0, 0, 0, item.[[Calendar]]).
    4. Let calendar be ? GetTemporalCalendarSlotValueWithISODefault(item).
    5. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « date-from-fields, fields »).
    6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
    7. Append "hour", "microsecond", "millisecond", "minute", "nanosecond", and "second" to fieldNames.
    8. Let fields be ? PrepareTemporalFields(item, fieldNames, «»).
    9. Let result be ? InterpretTemporalDateTimeFields(calendarRec, fields, resolvedOptions).
  4. Else,
    1. If item is not a String, throw a TypeError exception.
    2. Let result be ? ParseTemporalDateTimeString(item).
    3. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
    4. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
    5. Let calendar be result.[[Calendar]].
    6. If calendar is undefined, set calendar to "iso8601".
    7. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
    8. Set calendar to the ASCII-lowercase of calendar.
    9. Perform ? ToTemporalOverflow(resolvedOptions).
  5. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendar).

5.5.5 BalanceISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

The abstract operation BalanceISODateTime takes arguments year (an integer), month (an integer), day (an integer), hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), and nanosecond (an integer) and returns an ISO Date-Time Record. It performs the following steps when called:

  1. Let balancedTime be BalanceTime(hour, minute, second, millisecond, microsecond, nanosecond).
  2. Let balancedDate be BalanceISODate(year, month, day + balancedTime.[[Days]]).
  3. Return the Record { [[Year]]: balancedDate.[[Year]], [[Month]]: balancedDate.[[Month]], [[Day]]: balancedDate.[[Day]], [[Hour]]: balancedTime.[[Hour]], [[Minute]]: balancedTime.[[Minute]], [[Second]]: balancedTime.[[Second]], [[Millisecond]]: balancedTime.[[Millisecond]], [[Microsecond]]: balancedTime.[[Microsecond]], [[Nanosecond]]: balancedTime.[[Nanosecond]]  }.

5.5.6 CreateTemporalDateTime ( isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar [ , newTarget ] )

The abstract operation CreateTemporalDateTime takes arguments isoYear (an integer), isoMonth (an integer), isoDay (an integer), hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), nanosecond (an integer), and calendar (a String or Object) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainDateTime instance, or an abrupt completion. It creates a Temporal.PlainDateTime instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If IsValidISODate(isoYear, isoMonth, isoDay) is false, throw a RangeError exception.
  2. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
  3. If ISODateTimeWithinLimits(isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond) is false, then
    1. Throw a RangeError exception.
  4. If newTarget is not present, set newTarget to %Temporal.PlainDateTime%.
  5. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDateTime.prototype%", « [[InitializedTemporalDateTime]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] »).
  6. Set object.[[ISOYear]] to isoYear.
  7. Set object.[[ISOMonth]] to isoMonth.
  8. Set object.[[ISODay]] to isoDay.
  9. Set object.[[ISOHour]] to hour.
  10. Set object.[[ISOMinute]] to minute.
  11. Set object.[[ISOSecond]] to second.
  12. Set object.[[ISOMillisecond]] to millisecond.
  13. Set object.[[ISOMicrosecond]] to microsecond.
  14. Set object.[[ISONanosecond]] to nanosecond.
  15. Set object.[[Calendar]] to calendar.
  16. Return object.

5.5.7 TemporalDateTimeToString ( isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, nanosecond, calendar, precision, showCalendar )

  1. Assert: isoYear, isoMonth, isoDay, hour, minute, second, millisecond, microsecond, and nanosecond are integers.
  2. Let yearString be PadISOYear(isoYear).
  3. Let monthString be ToZeroPaddedDecimalString(isoMonth, 2).
  4. Let dayString be ToZeroPaddedDecimalString(isoDay, 2).
  5. Let subSecondNanoseconds be millisecond × 106 + microsecond × 103 + nanosecond.
  6. Let timeString be FormatTimeString(hour, minute, second, subSecondNanoseconds, precision).
  7. Let calendarString be ? MaybeFormatCalendarAnnotation(calendar, showCalendar).
  8. Return the string-concatenation of yearString, the code unit 0x002D (HYPHEN-MINUS), monthString, the code unit 0x002D (HYPHEN-MINUS), dayString, 0x0054 (LATIN CAPITAL LETTER T), timeString, and calendarString.

5.5.8 CompareISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2 )

  1. Assert: y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, and ns2 are integers.
  2. Let dateResult be ! CompareISODate(y1, mon1, d1, y2, mon2, d2).
  3. If dateResult is not 0, then
    1. Return dateResult.
  4. Return ! CompareTemporalTime(h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2).

5.5.9 AddDateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendarRec, years, months, weeks, days, norm, options )

The abstract operation AddDateTime takes arguments year (an integer), month (an integer in the inclusive interval from 1 to 12), day (an integer in the inclusive interval from 1 to 31), hour (an integer in the inclusive interval from 0 to 23), minute (an integer in the inclusive interval from 0 to 59), second (an integer in the inclusive interval from 0 to 59), millisecond (an integer in the inclusive interval from 0 to 999), microsecond (an integer in the inclusive interval from 0 to 999), nanosecond (an integer in the inclusive interval from 0 to 999), calendarRec (a Calendar Methods Record), years (an integer), months (an integer), weeks (an integer), days (an integer), norm (a Normalized Time Duration Record), and options (an Object or undefined) and returns either a normal completion containing an ISO Date-Time Record, or a throw completion. It adds a duration to a combined date and time, according to the reckoning of the given calendar, and returns the result as a Record. It performs the following steps when called:

  1. Assert: ISODateTimeWithinLimits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond) is true.
  2. Let timeResult be AddTime(hour, minute, second, millisecond, microsecond, nanosecond, norm).
  3. Let datePart be ! CreateTemporalDate(year, month, day, calendarRec.[[Receiver]]).
  4. Let dateDuration be ? CreateTemporalDuration(years, months, weeks, days + timeResult.[[Days]], 0, 0, 0, 0, 0, 0).
  5. Let addedDate be ? AddDate(calendarRec, datePart, dateDuration, options).
  6. Return the Record { [[Year]]: addedDate.[[ISOYear]], [[Month]]: addedDate.[[ISOMonth]], [[Day]]: addedDate.[[ISODay]], [[Hour]]: timeResult.[[Hour]], [[Minute]]: timeResult.[[Minute]], [[Second]]: timeResult.[[Second]], [[Millisecond]]: timeResult.[[Millisecond]], [[Microsecond]]: timeResult.[[Microsecond]], [[Nanosecond]]: timeResult.[[Nanosecond]]  }.

5.5.10 RoundISODateTime ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode [ , dayLength ] )

The abstract operation RoundISODateTime takes arguments year (an integer), month (an integer in the inclusive interval from 1 to 12), day (an integer in the inclusive interval from 1 to 31), hour (an integer in the inclusive interval from 0 to 23), minute (an integer in the inclusive interval from 0 to 59), second (an integer in the inclusive interval from 0 to 59), millisecond (an integer in the inclusive interval from 0 to 999), microsecond (an integer in the inclusive interval from 0 to 999), nanosecond (an integer in the inclusive interval from 0 to 999), increment (an integer), unit ("day", "hour", "minute", "second", "millisecond", "microsecond", or "nanosecond"), and roundingMode (a String from the Identifier column of Table 19) and optional argument dayLength (an integer) and returns an ISO Date-Time Record. It rounds the time part of a combined date and time, carrying over any excess into the date part. It performs the following steps when called:

  1. Assert: ISODateTimeWithinLimits(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond) is true.
  2. If dayLength is not present, set dayLength to nsPerDay.
  3. Let roundedTime be RoundTime(hour, minute, second, millisecond, microsecond, nanosecond, increment, unit, roundingMode, dayLength).
  4. Let balanceResult be BalanceISODate(year, month, day + roundedTime.[[Days]]).
  5. Return the Record { [[Year]]: balanceResult.[[Year]], [[Month]]: balanceResult.[[Month]], [[Day]]: balanceResult.[[Day]], [[Hour]]: roundedTime.[[Hour]], [[Minute]]: roundedTime.[[Minute]], [[Second]]: roundedTime.[[Second]], [[Millisecond]]: roundedTime.[[Millisecond]], [[Microsecond]]: roundedTime.[[Microsecond]], [[Nanosecond]]: roundedTime.[[Nanosecond]]  }.

5.5.11 DifferenceISODateTime ( y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2, calendarRec, largestUnit, options )

The abstract operation DifferenceISODateTime takes arguments y1 (an integer), mon1 (an integer between 1 and 12 inclusive), d1 (an integer between 1 and 31 inclusive), h1 (an integer between 0 and 23 inclusive), min1 (an integer between 0 and 59 inclusive), s1 (an integer between 0 and 59 inclusive), ms1 (an integer between 0 and 999 inclusive), mus1 (an integer between 0 and 999 inclusive), ns1 (an integer between 0 and 999 inclusive), y2 (an integer), mon2 (an integer between 1 and 12 inclusive), d2 (an integer between 1 and 31 inclusive), h2 (an integer between 0 and 23 inclusive), min2 (an integer between 0 and 59 inclusive), s2 (an integer between 0 and 59 inclusive), ms2 (an integer between 0 and 999 inclusive), mus2 (an integer between 0 and 999 inclusive), ns2 (an integer between 0 and 999 inclusive), calendarRec (a Calendar Methods Record), largestUnit (a String), and options (an ordinary Object for which the value of the [[Prototype]] internal slot is null and every property is a data property) and returns either a normal completion containing a Normalized Duration Record, or a throw completion. The returned Duration Record contains the elapsed duration from a first date and time, until a second date and time, according to the reckoning of the given calendar. The given date and time units are all in the ISO 8601 calendar. The largestUnit and options arguments are used in calendar's dateUntil method. It performs the following steps when called:

  1. Assert: ISODateTimeWithinLimits(y1, mon1, d1, h1, min1, s1, ms1, mus1, ns1) is true.
  2. Assert: ISODateTimeWithinLimits(y2, mon2, d2, h2, min2, s2, ms2, mus2, ns2) is true.
  3. Assert: If y1y2, and mon1mon2, and d1d2, and LargerOfTwoTemporalUnits(largestUnit, "day") is not "day", CalendarMethodsRecordHasLookedUp(calendarRec, date-until) is true.
  4. Let timeDuration be ! DifferenceTime(h1, min1, s1, ms1, mus1, ns1, h2, min2, s2, ms2, mus2, ns2).
  5. Let timeSign be NormalizedTimeDurationSign(timeDuration).
  6. Let dateSign be ! CompareISODate(y2, mon2, d2, y1, mon1, d1).
  7. Let adjustedDate be CreateISODateRecord(y1, mon1, d1).
  8. If timeSign is -dateSign, then
    1. Set adjustedDate to BalanceISODate(adjustedDate.[[Year]], adjustedDate.[[Month]], adjustedDate.[[Day]] - timeSign).
    2. Set timeDuration to ? Add24HourDaysToNormalizedTimeDuration(timeDuration, -timeSign).
  9. Let date1 be ! CreateTemporalDate(adjustedDate.[[Year]], adjustedDate.[[Month]], adjustedDate.[[Day]], calendarRec.[[Receiver]]).
  10. Let date2 be ! CreateTemporalDate(y2, mon2, d2, calendarRec.[[Receiver]]).
  11. Let dateLargestUnit be LargerOfTwoTemporalUnits("day", largestUnit).
  12. Let untilOptions be ! SnapshotOwnProperties(options, null).
  13. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", dateLargestUnit).
  14. Let dateDifference be ? DifferenceDate(calendarRec, date1, date2, untilOptions).
  15. Return ? CreateNormalizedDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], dateDifference.[[Days]], timeDuration).

5.5.12 DifferenceTemporalPlainDateTime ( operation, dateTime, other, options )

The abstract operation DifferenceTemporalPlainDateTime takes arguments operation (since or until), dateTime (a Temporal.PlainDateTime), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by dateTime and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalDateTime(other).
  3. If ? CalendarEquals(dateTime.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, datetime, « », "nanosecond", "day").
  6. Let datePartsIdentical be false.
  7. If dateTime.[[ISOYear]] = other.[[ISOYear]], and dateTime.[[ISOMonth]] = other.[[ISOMonth]], and dateTime.[[ISODay]] = other.[[ISODay]], then
    1. Set datePartsIdentical to true.
  8. If datePartsIdentical is true, and dateTime.[[ISOHour]] = other.[[ISOHour]], and dateTime.[[ISOMinute]] = other.[[ISOMinute]], and dateTime.[[ISOSecond]] = other.[[ISOSecond]], and dateTime.[[ISOMillisecond]] = other.[[ISOMillisecond]], and dateTime.[[ISOMicrosecond]] = other.[[ISOMicrosecond]], and dateTime.[[ISONanosecond]] = other.[[ISONanosecond]], then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  9. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « date-add, date-until »).
  10. Let result be ? DifferenceISODateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], other.[[ISOYear]], other.[[ISOMonth]], other.[[ISODay]], other.[[ISOHour]], other.[[ISOMinute]], other.[[ISOSecond]], other.[[ISOMillisecond]], other.[[ISOMicrosecond]], other.[[ISONanosecond]], calendarRec, settings.[[LargestUnit]], resolvedOptions).
  11. If settings.[[SmallestUnit]] is "nanosecond" and settings.[[RoundingIncrement]] = 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
  12. If roundingGranularityIsNoop is false, then
    1. Let relativeTo be ! CreateTemporalDate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[Calendar]]).
    2. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[NormalizedTime]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], relativeTo, calendarRec).
    3. Let roundResult be roundRecord.[[NormalizedDuration]].
    4. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundResult.[[NormalizedTime]], roundResult.[[Days]]).
    5. Let timeResult be BalanceTimeDuration(normWithDays, settings.[[LargestUnit]]).
    6. Let balanceResult be ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], timeResult.[[Days]], settings.[[LargestUnit]], settings.[[SmallestUnit]], relativeTo, calendarRec).
  13. Else,
    1. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(result.[[NormalizedTime]], result.[[Days]]).
    2. Let timeResult be BalanceTimeDuration(normWithDays, settings.[[LargestUnit]]).
    3. Let balanceResult be ! CreateDateDurationRecord(result.[[Years]], result.[[Months]], result.[[Weeks]], timeResult.[[Days]]).
  14. Return ? CreateTemporalDuration(sign × balanceResult.[[Years]], sign × balanceResult.[[Months]], sign × balanceResult.[[Weeks]], sign × balanceResult.[[Days]], sign × timeResult.[[Hours]], sign × timeResult.[[Minutes]], sign × timeResult.[[Seconds]], sign × timeResult.[[Milliseconds]], sign × timeResult.[[Microseconds]], sign × timeResult.[[Nanoseconds]]).

5.5.13 AddDurationToOrSubtractDurationFromPlainDateTime ( operation, dateTime, temporalDurationLike, options )

The abstract operation AddDurationToOrSubtractDurationFromPlainDateTime takes arguments operation (add or subtract), dateTime (a Temporal.PlainDateTime), temporalDurationLike (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainDateTime or an abrupt completion. It adds/subtracts temporalDurationLike to/from dateTime, returning a point in time that is in the future/past relative to datetime. It performs the following steps when called:

  1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
  2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
  3. Set options to ? GetOptionsObject(options).
  4. Let calendarRec be ? CreateCalendarMethodsRecord(dateTime.[[Calendar]], « date-add »).
  5. Let norm be NormalizeTimeDuration(sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
  6. Let result be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendarRec, sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], norm, options).
  7. Assert: IsValidISODate(result.[[Year]], result.[[Month]], result.[[Day]]) is true.
  8. Assert: IsValidTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]) is true.
  9. Return ? CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], dateTime.[[Calendar]]).

6 Temporal.ZonedDateTime Objects

A Temporal.ZonedDateTime object is an Object referencing a fixed point in time with nanoseconds precision, and containing Object values corresponding to a particular time zone and calendar system.

6.1 The Temporal.ZonedDateTime Constructor

The Temporal.ZonedDateTime constructor:

  • creates and initializes a new Temporal.ZonedDateTime object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.ZonedDateTime behaviour must include a super call to the %Temporal.ZonedDateTime% constructor to create and initialize subclass instances with the necessary internal slots.

6.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZoneLike [ , calendarLike ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. Set epochNanoseconds to ? ToBigInt(epochNanoseconds).
  3. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  4. Let timeZone be ? ToTemporalTimeZoneSlotValue(timeZoneLike).
  5. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  6. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget).

6.2 Properties of the Temporal.ZonedDateTime Constructor

The value of the [[Prototype]] internal slot of the Temporal.ZonedDateTime constructor is the intrinsic object %Function.prototype%.

The Temporal.ZonedDateTime constructor has the following properties:

6.2.1 Temporal.ZonedDateTime.prototype

The initial value of Temporal.ZonedDateTime.prototype is %Temporal.ZonedDateTime.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

6.2.2 Temporal.ZonedDateTime.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. If Type(item) is Object and item has an [[InitializedTemporalZonedDateTime]] internal slot, then
    1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalDisambiguation reads "disambiguation", ToTemporalOffset reads "offset", and ToTemporalOverflow reads "overflow").
    2. Perform ? ToTemporalDisambiguation(options).
    3. Perform ? ToTemporalOffset(options, "reject").
    4. Perform ? ToTemporalOverflow(options).
    5. Return ! CreateTemporalZonedDateTime(item.[[Nanoseconds]], item.[[TimeZone]], item.[[Calendar]]).
  3. Return ? ToTemporalZonedDateTime(item, options).

6.2.3 Temporal.ZonedDateTime.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalZonedDateTime(one).
  2. Set two to ? ToTemporalZonedDateTime(two).
  3. Return 𝔽(CompareEpochNanoseconds(one.[[Nanoseconds]], two.[[Nanoseconds]])).

6.3 Properties of the Temporal.ZonedDateTime Prototype Object

The Temporal.ZonedDateTime prototype object

  • is itself an ordinary object.
  • is not a Temporal.ZonedDateTime instance and does not have a [[InitializedTemporalZonedDateTime]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

6.3.1 Temporal.ZonedDateTime.prototype.constructor

The initial value of Temporal.ZonedDateTime.prototype.constructor is %Temporal.ZonedDateTime%.

6.3.2 Temporal.ZonedDateTime.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.ZonedDateTime".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

6.3.3 get Temporal.ZonedDateTime.prototype.calendarId

Temporal.ZonedDateTime.prototype.calendarId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? ToTemporalCalendarIdentifier(zonedDateTime.[[Calendar]]).

6.3.4 get Temporal.ZonedDateTime.prototype.timeZoneId

Temporal.ZonedDateTime.prototype.timeZoneId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? ToTemporalTimeZoneIdentifier(zonedDateTime.[[TimeZone]]).

6.3.5 get Temporal.ZonedDateTime.prototype.year

Temporal.ZonedDateTime.prototype.year is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarYear(calendar, temporalDateTime)).

6.3.6 get Temporal.ZonedDateTime.prototype.month

Temporal.ZonedDateTime.prototype.month is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarMonth(calendar, temporalDateTime)).

6.3.7 get Temporal.ZonedDateTime.prototype.monthCode

Temporal.ZonedDateTime.prototype.monthCode is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ? CalendarMonthCode(calendar, temporalDateTime).

6.3.8 get Temporal.ZonedDateTime.prototype.day

Temporal.ZonedDateTime.prototype.day is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « day »).
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
  7. Return 𝔽(? CalendarDay(calendarRec, temporalDateTime)).

6.3.9 get Temporal.ZonedDateTime.prototype.hour

Temporal.ZonedDateTime.prototype.hour is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISOHour]]).

6.3.10 get Temporal.ZonedDateTime.prototype.minute

Temporal.ZonedDateTime.prototype.minute is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISOMinute]]).

6.3.11 get Temporal.ZonedDateTime.prototype.second

Temporal.ZonedDateTime.prototype.second is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISOSecond]]).

6.3.12 get Temporal.ZonedDateTime.prototype.millisecond

Temporal.ZonedDateTime.prototype.millisecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISOMillisecond]]).

6.3.13 get Temporal.ZonedDateTime.prototype.microsecond

Temporal.ZonedDateTime.prototype.microsecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISOMicrosecond]]).

6.3.14 get Temporal.ZonedDateTime.prototype.nanosecond

Temporal.ZonedDateTime.prototype.nanosecond is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(temporalDateTime.[[ISONanosecond]]).

6.3.15 get Temporal.ZonedDateTime.prototype.epochSeconds

Temporal.ZonedDateTime.prototype.epochSeconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let ns be zonedDateTime.[[Nanoseconds]].
  4. Let s be floor((ns) / 109).
  5. Return 𝔽(s).

6.3.16 get Temporal.ZonedDateTime.prototype.epochMilliseconds

Temporal.ZonedDateTime.prototype.epochMilliseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let ns be zonedDateTime.[[Nanoseconds]].
  4. Let ms be floor((ns) / 106).
  5. Return 𝔽(ms).

6.3.17 get Temporal.ZonedDateTime.prototype.epochMicroseconds

Temporal.ZonedDateTime.prototype.epochMicroseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let ns be zonedDateTime.[[Nanoseconds]].
  4. Let µs be floor((ns) / 103).
  5. Return (µs).

6.3.18 get Temporal.ZonedDateTime.prototype.epochNanoseconds

Temporal.ZonedDateTime.prototype.epochNanoseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return zonedDateTime.[[Nanoseconds]].

6.3.19 get Temporal.ZonedDateTime.prototype.dayOfWeek

Temporal.ZonedDateTime.prototype.dayOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarDayOfWeek(calendar, temporalDateTime)).

6.3.20 get Temporal.ZonedDateTime.prototype.dayOfYear

Temporal.ZonedDateTime.prototype.dayOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarDayOfYear(calendar, temporalDateTime)).

6.3.21 get Temporal.ZonedDateTime.prototype.weekOfYear

Temporal.ZonedDateTime.prototype.weekOfYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarWeekOfYear(calendar, temporalDateTime)).

6.3.22 get Temporal.ZonedDateTime.prototype.yearOfWeek

Temporal.ZonedDateTime.prototype.yearOfWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarYearOfWeek(calendar, temporalDateTime)).

6.3.23 get Temporal.ZonedDateTime.prototype.hoursInDay

Temporal.ZonedDateTime.prototype.hoursInDay is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  5. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, "iso8601").
  6. Let year be temporalDateTime.[[ISOYear]].
  7. Let month be temporalDateTime.[[ISOMonth]].
  8. Let day be temporalDateTime.[[ISODay]].
  9. Let today be ? CreateTemporalDateTime(year, month, day, 0, 0, 0, 0, 0, 0, "iso8601").
  10. Let tomorrowFields be BalanceISODate(year, month, day + 1).
  11. Let tomorrow be ? CreateTemporalDateTime(tomorrowFields.[[Year]], tomorrowFields.[[Month]], tomorrowFields.[[Day]], 0, 0, 0, 0, 0, 0, "iso8601").
  12. Let todayInstant be ? GetInstantFor(timeZoneRec, today, "compatible").
  13. Let tomorrowInstant be ? GetInstantFor(timeZoneRec, tomorrow, "compatible").
  14. Let diff be NormalizedTimeDurationFromEpochNanosecondsDifference(tomorrowInstant.[[Nanoseconds]], todayInstant.[[Nanoseconds]]).
  15. Return 𝔽(DivideNormalizedTimeDuration(diff, 3.6 × 1012)).

6.3.24 get Temporal.ZonedDateTime.prototype.daysInWeek

Temporal.ZonedDateTime.prototype.daysInWeek is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarDaysInWeek(calendar, temporalDateTime)).

6.3.25 get Temporal.ZonedDateTime.prototype.daysInMonth

Temporal.ZonedDateTime.prototype.daysInMonth is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarDaysInMonth(calendar, temporalDateTime)).

6.3.26 get Temporal.ZonedDateTime.prototype.daysInYear

Temporal.ZonedDateTime.prototype.daysInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarDaysInYear(calendar, temporalDateTime)).

6.3.27 get Temporal.ZonedDateTime.prototype.monthsInYear

Temporal.ZonedDateTime.prototype.monthsInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return 𝔽(? CalendarMonthsInYear(calendar, temporalDateTime)).

6.3.28 get Temporal.ZonedDateTime.prototype.inLeapYear

Temporal.ZonedDateTime.prototype.inLeapYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ? CalendarInLeapYear(calendar, temporalDateTime).

6.3.29 get Temporal.ZonedDateTime.prototype.offsetNanoseconds

Temporal.ZonedDateTime.prototype.offsetNanoseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  5. Return 𝔽(? GetOffsetNanosecondsFor(timeZoneRec, instant)).

6.3.30 get Temporal.ZonedDateTime.prototype.offset

Temporal.ZonedDateTime.prototype.offset is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  5. Return ? GetOffsetStringFor(timeZoneRec, instant).

6.3.31 Temporal.ZonedDateTime.prototype.with ( temporalZonedDateTimeLike [ , options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. If ? IsPartialTemporalObject(temporalZonedDateTimeLike) is false, throw a TypeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « date-from-fields, fields, merge-fields »).
  6. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  7. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  8. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  9. Let dateTime be ! GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]], offsetNanoseconds).
  10. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
  11. Let fields be ? PrepareTemporalFields(dateTime, fieldNames, « »).
  12. Perform ! CreateDataPropertyOrThrow(fields, "hour", dateTime.[[ISOHour]]).
  13. Perform ! CreateDataPropertyOrThrow(fields, "minute", dateTime.[[ISOMinute]]).
  14. Perform ! CreateDataPropertyOrThrow(fields, "second", dateTime.[[ISOSecond]]).
  15. Perform ! CreateDataPropertyOrThrow(fields, "millisecond", dateTime.[[ISOMillisecond]]).
  16. Perform ! CreateDataPropertyOrThrow(fields, "microsecond", dateTime.[[ISOMicrosecond]]).
  17. Perform ! CreateDataPropertyOrThrow(fields, "nanosecond", dateTime.[[ISONanosecond]]).
  18. Perform ! CreateDataPropertyOrThrow(fields, "offset", FormatUTCOffsetNanoseconds(offsetNanoseconds)).
  19. Append "hour", "microsecond", "millisecond", "minute", "nanosecond", "offset", and "second" to fieldNames.
  20. Let partialZonedDateTime be ? PrepareTemporalFields(temporalZonedDateTimeLike, fieldNames, partial).
  21. Set fields to ? CalendarMergeFields(calendarRec, fields, partialZonedDateTime).
  22. Set fields to ? PrepareTemporalFields(fields, fieldNames, « "offset" »).
  23. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalDisambiguation reads "disambiguation", ToTemporalOffset reads "offset", and InterpretTemporalDateTimeFields reads "overflow").
  24. Let disambiguation be ? ToTemporalDisambiguation(resolvedOptions).
  25. Let offset be ? ToTemporalOffset(resolvedOptions, "prefer").
  26. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendarRec, fields, resolvedOptions).
  27. Let offsetString be ! Get(fields, "offset").
  28. Assert: Type(offsetString) is String.
  29. Let newOffsetNanoseconds be ? ParseDateTimeUTCOffset(offsetString).
  30. Let epochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[Year]], dateTimeResult.[[Month]], dateTimeResult.[[Day]], dateTimeResult.[[Hour]], dateTimeResult.[[Minute]], dateTimeResult.[[Second]], dateTimeResult.[[Millisecond]], dateTimeResult.[[Microsecond]], dateTimeResult.[[Nanosecond]], option, newOffsetNanoseconds, timeZoneRec, disambiguation, offset, match-exactly).
  31. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZoneRec.[[Receiver]], calendarRec.[[Receiver]]).

6.3.32 Temporal.ZonedDateTime.prototype.withPlainTime ( [ plainTimeLike ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. If plainTimeLike is undefined, then
    1. Let plainTime be ! CreateTemporalTime(0, 0, 0, 0, 0, 0).
  4. Else,
    1. Let plainTime be ? ToTemporalTime(plainTimeLike).
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  6. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  7. Let calendar be zonedDateTime.[[Calendar]].
  8. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  9. Let resultPlainDateTime be ? CreateTemporalDateTime(plainDateTime.[[ISOYear]], plainDateTime.[[ISOMonth]], plainDateTime.[[ISODay]], plainTime.[[ISOHour]], plainTime.[[ISOMinute]], plainTime.[[ISOSecond]], plainTime.[[ISOMillisecond]], plainTime.[[ISOMicrosecond]], plainTime.[[ISONanosecond]], calendar).
  10. Set instant to ? GetInstantFor(timeZoneRec, resultPlainDateTime, "compatible").
  11. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZoneRec.[[Receiver]], calendar).

6.3.33 Temporal.ZonedDateTime.prototype.withPlainDate ( plainDateLike )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let plainDate be ? ToTemporalDate(plainDateLike).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  6. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, zonedDateTime.[[Calendar]]).
  7. Let calendar be ? ConsolidateCalendars(zonedDateTime.[[Calendar]], plainDate.[[Calendar]]).
  8. Let resultPlainDateTime be ? CreateTemporalDateTime(plainDate.[[ISOYear]], plainDate.[[ISOMonth]], plainDate.[[ISODay]], plainDateTime.[[ISOHour]], plainDateTime.[[ISOMinute]], plainDateTime.[[ISOSecond]], plainDateTime.[[ISOMillisecond]], plainDateTime.[[ISOMicrosecond]], plainDateTime.[[ISONanosecond]], calendar).
  9. Set instant to ? GetInstantFor(timeZoneRec, resultPlainDateTime, "compatible").
  10. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZoneRec.[[Receiver]], calendar).

6.3.34 Temporal.ZonedDateTime.prototype.withTimeZone ( timeZoneLike )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZone be ? ToTemporalTimeZoneSlotValue(timeZoneLike).
  4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZone, zonedDateTime.[[Calendar]]).

6.3.35 Temporal.ZonedDateTime.prototype.withCalendar ( calendarLike )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], zonedDateTime.[[TimeZone]], calendar).

6.3.36 Temporal.ZonedDateTime.prototype.add ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(add, zonedDateTime, temporalDurationLike, options).

6.3.37 Temporal.ZonedDateTime.prototype.subtract ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? AddDurationToOrSubtractDurationFromZonedDateTime(subtract, zonedDateTime, temporalDurationLike, options).

6.3.38 Temporal.ZonedDateTime.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? DifferenceTemporalZonedDateTime(until, zonedDateTime, other, options).

6.3.39 Temporal.ZonedDateTime.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? DifferenceTemporalZonedDateTime(since, zonedDateTime, other, options).

6.3.40 Temporal.ZonedDateTime.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. If roundTo is undefined, then
    1. Throw a TypeError exception.
  4. If Type(roundTo) is String, then
    1. Let paramString be roundTo.
    2. Set roundTo to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
  5. Else,
    1. Set roundTo to ? GetOptionsObject(roundTo).
  6. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  7. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
  8. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
  9. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required, « "day" »).
  10. If smallestUnit is "day", then
    1. Let maximum be 1.
    2. Let inclusive be true.
  11. Else,
    1. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
    2. Assert: maximum is not undefined.
    3. Let inclusive be false.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, inclusive).
  13. If smallestUnit is "nanosecond" and roundingIncrement is 1, then
    1. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[Nanoseconds]], zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]]).
  14. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  15. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  16. Let calendar be zonedDateTime.[[Calendar]].
  17. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  18. Let temporalDateTime be ! GetPlainDateTimeFor(timeZoneRec, instant, calendar, offsetNanoseconds).
  19. Let dtStart be ? CreateTemporalDateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, "iso8601").
  20. Let instantStart be ? GetInstantFor(timeZoneRec, dtStart, "compatible").
  21. Let startNs be instantStart.[[Nanoseconds]].
  22. Let endNs be ? AddDaysToZonedDateTime(instantStart, dtStart, timeZoneRec, calendar, 1).[[EpochNanoseconds]].
  23. Let dayLengthNs be (endNs - startNs).
  24. If dayLengthNs ≤ 0, then
    1. Throw a RangeError exception.
  25. Let roundResult be RoundISODateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], roundingIncrement, smallestUnit, roundingMode, dayLengthNs).
  26. Let epochNanoseconds be ? InterpretISODateTimeOffset(roundResult.[[Year]], roundResult.[[Month]], roundResult.[[Day]], roundResult.[[Hour]], roundResult.[[Minute]], roundResult.[[Second]], roundResult.[[Millisecond]], roundResult.[[Microsecond]], roundResult.[[Nanosecond]], option, offsetNanoseconds, timeZoneRec, "compatible", "prefer", match-exactly).
  27. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZoneRec.[[Receiver]], calendar).

6.3.41 Temporal.ZonedDateTime.prototype.equals ( other )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Set other to ? ToTemporalZonedDateTime(other).
  4. If zonedDateTime.[[Nanoseconds]]other.[[Nanoseconds]], return false.
  5. If ? TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, return false.
  6. Return ? CalendarEquals(zonedDateTime.[[Calendar]], other.[[Calendar]]).

6.3.42 Temporal.ZonedDateTime.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Set options to ? GetOptionsObject(options).
  4. NOTE: The following steps read options and perform independent validation in alphabetical order (ToCalendarNameOption reads "calendarName", ToFractionalSecondDigits reads "fractionalSecondDigits", ToShowOffsetOption reads "offset", and ToTemporalRoundingMode reads "roundingMode").
  5. Let showCalendar be ? ToCalendarNameOption(options).
  6. Let digits be ? ToFractionalSecondDigits(options).
  7. Let showOffset be ? ToShowOffsetOption(options).
  8. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  9. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", time, undefined).
  10. If smallestUnit is "hour", throw a RangeError exception.
  11. Let showTimeZone be ? ToTimeZoneNameOption(options).
  12. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  13. Return ? TemporalZonedDateTimeToString(zonedDateTime, precision.[[Precision]], showCalendar, showTimeZone, showOffset, precision.[[Increment]], precision.[[Unit]], roundingMode).

6.3.43 Temporal.ZonedDateTime.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? TemporalZonedDateTimeToString(zonedDateTime, "auto", "auto", "auto", "auto").

6.3.44 Temporal.ZonedDateTime.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ? TemporalZonedDateTimeToString(zonedDateTime, "auto", "auto", "auto", "auto").

6.3.45 Temporal.ZonedDateTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

6.3.46 Temporal.ZonedDateTime.prototype.startOfDay ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Let startDateTime be ? CreateTemporalDateTime(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], 0, 0, 0, 0, 0, 0, calendar).
  8. Let startInstant be ? GetInstantFor(timeZoneRec, startDateTime, "compatible").
  9. Return ! CreateTemporalZonedDateTime(startInstant.[[Nanoseconds]], timeZoneRec,[[Receiver]], calendar).

6.3.47 Temporal.ZonedDateTime.prototype.toInstant ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).

6.3.48 Temporal.ZonedDateTime.prototype.toPlainDate ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ! CreateTemporalDate(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], calendar).

6.3.49 Temporal.ZonedDateTime.prototype.toPlainTime ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ! CreateTemporalTime(temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]]).

6.3.50 Temporal.ZonedDateTime.prototype.toPlainDateTime ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  5. Return ? GetPlainDateTimeFor(timeZoneRec, instant, zonedDateTime.[[Calendar]]).

6.3.51 Temporal.ZonedDateTime.prototype.toPlainYearMonth ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « fields, year-month-from-fields »).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
  7. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  8. Let fields be ? PrepareTemporalFields(temporalDateTime, fieldNames, «»).
  9. Return ? CalendarYearMonthFromFields(calendarRec, fields).
  10. NOTE: The call to CalendarYearMonthFromFields is necessary in order to create a PlainYearMonth object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

6.3.52 Temporal.ZonedDateTime.prototype.toPlainMonthDay ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « fields, month-day-from-fields »).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  5. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  6. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
  7. Let fieldNames be ? CalendarFields(calendarRec, « "day", "monthCode" »).
  8. Let fields be ? PrepareTemporalFields(temporalDateTime, fieldNames, «»).
  9. Return ? CalendarMonthDayFromFields(calendarRec, fields).
  10. NOTE: The call to CalendarMonthDayFromFields is necessary in order to create a PlainMonthDay object with the [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots set correctly.

6.3.53 Temporal.ZonedDateTime.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  5. Let calendar be zonedDateTime.[[Calendar]].
  6. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  7. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  8. Let dateTime be ! GetPlainDateTimeFor(timeZoneRec, instant, calendar, offsetNanoseconds).
  9. Let offset be FormatUTCOffsetNanoseconds(offsetNanoseconds).
  10. Perform ! CreateDataPropertyOrThrow(fields, "calendar", calendar).
  11. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(dateTime.[[ISODay]])).
  12. Perform ! CreateDataPropertyOrThrow(fields, "isoHour", 𝔽(dateTime.[[ISOHour]])).
  13. Perform ! CreateDataPropertyOrThrow(fields, "isoMicrosecond", 𝔽(dateTime.[[ISOMicrosecond]])).
  14. Perform ! CreateDataPropertyOrThrow(fields, "isoMillisecond", 𝔽(dateTime.[[ISOMillisecond]])).
  15. Perform ! CreateDataPropertyOrThrow(fields, "isoMinute", 𝔽(dateTime.[[ISOMinute]])).
  16. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(dateTime.[[ISOMonth]])).
  17. Perform ! CreateDataPropertyOrThrow(fields, "isoNanosecond", 𝔽(dateTime.[[ISONanosecond]])).
  18. Perform ! CreateDataPropertyOrThrow(fields, "isoSecond", 𝔽(dateTime.[[ISOSecond]])).
  19. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(dateTime.[[ISOYear]])).
  20. Perform ! CreateDataPropertyOrThrow(fields, "offset", offset).
  21. Perform ! CreateDataPropertyOrThrow(fields, "timeZone", timeZoneRec.[[Receiver]]).
  22. Return fields.

6.3.54 Temporal.ZonedDateTime.prototype.getCalendar ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ToTemporalCalendarObject(zonedDateTime.[[Calendar]]).

6.3.55 Temporal.ZonedDateTime.prototype.getTimeZone ( )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Return ToTemporalTimeZoneObject(zonedDateTime.[[TimeZone]]).

6.4 Properties of Temporal.ZonedDateTime Instances

Temporal.ZonedDateTime instances are ordinary objects that inherit properties from the %Temporal.ZonedDateTime.prototype% intrinsic object. Temporal.ZonedDateTime instances are initially created with the internal slots described in Table 8.

Table 8: Internal Slots of Temporal.ZonedDateTime Instances
Internal Slot Description
[[InitializedTemporalZonedDateTime]] The only specified use of this slot is for distinguishing Temporal.ZonedDateTime instances from other objects.
[[Nanoseconds]] A BigInt value representing the number of nanoseconds since the epoch.
[[TimeZone]] A String or Object representing the time zone.
[[Calendar]] A String or Object representing the calendar.

6.5 Abstract Operations

6.5.1 InterpretISODateTimeOffset ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, offsetBehaviour, offsetNanoseconds, timeZoneRec, disambiguation, offsetOption, matchBehaviour )

The abstract operation InterpretISODateTimeOffset takes arguments year (an integer), month (an integer), day (an integer), hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), nanosecond (an integer), offsetBehaviour (one of option, exact, or wall), offsetNanoseconds (an integer), timeZoneRec (a Time Zone Methods Record), disambiguation (one of "earlier", "later", "compatible", or "reject"), offsetOption (one of "ignore", "use", "prefer", or "reject"), and matchBehaviour (one of match-exactly or match-minutes) and returns either a normal completion containing a BigInt or an abrupt completion.

It determines the exact time in timeZone corresponding to the given calendar date and time, and the given UTC offset in nanoseconds. In the case of more than one possible exact time, or no possible exact time, an answer is determined using offsetBehaviour, disambiguation and offsetOption.

As a special case when parsing ISO 8601 strings which are only required to specify time zone offsets to minutes precision, if matchBehaviour is match minutes, then a value for offsetNanoseconds that is rounded to the nearest minute will be accepted in those cases where offsetNanoseconds is compared against timeZone's offset. If matchBehaviour is match exactly, then this does not happen.

It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  3. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-possible-instants-for) is true.
  4. Let dateTime be ? CreateTemporalDateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, "iso8601").
  5. If offsetBehaviour is wall, or offsetBehaviour is option and offsetOption is "ignore", then
    1. Let instant be ? GetInstantFor(timeZoneRec, dateTime, disambiguation).
    2. Return instant.[[Nanoseconds]].
  6. If offsetBehaviour is exact, or offsetBehaviour is option and offsetOption is "use", then
    1. Let epochNanoseconds be GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, offsetNanoseconds).
    2. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
    3. Return epochNanoseconds.
  7. Assert: offsetBehaviour is option.
  8. Assert: offsetOption is "prefer" or "reject".
  9. Let possibleInstants be ? GetPossibleInstantsFor(timeZoneRec, dateTime).
  10. If possibleInstants is not empty, then
    1. For each element candidate of possibleInstants, do
      1. Let candidateNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, candidate).
      2. If candidateNanoseconds = offsetNanoseconds, then
        1. Return candidate.[[Nanoseconds]].
      3. If matchBehaviour is match-minutes, then
        1. Let roundedCandidateNanoseconds be RoundNumberToIncrement(candidateNanoseconds, 60 × 109, "halfExpand").
        2. If roundedCandidateNanoseconds = offsetNanoseconds, then
          1. Return candidate.[[Nanoseconds]].
  11. If offsetOption is "reject", throw a RangeError exception.
  12. Let instant be ? DisambiguatePossibleInstants(possibleInstants, timeZoneRec, dateTime, disambiguation).
  13. Return instant.[[Nanoseconds]].

6.5.2 ToTemporalZonedDateTime ( item [ , options ] )

The abstract operation ToTemporalZonedDateTime takes argument item (an ECMAScript language value) and optional argument options (an Object) and returns either a normal completion containing a Temporal.ZonedDateTime, or a throw completion. It returns its argument item if it is already a Temporal.ZonedDateTime instance, converts item to a new Temporal.ZonedDateTime instance if possible, and throws otherwise. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let resolvedOptions be ? SnapshotOwnProperties(! GetOptionsObject(options), null).
  3. Let offsetBehaviour be option.
  4. Let matchBehaviour be match-exactly.
  5. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return item.
    2. Let calendar be ? GetTemporalCalendarSlotValueWithISODefault(item).
    3. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « date-from-fields, fields »).
    4. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
    5. Append "hour", "microsecond", "millisecond", "minute", "nanosecond", "offset", "second", and "timeZone" to fieldNames.
    6. Let fields be ? PrepareTemporalFields(item, fieldNames, « "timeZone" »).
    7. Let timeZone be ! Get(fields, "timeZone").
    8. Set timeZone to ? ToTemporalTimeZoneSlotValue(timeZone).
    9. Let offsetString be ! Get(fields, "offset").
    10. Assert: offsetString is a String or undefined.
    11. If offsetString is undefined, then
      1. Set offsetBehaviour to wall.
    12. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalDisambiguation reads "disambiguation", ToTemporalOffset reads "offset", and InterpretTemporalDateTimeFields reads "overflow").
    13. Let disambiguation be ? ToTemporalDisambiguation(resolvedOptions).
    14. Let offsetOption be ? ToTemporalOffset(resolvedOptions, "reject").
    15. Let result be ? InterpretTemporalDateTimeFields(calendarRec, fields, resolvedOptions).
  6. Else,
    1. If item is not a String, throw a TypeError exception.
    2. Let result be ? ParseTemporalZonedDateTimeString(item).
    3. Let annotation be result.[[TimeZone]].[[TimeZoneAnnotation]].
    4. Assert: annotation is not undefined.
    5. Let timeZone be ? ToTemporalTimeZoneSlotValue(annotation).
    6. Let offsetString be result.[[TimeZone]].[[OffsetString]].
    7. If result.[[TimeZone]].[[Z]] is true, then
      1. Set offsetBehaviour to exact.
    8. Else if offsetString is undefined, then
      1. Set offsetBehaviour to wall.
    9. Let calendar be result.[[Calendar]].
    10. If calendar is undefined, set calendar to "iso8601".
    11. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
    12. Set calendar to the ASCII-lowercase of calendar.
    13. Set matchBehaviour to match-minutes.
    14. Let disambiguation be ? ToTemporalDisambiguation(resolvedOptions).
    15. Let offsetOption be ? ToTemporalOffset(resolvedOptions, "reject").
    16. Perform ? ToTemporalOverflow(resolvedOptions).
  7. Let offsetNanoseconds be 0.
  8. If offsetBehaviour is option, then
    1. Set offsetNanoseconds to ? ParseDateTimeUTCOffset(offsetString).
  9. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  10. Let epochNanoseconds be ? InterpretISODateTimeOffset(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], offsetBehaviour, offsetNanoseconds, timeZoneRec, disambiguation, offsetOption, matchBehaviour).
  11. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

6.5.3 CreateTemporalZonedDateTime ( epochNanoseconds, timeZone, calendar [ , newTarget ] )

The abstract operation CreateTemporalZonedDateTime takes arguments epochNanoseconds (a BigInt), timeZone (a String or Object), and calendar (a String or Object) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.ZonedDateTime, or an abrupt completion. It creates a Temporal.ZonedDateTime instance and fills the internal slots with valid values. It performs the following steps when called:

  1. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true.
  2. If newTarget is not present, set newTarget to %Temporal.ZonedDateTime%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.ZonedDateTime.prototype%", « [[InitializedTemporalZonedDateTime]], [[Nanoseconds]], [[TimeZone]], [[Calendar]] »).
  4. Set object.[[Nanoseconds]] to epochNanoseconds.
  5. Set object.[[TimeZone]] to timeZone.
  6. Set object.[[Calendar]] to calendar.
  7. Return object.

6.5.4 TemporalZonedDateTimeToString ( zonedDateTime, precision, showCalendar, showTimeZone, showOffset [ , increment [ , unit [ , roundingMode ] ] ] )

The abstract operation TemporalZonedDateTimeToString takes arguments zonedDateTime (a Temporal.ZonedDateTime), precision (one of "auto", "minute", or an integer between 0 and 9 inclusive), showCalendar (one of "auto", "always", "never", or "critical"), showTimeZone (one of "auto", "never", or "critical"), and showOffset (one of "auto" or "never") and optional arguments increment (an integer), unit (one of "minute", "second", "millisecond", "microsecond", or "nanosecond"), and roundingMode (a String from the Identifier column of Table 19) and returns either a normal completion containing a String or an abrupt completion. It returns an ISO 8601 string representation of its argument, including a time zone name annotation and calendar annotation, which are extensions to the ISO 8601 format. It performs the following steps when called:

  1. If increment is not present, set increment to 1.
  2. If unit is not present, set unit to "nanosecond".
  3. If roundingMode is not present, set roundingMode to "trunc".
  4. Let ns be RoundTemporalInstant(zonedDateTime.[[Nanoseconds]], increment, unit, roundingMode).
  5. Let timeZone be zonedDateTime.[[TimeZone]].
  6. Let instant be ! CreateTemporalInstant(ns).
  7. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for »).
  8. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  9. Let temporalDateTime be ! GetPlainDateTimeFor(timeZoneRec, instant, "iso8601", offsetNanoseconds).
  10. Let dateTimeString be ! TemporalDateTimeToString(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], "iso8601", precision, "never").
  11. If showOffset is "never", then
    1. Let offsetString be the empty String.
  12. Else,
    1. Let offsetString be FormatDateTimeUTCOffsetRounded(offsetNanoseconds).
  13. If showTimeZone is "never", then
    1. Let timeZoneString be the empty String.
  14. Else,
    1. Let timeZoneIdentifier be ? ToTemporalTimeZoneIdentifier(timeZone).
    2. If showTimeZone is "critical", let flag be "!"; else let flag be the empty String.
    3. Let timeZoneString be the string-concatenation of the code unit 0x005B (LEFT SQUARE BRACKET), flag, timeZoneIdentifier, and the code unit 0x005D (RIGHT SQUARE BRACKET).
  15. Let calendarString be ? MaybeFormatCalendarAnnotation(zonedDateTime.[[Calendar]], showCalendar).
  16. Return the string-concatenation of dateTimeString, offsetString, timeZoneString, and calendarString.

6.5.5 AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months, weeks, days, norm [ , precalculatedPlainDateTime [ , options ] ] )

The abstract operation AddZonedDateTime takes arguments epochNanoseconds (a BigInt), timeZoneRec (a Time Zone Methods Record), calendarRec (a Calendar Methods Record), years (an integer), months (an integer), weeks (an integer), days (an integer), and norm (a Normalized Time Duration Record) and optional arguments precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and options (an Object) and returns either a normal completion containing a BigInt or an abrupt completion. It adds a duration in various units to a number of nanoseconds epochNanoseconds since the epoch, subject to the rules of the time zone and calendar, and returns the result as a BigInt value. As specified in RFC 5545, the date portion of the duration is added in calendar days, and the time portion is added in exact time.

Unless precalculatedPlainDateTime is supplied, the given timeZone's getOffsetNanosecondsFor method will be called to convert epochNanoseconds to a wall-clock time, and timeZoneRec must have looked up getOffsetNanosecondsFor. getPossibleInstantsFor will always be called and must have been looked up.

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-possible-instants-for) is true.
  2. If precalculatedPlainDateTime is not present, set precalculatedPlainDateTime to undefined.
  3. Assert: If precalculatedPlainDateTime is undefined, TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  4. If options is not present, set options to undefined.
  5. Assert: Type(options) is Object or Undefined.
  6. If years = 0, months = 0, weeks = 0, and days = 0, then
    1. Return ? AddInstant(epochNanoseconds, norm).
  7. Let instant be ! CreateTemporalInstant(epochNanoseconds).
  8. If precalculatedPlainDateTime is not undefined, then
    1. Let temporalDateTime be precalculatedPlainDateTime.
  9. Else,
    1. Let temporalDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
  10. If years = 0, and months = 0, and weeks = 0, then
    1. Let overflow be ? ToTemporalOverflow(options).
    2. Let intermediate be ? AddDaysToZonedDateTime(instant, temporalDateTime, timeZoneRec, calendarRec.[[Receiver]], days, overflow).[[EpochNanoseconds]].
    3. Return ? AddInstant(intermediate, norm).
  11. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-add) is true.
  12. Let datePart be ! CreateTemporalDate(temporalDateTime.[[ISOYear]], temporalDateTime.[[ISOMonth]], temporalDateTime.[[ISODay]], calendarRec.[[Receiver]]).
  13. Let dateDuration be ! CreateTemporalDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0).
  14. Let addedDate be ? CalendarDateAdd(calendarRec, datePart, dateDuration, options).
  15. Let intermediateDateTime be ? CreateTemporalDateTime(addedDate.[[ISOYear]], addedDate.[[ISOMonth]], addedDate.[[ISODay]], temporalDateTime.[[ISOHour]], temporalDateTime.[[ISOMinute]], temporalDateTime.[[ISOSecond]], temporalDateTime.[[ISOMillisecond]], temporalDateTime.[[ISOMicrosecond]], temporalDateTime.[[ISONanosecond]], calendarRec.[[Receiver]]).
  16. Let intermediateInstant be ? GetInstantFor(timeZoneRec, intermediateDateTime, "compatible").
  17. Return ? AddInstant(intermediateInstant.[[Nanoseconds]], norm).

6.5.6 AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ , overflow ] )

The abstract operation AddDaysToZonedDateTime takes arguments instant (a Temporal.Instant), dateTime (a Temporal.PlainDateTime), timeZoneRec (a Time Zone Methods Record), calendar (a String or Object), and days (an integer) and optional argument overflow ("constrain" or "reject") and returns either a normal completion containing a Record, or an abrupt completion. The returned Record has fields [[EpochNanoseconds]] (a BigInt), [[Instant]] (a Temporal.Instant), and [[DateTime]] (a Temporal.PlainDateTime).

This operation is similar to AddZonedDateTime, but adds only a number of days instead of a full duration, which allows performing fewer observable operations.

  1. Assert: If TimeZoneMethodsRecordIsBuiltin(timeZoneRec) is true, dateTime's internal slots are the same as those of the Object returned from ! GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  2. If overflow is not present, set overflow to "constrain".
  3. If days = 0, then
    1. Return the Record { [[EpochNanoseconds]]: instant.[[Nanoseconds]], [[Instant]]: instant, [[DateTime]]: dateTime  }.
  4. Let addedDate be ? AddISODate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], 0, 0, 0, days, overflow).
  5. Let dateTimeResult be ? CreateTemporalDateTime(addedDate.[[Year]], addedDate.[[Month]], addedDate.[[Day]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], calendar).
  6. Let instantResult be ? GetInstantFor(timeZoneRec, dateTimeResult, "compatible").
  7. Return the Record { [[EpochNanoseconds]]: instantResult.[[Nanoseconds]], [[Instant]]: instantResult, [[DateTime]]: dateTimeResult  }.

6.5.7 DifferenceZonedDateTime ( ns1, ns2, timeZoneRec, calendarRec, largestUnit, options, precalculatedPlainDateTime )

The abstract operation DifferenceZonedDateTime takes arguments ns1 (a BigInt), ns2 (a BigInt), timeZoneRec (a Time Zone Methods Record), calendarRec (a Calendar Methods Record), largestUnit (a String), options (an ordinary Object for which the value of the [[Prototype]] internal slot is null and every property is a data property), and precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and returns either a normal completion containing a Normalized Duration Record, or a throw completion. It computes the difference between two exact times expressed in nanoseconds since the epoch, and balances the result so that there is no non-zero unit larger than largestUnit in the result, taking calendar reckoning and time zone offset changes into account.

Unless ns1 and ns2 are equal, timeZoneRec must have looked up both getOffsetNanosecondsFor and getPossibleInstantsFor.

  1. If ns1 is ns2, then
    1. Return ! CreateNormalizedDurationRecord(0, 0, 0, 0, ZeroTimeDuration()).
  2. If precalculatedPlainDateTime is undefined, then
    1. Let startInstant be ! CreateTemporalInstant(ns1).
    2. Let startDateTime be ? GetPlainDateTimeFor(timeZoneRec, startInstant, calendarRec.[[Receiver]]).
  3. Else,
    1. Let startDateTime be precalculatedPlainDateTime.
  4. Let endInstant be ! CreateTemporalInstant(ns2).
  5. Let endDateTime be ? GetPlainDateTimeFor(timeZoneRec, endInstant, calendarRec.[[Receiver]]).
  6. Let dateDifference be ? DifferenceISODateTime(startDateTime.[[ISOYear]], startDateTime.[[ISOMonth]], startDateTime.[[ISODay]], startDateTime.[[ISOHour]], startDateTime.[[ISOMinute]], startDateTime.[[ISOSecond]], startDateTime.[[ISOMillisecond]], startDateTime.[[ISOMicrosecond]], startDateTime.[[ISONanosecond]], endDateTime.[[ISOYear]], endDateTime.[[ISOMonth]], endDateTime.[[ISODay]], endDateTime.[[ISOHour]], endDateTime.[[ISOMinute]], endDateTime.[[ISOSecond]], endDateTime.[[ISOMillisecond]], endDateTime.[[ISOMicrosecond]], endDateTime.[[ISONanosecond]], calendarRec, largestUnit, options).
  7. Let intermediateNs be ? AddZonedDateTime(ns1, timeZoneRec, calendarRec, dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], 0, ZeroTimeDuration(), startDateTime).
  8. Let norm be NormalizedTimeDurationFromEpochNanosecondsDifference(ns2, intermediateNs).
  9. Let intermediate be ! CreateTemporalZonedDateTime(intermediateNs, timeZoneRec.[[Receiver]], calendarRec.[[Receiver]]).
  10. Let result be ? NormalizedTimeDurationToDays(norm, intermediate, timeZoneRec).
  11. Return ! CreateNormalizedDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Remainder]]).

6.5.8 NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] )

The abstract operation NormalizedTimeDurationToDays takes arguments norm (a Normalized Time Duration Record), zonedRelativeTo (a Temporal.ZonedDateTime), and timeZoneRec (a Time Zone Methods Record) and optional argument precalculatedPlainDateTime (a Temporal.PlainDateTime) and returns either a normal completion containing a Record with fields [[Days]] (an integer), [[Remainder]] (a Normalized Time Duration Record), and [[DayLength]] (an integer), or an abrupt completion. It converts a normalized time duration norm relative to a Temporal.ZonedDateTime zonedRelativeTo into a number of days and a remainder normalized time duration, taking into account any offset changes in the time zone of zonedRelativeTo. It also returns the length of the last day in nanoseconds, for rounding purposes.

Unless nanoseconds = 0, timeZoneRec must have looked up both getOffsetNanosecondsFor and getPossibleInstantsFor.

  1. Let sign be NormalizedTimeDurationSign(norm).
  2. If sign = 0, then
    1. Return the Record { [[Days]]: 0, [[Remainder]]: norm, [[DayLength]]: nsPerDay }.
  3. Let startNs be zonedRelativeTo.[[Nanoseconds]].
  4. Let startInstant be ! CreateTemporalInstant(startNs).
  5. Let endNs be ? AddInstant(startNs, norm).
  6. Let endInstant be ! CreateTemporalInstant(endNs).
  7. If precalculatedPlainDateTime is present, let startDateTime be precalculatedPlainDateTime; else let startDateTime be ? GetPlainDateTimeFor(timeZoneRec, startInstant, "iso8601").
  8. Let endDateTime be ? GetPlainDateTimeFor(timeZoneRec, endInstant, "iso8601").
  9. Let date1 be ! CreateTemporalDate(startDateTime.[[ISOYear]], startDateTime.[[ISOMonth]], startDateTime.[[ISODay]], "iso8601").
  10. Let date2 be ! CreateTemporalDate(endDateTime.[[ISOYear]], endDateTime.[[ISOMonth]], endDateTime.[[ISODay]], "iso8601").
  11. Let days be DaysUntil(date1, date2).
  12. Let timeSign be CompareTemporalTime(startDateTime.[[ISOHour]], startDateTime.[[ISOMinute]], startDateTime.[[ISOSecond]], startDateTime.[[ISOMillisecond]], startDateTime.[[ISOMicrosecond]], startDateTime.[[ISONanosecond]], endDateTime.[[ISOHour]], endDateTime.[[ISOMinute]], endDateTime.[[ISOSecond]], endDateTime.[[ISOMillisecond]], endDateTime.[[ISOMicrosecond]], endDateTime.[[ISONanosecond]]).
  13. If days > 0 and timeSign > 0, then
    1. Set days to days - 1.
  14. Else if days < 0 and timeSign < 0, then
    1. Set days to days + 1.
  15. Let relativeResult be ? AddDaysToZonedDateTime(startInstant, startDateTime, timeZoneRec, zonedRelativeTo.[[Calendar]], days).
  16. If sign = 1, and days > 0, and (relativeResult.[[EpochNanoseconds]]) > endNs, then
    1. Set days to days - 1.
    2. Set relativeResult to ? AddDaysToZonedDateTime(startInstant, startDateTime, timeZoneRec, zonedRelativeTo.[[Calendar]], days).
    3. If days > 0 and (relativeResult.[[EpochNanoseconds]]) > endNs, throw a RangeError exception.
  17. Set norm to NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, relativeResult.[[EpochNanoseconds]]).
  18. Let oneDayFarther be ? AddDaysToZonedDateTime(relativeResult.[[Instant]], relativeResult.[[DateTime]], timeZoneRec, zonedRelativeTo.[[Calendar]], sign).
  19. Let dayLengthNs be NormalizedTimeDurationFromEpochNanosecondsDifference(oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]).
  20. Let oneDayLess be ! SubtractNormalizedTimeDuration(norm, dayLengthNs).
  21. If NormalizedTimeDurationSign(oneDayLess) × sign ≥ 0, then
    1. Set norm to oneDayLess.
    2. Set relativeResult to oneDayFarther.
    3. Set days to days + sign.
    4. Set oneDayFarther to ? AddDaysToZonedDateTime(relativeResult.[[Instant]], relativeResult.[[DateTime]], timeZoneRec, zonedRelativeTo.[[Calendar]], sign).
    5. Set dayLengthNs to NormalizedTimeDurationFromEpochNanosecondsDifference(oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]).
    6. If NormalizedTimeDurationSign(! SubtractNormalizedTimeDuration(norm, dayLengthNs)) × sign ≥ 0, then
      1. Throw a RangeError exception.
  22. If days < 0 and sign = 1, throw a RangeError exception.
  23. If days > 0 and sign = -1, throw a RangeError exception.
  24. If sign = -1, then
    1. If NormalizedTimeDurationSign(norm) = 1, throw a RangeError exception.
  25. Else,
    1. Assert: NormalizedTimeDurationSign(norm) ≥ 0.
  26. Assert: CompareNormalizedTimeDuration(NormalizedTimeDurationAbs(norm), NormalizedTimeDurationAbs(dayLengthNs)) = -1.
  27. Let dayLength be abs((dayLengthNs.[[TotalNanoseconds]])).
  28. If dayLength ≥ 253, throw a RangeError exception.
  29. Assert: abs(days) < 253 / (HoursPerDay × MinutesPerHour × SecondsPerMinute).
  30. Return the Record { [[Days]]: days, [[Remainder]]: norm, [[DayLength]]: dayLength  }.

6.5.9 DifferenceTemporalZonedDateTime ( operation, zonedDateTime, other, options )

The abstract operation DifferenceTemporalZonedDateTime takes arguments operation (until or since), zonedDateTime (a Temporal.ZonedDateTime), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by zonedDateTime and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalZonedDateTime(other).
  3. If ? CalendarEquals(zonedDateTime.[[Calendar]], other.[[Calendar]]) is false, then
    1. Throw a RangeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, datetime, « », "nanosecond", "hour").
  6. If settings.[[LargestUnit]] is not one of "year", "month", "week", or "day", then
    1. Let norm be DifferenceInstant(zonedDateTime.[[Nanoseconds]], other.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
    2. Let result be BalanceTimeDuration(norm, settings.[[LargestUnit]]).
    3. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]).
  7. NOTE: To calculate differences in two different time zones, settings.[[LargestUnit]] must be "hour" or smaller, because day lengths can vary between time zones due to DST and other UTC offset shifts.
  8. If ? TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, then
    1. Throw a RangeError exception.
  9. If zonedDateTime.[[Nanoseconds]] = other.[[Nanoseconds]], then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  10. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  11. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « date-add, date-until »).
  12. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  13. Let precalculatedPlainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
  14. Let plainRelativeTo be ! CreateTemporalDate(precalculatedPlainDateTime.[[ISOYear]], precalculatedPlainDateTime.[[ISOMonth]], precalculatedPlainDateTime.[[ISODay]], calendarRec.[[Receiver]]).
  15. Let result be ? DifferenceZonedDateTime(zonedDateTime.[[Nanoseconds]], other.[[Nanoseconds]], timeZoneRec, calendarRec, settings.[[LargestUnit]], resolvedOptions, precalculatedPlainDateTime).
  16. If settings.[[SmallestUnit]] is "nanosecond" and settings.[[RoundingIncrement]] is 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
  17. If roundingGranularityIsNoop is false, then
    1. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[NormalizedTime]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], plainRelativeTo, calendarRec, zonedDateTime, timeZoneRec, precalculatedPlainDateTime).
    2. Let roundResult be roundRecord.[[NormalizedDuration]].
    3. Let daysResult be ! NormalizedTimeDurationToDays(roundResult.[[NormalizedTime]], zonedDateTime, timeZoneRec).
    4. Let days be roundResult.[[Days]] + daysResult.[[Days]].
    5. Let adjustResult be ? AdjustRoundedDurationDays(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], days, daysResult.[[NormalizedTime]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], zonedDateTime, calendarRec, timeZoneRec, precalculatedPlainDateTime).
    6. Let balanceResult be ? BalanceDateDurationRelative(adjustResult.[[Years]], adjustResult.[[Months]], adjustResult.[[Weeks]], adjustResult.[[Days]], settings.[[LargestUnit]], settings.[[SmallestUnit]], plainRelativeTo, calendarRec).
    7. Set result to ? CombineDateAndNormalizedTimeDuration(balanceResult, adjustResult.[[NormalizedTime]]).
  18. Let timeResult be BalanceTimeDuration(result.[[NormalizedTime]], "hour").
  19. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], sign × result.[[Weeks]], sign × result.[[Days]], sign × timeResult.[[Hours]], sign × timeResult.[[Minutes]], sign × timeResult.[[Seconds]], sign × timeResult.[[Milliseconds]], sign × timeResult.[[Microseconds]], sign × timeResult.[[Nanoseconds]]).

6.5.10 AddDurationToOrSubtractDurationFromZonedDateTime ( operation, zonedDateTime, temporalDurationLike, options )

The abstract operation AddDurationToOrSubtractDurationFromZonedDateTime takes arguments operation (add or subtract), zonedDateTime (a Temporal.ZonedDateTime), temporalDurationLike (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.ZonedDateTime or an abrupt completion. It adds/subtracts temporalDurationLike to/from zonedDateTime. It performs the following steps when called:

  1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
  2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
  3. Set options to ? GetOptionsObject(options).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(zonedDateTime.[[Calendar]], « date-add »).
  6. Let norm be NormalizeTimeDuration(sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
  7. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZoneRec, calendarRec, sign × duration.[[Years]], sign × duration.[[Months]], sign × duration.[[Weeks]], sign × duration.[[Days]], norm, undefined, options).
  8. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZoneRec.[[Receiver]], calendarRec.[[Receiver]]).

7 Temporal.Duration Objects

A Temporal.Duration object describes the difference in elapsed time between two other Temporal objects of the same type: Instant, PlainDate, PlainDateTime, PlainTime, PlainYearMonth, or ZonedDateTime. Objects of this type are only created via the .since() and .until() methods of these objects.

7.1 The Temporal.Duration Constructor

The Temporal.Duration constructor:

  • creates and initializes a new Temporal.Duration object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.Duration behaviour must include a super call to the %Temporal.Duration% constructor to create and initialize subclass instances with the necessary internal slots.

7.1.1 Temporal.Duration ( [ years [ , months [ , weeks [ , days [ , hours [ , minutes [ , seconds [ , milliseconds [ , microseconds [ , nanoseconds ] ] ] ] ] ] ] ] ] ] )

The Temporal.Duration function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If years is undefined, let y be 0; else let y be ? ToIntegerIfIntegral(years).
  3. If months is undefined, let mo be 0; else let mo be ? ToIntegerIfIntegral(months).
  4. If weeks is undefined, let w be 0; else let w be ? ToIntegerIfIntegral(weeks).
  5. If days is undefined, let d be 0; else let d be ? ToIntegerIfIntegral(days).
  6. If hours is undefined, let h be 0; else let h be ? ToIntegerIfIntegral(hours).
  7. If minutes is undefined, let m be 0; else let m be ? ToIntegerIfIntegral(minutes).
  8. If seconds is undefined, let s be 0; else let s be ? ToIntegerIfIntegral(seconds).
  9. If milliseconds is undefined, let ms be 0; else let ms be ? ToIntegerIfIntegral(milliseconds).
  10. If microseconds is undefined, let mis be 0; else let mis be ? ToIntegerIfIntegral(microseconds).
  11. If nanoseconds is undefined, let ns be 0; else let ns be ? ToIntegerIfIntegral(nanoseconds).
  12. Return ? CreateTemporalDuration(y, mo, w, d, h, m, s, ms, mis, ns, NewTarget).

7.2 Properties of the Temporal.Duration Constructor

The value of the [[Prototype]] internal slot of the Temporal.Duration constructor is the intrinsic object %Function.prototype%.

The Temporal.Duration constructor has the following properties:

7.2.1 Temporal.Duration.prototype

The initial value of Temporal.Duration.prototype is %Temporal.Duration.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

7.2.2 Temporal.Duration.from ( item )

The Temporal.Duration.from function performs the following steps when called:

  1. If Type(item) is Object and item has an [[InitializedTemporalDuration]] internal slot, then
    1. Return ! CreateTemporalDuration(item.[[Years]], item.[[Months]], item.[[Weeks]], item.[[Days]], item.[[Hours]], item.[[Minutes]], item.[[Seconds]], item.[[Milliseconds]], item.[[Microseconds]], item.[[Nanoseconds]]).
  2. Return ? ToTemporalDuration(item).

7.2.3 Temporal.Duration.compare ( one, two [ , options ] )

The Temporal.Duration.compare function performs the following steps when called:

  1. Set one to ? ToTemporalDuration(one).
  2. Set two to ? ToTemporalDuration(two).
  3. Set options to ? GetOptionsObject(options).
  4. If one.[[Years]] = two.[[Years]], and one.[[Months]] = two.[[Months]], and one.[[Weeks]] = two.[[Weeks]], and one.[[Days]] = two.[[Days]], and one.[[Hours]] = two.[[Hours]], and one.[[Minutes]] = two.[[Minutes]], and one.[[Seconds]] = two.[[Seconds]], and one.[[Millieconds]] = two.[[Millieconds]], and one.[[Microseconds]] = two.[[Microseconds]], and one.[[Nanoseconds]] = two.[[Nanoseconds]], then
    1. Return +0𝔽.
  5. Let relativeToRecord be ? ToRelativeTemporalObject(options).
  6. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  7. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  8. Let timeZoneRec be relativeToRecord.[[TimeZoneRec]].
  9. Let calendarUnitsPresent be false.
  10. If one.[[Years]] ≠ 0, or two.[[Years]] ≠ 0, or one.[[Months]] ≠ 0, or two.[[Months]] ≠ 0, or one.[[Weeks]] ≠ 0, or two.[[Weeks]] ≠ 0, set calendarUnitsPresent to true.
  11. Let calendarRec be ? CreateCalendarMethodsRecordFromRelativeTo(plainRelativeTo, zonedRelativeTo, « date-add »).
  12. If zonedRelativeTo is not undefined, and either calendarUnitsPresent is true, or one.[[Days]] ≠ 0, or two.[[Days]] ≠ 0, then
    1. Let instant be ! CreateTemporalInstant(zonedRelativeTo.[[Nanoseconds]]).
    2. Let precalculatedPlainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendarRec.[[Receiver]]).
    3. Let norm1 be NormalizeTimeDuration(one.[[Hours]], one.[[Minutes]], one.[[Seconds]], one.[[Milliseconds]], one.[[Microseconds]], one.[[Nanoseconds]]).
    4. Let norm2 be NormalizeTimeDuration(two.[[Hours]], two.[[Minutes]], two.[[Seconds]], two.[[Milliseconds]], two.[[Microseconds]], two.[[Nanoseconds]]).
    5. Let after1 be ? AddZonedDateTime(zonedRelativeTo.[[Nanoseconds]], timeZoneRec, calendarRec, one.[[Years]], one.[[Months]], one.[[Weeks]], one.[[Days]], norm1, precalculatedPlainDateTime).
    6. Let after2 be ? AddZonedDateTime(zonedRelativeTo.[[Nanoseconds]], timeZoneRec, calendarRec, two.[[Years]], two.[[Months]], two.[[Weeks]], two.[[Days]], norm2, precalculatedPlainDateTime).
    7. If after1 > after2, return 1𝔽.
    8. If after1 < after2, return -1𝔽.
    9. Return +0𝔽.
  13. If calendarUnitsPresent is true, then
    1. Let unbalanceResult1 be ? UnbalanceDateDurationRelative(one.[[Years]], one.[[Months]], one.[[Weeks]], one.[[Days]], "day", plainRelativeTo, calendarRec).
    2. Let unbalanceResult2 be ? UnbalanceDateDurationRelative(two.[[Years]], two.[[Months]], two.[[Weeks]], two.[[Days]], "day", plainRelativeTo, calendarRec).
    3. Let days1 be unbalanceResult1.[[Days]].
    4. Let days2 be unbalanceResult2.[[Days]].
  14. Else,
    1. Let days1 be one.[[Days]].
    2. Let days2 be two.[[Days]].
  15. Let norm1 be NormalizeTimeDuration(one.[[Hours]], one.[[Minutes]], one.[[Seconds]], one.[[Milliseconds]], one.[[Microseconds]], one.[[Nanoseconds]]).
  16. Set norm1 to ? Add24HourDaysToNormalizedTimeDuration(norm1, days1).
  17. Let norm2 be NormalizeTimeDuration(two.[[Hours]], two.[[Minutes]], two.[[Seconds]], two.[[Milliseconds]], two.[[Microseconds]], two.[[Nanoseconds]]).
  18. Set norm2 to ? Add24HourDaysToNormalizedTimeDuration(norm2, days2).
  19. Return 𝔽(CompareNormalizedTimeDuration(norm1, norm2)).

7.3 Properties of the Temporal.Duration Prototype Object

The Temporal.Duration prototype object

  • is itself an ordinary object.
  • is not a Temporal.Duration instance and doesn't have an [[InitializedTemporalDuration]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.

7.3.1 Temporal.Duration.prototype.constructor

The initial value of Temporal.Duration.prototype.constructor is %Temporal.Duration%.

7.3.2 Temporal.Duration.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.Duration".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

7.3.3 get Temporal.Duration.prototype.years

Temporal.Duration.prototype.years is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Years]]).

7.3.4 get Temporal.Duration.prototype.months

Temporal.Duration.prototype.months is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Months]]).

7.3.5 get Temporal.Duration.prototype.weeks

Temporal.Duration.prototype.weeks is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Weeks]]).

7.3.6 get Temporal.Duration.prototype.days

Temporal.Duration.prototype.days is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Days]]).

7.3.7 get Temporal.Duration.prototype.hours

Temporal.Duration.prototype.hours is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Hours]]).

7.3.8 get Temporal.Duration.prototype.minutes

Temporal.Duration.prototype.minutes is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Minutes]]).

7.3.9 get Temporal.Duration.prototype.seconds

Temporal.Duration.prototype.seconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Seconds]]).

7.3.10 get Temporal.Duration.prototype.milliseconds

Temporal.Duration.prototype.milliseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Milliseconds]]).

7.3.11 get Temporal.Duration.prototype.microseconds

Temporal.Duration.prototype.microseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Microseconds]]).

7.3.12 get Temporal.Duration.prototype.nanoseconds

Temporal.Duration.prototype.nanoseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(duration.[[Nanoseconds]]).

7.3.13 get Temporal.Duration.prototype.sign

Temporal.Duration.prototype.sign is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return 𝔽(! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]])).

7.3.14 get Temporal.Duration.prototype.blank

Temporal.Duration.prototype.blank is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  4. If sign = 0, return true.
  5. Return false.

7.3.15 Temporal.Duration.prototype.with ( temporalDurationLike )

The Temporal.Duration.prototype.with method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let temporalDurationLike be ? ToTemporalPartialDurationRecord(temporalDurationLike).
  4. If temporalDurationLike.[[Years]] is not undefined, then
    1. Let years be temporalDurationLike.[[Years]].
  5. Else,
    1. Let years be duration.[[Years]].
  6. If temporalDurationLike.[[Months]] is not undefined, then
    1. Let months be temporalDurationLike.[[Months]].
  7. Else,
    1. Let months be duration.[[Months]].
  8. If temporalDurationLike.[[Weeks]] is not undefined, then
    1. Let weeks be temporalDurationLike.[[Weeks]].
  9. Else,
    1. Let weeks be duration.[[Weeks]].
  10. If temporalDurationLike.[[Days]] is not undefined, then
    1. Let days be temporalDurationLike.[[Days]].
  11. Else,
    1. Let days be duration.[[Days]].
  12. If temporalDurationLike.[[Hours]] is not undefined, then
    1. Let hours be temporalDurationLike.[[Hours]].
  13. Else,
    1. Let hours be duration.[[Hours]].
  14. If temporalDurationLike.[[Minutes]] is not undefined, then
    1. Let minutes be temporalDurationLike.[[Minutes]].
  15. Else,
    1. Let minutes be duration.[[Minutes]].
  16. If temporalDurationLike.[[Seconds]] is not undefined, then
    1. Let seconds be temporalDurationLike.[[Seconds]].
  17. Else,
    1. Let seconds be duration.[[Seconds]].
  18. If temporalDurationLike.[[Milliseconds]] is not undefined, then
    1. Let milliseconds be temporalDurationLike.[[Milliseconds]].
  19. Else,
    1. Let milliseconds be duration.[[Milliseconds]].
  20. If temporalDurationLike.[[Microseconds]] is not undefined, then
    1. Let microseconds be temporalDurationLike.[[Microseconds]].
  21. Else,
    1. Let microseconds be duration.[[Microseconds]].
  22. If temporalDurationLike.[[Nanoseconds]] is not undefined, then
    1. Let nanoseconds be temporalDurationLike.[[Nanoseconds]].
  23. Else,
    1. Let nanoseconds be duration.[[Nanoseconds]].
  24. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).

7.3.16 Temporal.Duration.prototype.negated ( )

The Temporal.Duration.prototype.negated method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return ! CreateNegatedTemporalDuration(duration).

7.3.17 Temporal.Duration.prototype.abs ( )

The Temporal.Duration.prototype.abs method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return ! CreateTemporalDuration(abs(duration.[[Years]]), abs(duration.[[Months]]), abs(duration.[[Weeks]]), abs(duration.[[Days]]), abs(duration.[[Hours]]), abs(duration.[[Minutes]]), abs(duration.[[Seconds]]), abs(duration.[[Milliseconds]]), abs(duration.[[Microseconds]]), abs(duration.[[Nanoseconds]])).

7.3.18 Temporal.Duration.prototype.add ( other [ , options ] )

The Temporal.Duration.prototype.add method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return ? AddDurationToOrSubtractDurationFromDuration(add, duration, other, options).

7.3.19 Temporal.Duration.prototype.subtract ( other [ , options ] )

The Temporal.Duration.prototype.subtract method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return ? AddDurationToOrSubtractDurationFromDuration(subtract, duration, other, options).

7.3.20 Temporal.Duration.prototype.round ( roundTo )

The Temporal.Duration.prototype.round method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. If roundTo is undefined, then
    1. Throw a TypeError exception.
  4. If Type(roundTo) is String, then
    1. Let paramString be roundTo.
    2. Set roundTo to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
  5. Else,
    1. Set roundTo to ? GetOptionsObject(roundTo).
  6. Let smallestUnitPresent be true.
  7. Let largestUnitPresent be true.
  8. NOTE: The following steps read options and perform independent validation in alphabetical order (ToRelativeTemporalObject reads "relativeTo", ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  9. Let largestUnit be ? GetTemporalUnit(roundTo, "largestUnit", datetime, undefined, « "auto" »).
  10. Let relativeToRecord be ? ToRelativeTemporalObject(roundTo).
  11. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  12. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  13. Let timeZoneRec be relativeToRecord.[[TimeZoneRec]].
  14. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
  15. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
  16. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", datetime, undefined).
  17. If smallestUnit is undefined, then
    1. Set smallestUnitPresent to false.
    2. Set smallestUnit to "nanosecond".
  18. Let existingLargestUnit be ! DefaultTemporalLargestUnit(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]]).
  19. Let defaultLargestUnit be LargerOfTwoTemporalUnits(existingLargestUnit, smallestUnit).
  20. If largestUnit is undefined, then
    1. Set largestUnitPresent to false.
    2. Set largestUnit to defaultLargestUnit.
  21. Else if largestUnit is "auto", then
    1. Set largestUnit to defaultLargestUnit.
  22. If smallestUnitPresent is false and largestUnitPresent is false, then
    1. Throw a RangeError exception.
  23. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
  24. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  25. If maximum is not undefined, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  26. Let hoursToDaysConversionMayOccur be false.
  27. If duration.[[Days]] ≠ 0 and zonedRelativeTo is not undefined, set hoursToDaysConversionMayOccur to true.
  28. Else if abs(duration.[[Hours]]) ≥ 24, set hoursToDaysConversionMayOccur to true.
  29. If smallestUnit is "nanosecond" and roundingIncrement = 1, let roundingGranularityIsNoop be true; else let roundingGranularityIsNoop be false.
  30. If duration.[[Years]] = 0 and duration.[[Months]] = 0 and duration.[[Weeks]] = 0, let calendarUnitsPresent be false; else let calendarUnitsPresent be true.
  31. If roundingGranularityIsNoop is true, and largestUnit is existingLargestUnit, and calendarUnitsPresent is false, and hoursToDaysConversionMayOccur is false, and abs(duration.[[Minutes]]) < 60, and abs(duration.[[Seconds]]) < 60, and abs(duration.[[Milliseconds]]) < 1000, and abs(duration.[[Microseconds]]) < 1000, and abs(duration.[[Nanoseconds]]) < 1000, then
    1. NOTE: The above conditions mean that the operation will have no effect: the smallest unit and rounding increment will leave the total duration unchanged, and it can be determined without calling a calendar or time zone method that no balancing will take place.
    2. Return ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  32. Let precalculatedPlainDateTime be undefined.
  33. If roundingGranularityIsNoop is false, or IsCalendarUnit(largestUnit) is true, or largestUnit is "day", or calendarUnitsPresent is true, or duration.[[Days]] ≠ 0, let plainDateTimeOrRelativeToWillBeUsed be true; else let plainDateTimeOrRelativeToWillBeUsed be false.
  34. If zonedRelativeTo is not undefined and plainDateTimeOrRelativeToWillBeUsed is true, then
    1. NOTE: The above conditions mean that the corresponding Temporal.PlainDateTime or Temporal.PlainDate for zonedRelativeTo will be used in one of the operations below.
    2. Let instant be ! CreateTemporalInstant(zonedRelativeTo.[[Nanoseconds]]).
    3. Set precalculatedPlainDateTime to ? GetPlainDateTimeFor(timeZoneRec, instant, zonedRelativeTo.[[Calendar]]).
    4. Set plainRelativeTo to ! CreateTemporalDate(precalculatedPlainDateTime.[[ISOYear]], precalculatedPlainDateTime.[[ISOMonth]], precalculatedPlainDateTime.[[ISODay]], zonedRelativeTo.[[Calendar]]).
  35. Let calendarRec be ? CreateCalendarMethodsRecordFromRelativeTo(plainRelativeTo, zonedRelativeTo, « date-add, date-until »).
  36. Let unbalanceResult be ? UnbalanceDateDurationRelative(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], largestUnit, plainRelativeTo, calendarRec).
  37. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  38. Let roundRecord be ? RoundDuration(unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], unbalanceResult.[[Days]], norm, roundingIncrement, smallestUnit, roundingMode, plainRelativeTo, calendarRec, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
  39. Let roundResult be roundRecord.[[NormalizedDuration]].
  40. If zonedRelativeTo is not undefined, then
    1. Set roundResult to ? AdjustRoundedDurationDays(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], roundResult.[[Days]], roundResult.[[NormalizedTime]], roundingIncrement, smallestUnit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, precalculatedPlainDateTime).
    2. Let balanceResult be ? BalanceTimeDurationRelative(roundResult.[[Days]], roundResult.[[NormalizedTime]], largestUnit, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
  41. Else,
    1. Let normWithDays be ? Add24HourDaysToNormalizedTimeDuration(roundResult.[[NormalizedTime]], roundResult.[[Days]]).
    2. Let balanceResult be BalanceTimeDuration(normWithDays, largestUnit).
  42. Let result be ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], roundResult.[[Weeks]], balanceResult.[[Days]], largestUnit, smallestUnit, plainRelativeTo, calendarRec).
  43. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], balanceResult.[[Hours]], balanceResult.[[Minutes]], balanceResult.[[Seconds]], balanceResult.[[Milliseconds]], balanceResult.[[Microseconds]], balanceResult.[[Nanoseconds]]).

7.3.21 Temporal.Duration.prototype.total ( totalOf )

The Temporal.Duration.prototype.total method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. If totalOf is undefined, throw a TypeError exception.
  4. If Type(totalOf) is String, then
    1. Let paramString be totalOf.
    2. Set totalOf to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(totalOf, "unit", paramString).
  5. Else,
    1. Set totalOf to ? GetOptionsObject(totalOf).
  6. NOTE: The following steps read options and perform independent validation in alphabetical order (ToRelativeTemporalObject reads "relativeTo").
  7. Let relativeToRecord be ? ToRelativeTemporalObject(totalOf).
  8. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  9. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  10. Let timeZoneRec be relativeToRecord.[[TimeZoneRec]].
  11. Let unit be ? GetTemporalUnit(totalOf, "unit", datetime, required).
  12. Let precalculatedPlainDateTime be undefined.
  13. If IsCalendarUnit(unit) is true, or unit is "day", or duration.[[Years]] ≠ 0, or duration.[[Months]] ≠ 0, or duration.[[Weeks]] ≠ 0, or duration.[[Days]] ≠ 0, let plainDateTimeOrRelativeToWillBeUsed be true; else let plainDateTimeOrRelativeToWillBeUsed be false.
  14. If zonedRelativeTo is not undefined and plainDateTimeOrRelativeToWillBeUsed is true, then
    1. NOTE: The above conditions mean that the corresponding Temporal.PlainDateTime or Temporal.PlainDate for zonedRelativeTo will be used in one of the operations below.
    2. Let instant be ! CreateTemporalInstant(zonedRelativeTo.[[Nanoseconds]]).
    3. Set precalculatedPlainDateTime to ? GetPlainDateTimeFor(timeZoneRec, instant, zonedRelativeTo.[[Calendar]]).
    4. Set plainRelativeTo to ! CreateTemporalDate(precalculatedPlainDateTime.[[ISOYear]], precalculatedPlainDateTime.[[ISOMonth]], precalculatedPlainDateTime.[[ISODay]], zonedRelativeTo.[[Calendar]]).
  15. Let calendarRec be ? CreateCalendarMethodsRecordFromRelativeTo(plainRelativeTo, zonedRelativeTo, « date-add, date-until »).
  16. Let unbalanceResult be ? UnbalanceDateDurationRelative(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], unit, plainRelativeTo, calendarRec).
  17. Let days be unbalanceResult.[[Days]].
  18. If zonedRelativeTo is not undefined, then
    1. Let intermediate be ? MoveRelativeZonedDateTime(zonedRelativeTo, calendarRec, timeZoneRec, unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], 0, precalculatedPlainDateTime).
    2. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
    3. Let startNs be intermediate.[[Nanoseconds]].
    4. Let startInstant be ! CreateTemporalInstant(startNs).
    5. Let startDateTime be undefined.
    6. If days ≠ 0, then
      1. Set startDateTime to ? GetPlainDateTimeFor(timeZoneRec, startInstant, "iso8601").
      2. Let addResult be ? AddDaysToZonedDateTime(startInstant, startDateTime, timeZoneRec, "iso8601", days).
      3. Let intermediateNs be addResult.[[EpochNanoseconds]].
    7. Else,
      1. Let intermediateNs be startNs.
    8. Let endNs be ? AddInstant(intermediateNs, norm).
    9. Set norm to NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, startNs).
    10. If IsCalendarUnit(unit) is true or unit is "day", then
      1. If NormalizedTimeDurationIsZero(norm) is false and startDateTime is undefined, set startDateTime to ? GetPlainDateTimeFor(timeZoneRec, startInstant, "iso8601").
      2. Let result be ? NormalizedTimeDurationToDays(norm, intermediate, timeZoneRec, startDateTime).
      3. Set norm to result.[[Remainder]].
      4. Set days to result.[[Days]].
    11. Else,
      1. Set days to 0.
  19. Else,
    1. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
    2. Set norm to ? Add24HourDaysToNormalizedTimeDuration(norm, days).
    3. Set days to 0.
  20. Let roundRecord be ? RoundDuration(unbalanceResult.[[Years]], unbalanceResult.[[Months]], unbalanceResult.[[Weeks]], days, norm, 1, unit, "trunc", plainRelativeTo, calendarRec, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
  21. Return 𝔽(roundRecord.[[Total]]).

7.3.22 Temporal.Duration.prototype.toString ( [ options ] )

The Temporal.Duration.prototype.toString method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Set options to ? GetOptionsObject(options).
  4. NOTE: The following steps read options and perform independent validation in alphabetical order (ToFractionalSecondDigits reads "fractionalSecondDigits" and ToTemporalRoundingMode reads "roundingMode").
  5. Let digits be ? ToFractionalSecondDigits(options).
  6. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  7. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", time, undefined).
  8. If smallestUnit is "hour" or "minute", throw a RangeError exception.
  9. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  10. If precision.[[Unit]] is not "nanosecond" or precision.[[Increment]] ≠ 1, then
    1. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
    2. Let largestUnit be DefaultTemporalLargestUnit(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]]).
    3. Let roundRecord be ? RoundDuration(0, 0, 0, 0, norm, precision.[[Increment]], precision.[[Unit]], roundingMode).
    4. Set norm to roundRecord.[[NormalizedDuration]].[[NormalizedTime]].
    5. Let result be BalanceTimeDuration(norm, LargerOfTwoTemporalUnits(largestUnit, "second")).
    6. Set result to CreateDurationRecord(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]] + result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
  11. Else,
    1. Let result be duration.
  12. Let normSeconds be NormalizeTimeDuration(0, 0, result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
  13. Return ! TemporalDurationToString(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], normSeconds, precision.[[Precision]]).

7.3.23 Temporal.Duration.prototype.toJSON ( )

The Temporal.Duration.prototype.toJSON method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let normSeconds be NormalizeTimeDuration(0, 0, duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  4. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], normSeconds, "auto").

7.3.24 Temporal.Duration.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Duration.prototype.toLocaleString method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of the Temporal.Duration.prototype.toLocaleString method is used.

The Temporal.Duration.prototype.toLocaleString method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let normSeconds be NormalizeTimeDuration(0, 0, duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  4. Return ! TemporalDurationToString(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], normSeconds, "auto").

7.3.25 Temporal.Duration.prototype.valueOf ( )

The Temporal.Duration.prototype.valueOf method performs the following steps when called:

  1. Throw a TypeError exception.

7.4 Properties of Temporal.Duration Instances

Temporal.Duration instances are ordinary objects that inherit properties from the %Temporal.Duration.prototype% intrinsic object. Temporal.Duration instances are initially created with the internal slots described in Table 9.

A float64-representable integer is an integer that is exactly representable as a Number value. That is, for a float64-representable integer x, it must hold that (𝔽(x)) = x.

Note
The use of float64-representable integers here is intended so that implementations can store and do arithmetic on Duration fields using 64-bit floating-point values.
Table 9: Internal Slots of Temporal.Duration Instances
Internal Slot Description
[[InitializedTemporalDuration]] The only specified use of this slot is for distinguishing Temporal.Duration instances from other objects.
[[Years]] A float64-representable integer representing the number of years in the duration.
[[Months]] A float64-representable integer representing the number of months in the duration.
[[Weeks]] A float64-representable integer representing the number of weeks in the duration.
[[Days]] A float64-representable integer representing the number of days in the duration.
[[Hours]] A float64-representable integer representing the number of hours in the duration.
[[Minutes]] A float64-representable integer representing the number of minutes in the duration.
[[Seconds]] A float64-representable integer representing the number of seconds in the duration.
[[Milliseconds]] A float64-representable integer representing the number of milliseconds in the duration.
[[Microseconds]] A float64-representable integer representing the number of microseconds in the duration.
[[Nanoseconds]] A float64-representable integer representing the number of nanoseconds in the duration.

7.5 Abstract Operations

7.5.1 Duration Records

A Duration Record is a Record value used to represent a Temporal.Duration object. Duration Records are produced by the abstract operation CreateDurationRecord, among others.

Duration Records have the fields listed in Table 10.

Table 10: Duration Record Fields
Field Name Property Name Value Meaning
[[Years]] "years" a float64-representable integer The number of years in the duration.
[[Months]] "months" a float64-representable integer The number of months in the duration.
[[Weeks]] "weeks" a float64-representable integer The number of weeks in the duration.
[[Days]] "days" a float64-representable integer The number of days in the duration.
[[Hours]] "hours" a float64-representable integer The number of hours in the duration.
[[Minutes]] "minutes" a float64-representable integer The number of minutes in the duration.
[[Seconds]] "seconds" a float64-representable integer The number of seconds in the duration.
[[Milliseconds]] "milliseconds" a float64-representable integer The number of milliseconds in the duration.
[[Microseconds]] "microseconds" a float64-representable integer The number of microseconds in the duration.
[[Nanoseconds]] "nanoseconds" a float64-representable integer The number of nanoseconds in the duration.

7.5.2 Date Duration Records

A Date Duration Record is a Record value used to represent the portion of a Temporal.Duration object that deals with calendar date units. Date Duration Records are produced by the abstract operation CreateDateDurationRecord, among others.

Of the fields listed in Table 10, Date Duration Records have [[Years]], [[Months]], [[Weeks]], and [[Days]].

7.5.3 Time Duration Records

A Time Duration Record is a Record value used to represent the portion of a Temporal.Duration object that deals with exact time units. Time Duration Records are produced by the abstract operation CreateTimeDurationRecord, among others.

Of the fields listed in Table 10, Time Duration Records have [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], and [[Nanoseconds]].

7.5.4 Partial Duration Records

A partial Duration Record is a Record value used to represent a portion of a Temporal.Duration object, in which it is not required that all the fields be specified.

Partial Duration Records have the same fields listed in Table 10. Unlike Duration Records, each field of a partial Duration Record may also have the value undefined as long as there is at least one field that is not undefined.

7.5.5 Normalized Time Duration Records

A Normalized Time Duration Record is a Record value used to represent the portion of a Temporal.Duration object that deals with time units, but as a combined value. Normalized Time Duration Records are produced by the abstract operation NormalizeTimeDuration, among others.

Normalized Time Duration Records have the fields listed in Table 11.

Table 11: Normalized Time Duration Record Fields
Field Name Value Meaning
[[TotalNanoseconds]] an integer in the inclusive interval from -maxTimeDuration to maxTimeDuration, where maxTimeDuration = 253 × 109 - 1 = 9,007,199,254,740,991,999,999,999 The number of nanoseconds in the duration.

7.5.6 Normalized Duration Records

A Normalized Duration Record is a Record value used to represent the combination of a Date Duration Record with a Normalized Time Duration Record. Such Records are used by operations that deal with both date and time portions of durations, such as RoundDuration.

Normalized Duration Records have the fields listed in Table 12.

Table 12: Normalized Duration Record Fields
Field Name Value Meaning
[[Years]] a float64-representable integer The number of years in the duration.
[[Months]] a float64-representable integer The number of months in the duration.
[[Weeks]] a float64-representable integer The number of weeks in the duration.
[[Days]] a float64-representable integer The number of days in the duration.
[[NormalizedTime]] a Normalized Time Duration Record The time portion of the duration.

7.5.7 CreateDurationRecord ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation CreateDurationRecord takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer) and returns a Duration Record. It performs the following steps when called:

  1. Assert: ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is true.
  2. Return the Record { [[Years]]: (𝔽(years)), [[Months]]: (𝔽(months)), [[Weeks]]: (𝔽(weeks)), [[Days]]: (𝔽(days)), [[Hours]]: (𝔽(hours)), [[Minutes]]: (𝔽(minutes)), [[Seconds]]: (𝔽(seconds)), [[Milliseconds]]: (𝔽(milliseconds)), [[Microseconds]]: (𝔽(microseconds)), [[Nanoseconds]]: (𝔽(nanoseconds))  }.

7.5.8 CreateDateDurationRecord ( years, months, weeks, days )

The abstract operation CreateDateDurationRecord takes arguments years (an integer), months (an integer), weeks (an integer), and days (an integer). It returns a Date Duration Record. It performs the following steps when called:

  1. If ! IsValidDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0) is false, throw a RangeError exception.
  2. Return the Record { [[Years]]: (𝔽(years)), [[Months]]: (𝔽(months)), [[Weeks]]: (𝔽(weeks)), [[Days]]: (𝔽(days))  }.

7.5.9 CreateTimeDurationRecord ( days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation CreateTimeDurationRecord takes arguments days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer). It returns a Time Duration Record. It performs the following steps when called:

  1. Assert: ! IsValidDuration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is true.
  2. Return the Record { [[Days]]: (𝔽(days)), [[Hours]]: (𝔽(hours)), [[Minutes]]: (𝔽(minutes)), [[Seconds]]: (𝔽(seconds)), [[Milliseconds]]: (𝔽(milliseconds)), [[Microseconds]]: (𝔽(microseconds)), [[Nanoseconds]]: (𝔽(nanoseconds))  }.

7.5.10 CreateNormalizedDurationRecord ( years, months, weeks, days, norm )

The abstract operation CreateNormalizedDurationRecord takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), and norm (a Normalized Time Duration Record) and returns either a normal completion containing a Normalized Duration Record, or a throw completion. It performs the following steps when called:

  1. Let dateDurationRecord be ? CreateDateDurationRecord(years, months, weeks, days).
  2. Return ? CombineDateAndNormalizedTimeDuration(dateDurationRecord, norm).

7.5.11 CombineDateAndNormalizedTimeDuration ( dateDurationRecord, norm )

The abstract operation CombineDateAndNormalizedTimeDuration takes arguments dateDurationRecord (a Date Duration Record) and norm (a Normalized Time Duration Record) and returns either a normal completion containing a Normalized Duration Record, or a throw completion. It performs the following steps when called:

  1. Let dateSign be DurationSign(dateDurationRecord.[[Years]], dateDurationRecord.[[Months]], dateDurationRecord.[[Weeks]], dateDurationRecord.[[Days]], 0, 0, 0, 0, 0, 0).
  2. Let timeSign be NormalizedTimeDurationSign(norm).
  3. If dateSign ≠ 0 and timeSign ≠ 0 and dateSigntimeSign, throw a RangeError exception.
  4. Return the Record { [[Years]]: dateDurationRecord.[[Years]], [[Months]]: dateDurationRecord.[[Months]], [[Weeks]]: dateDurationRecord.[[Weeks]], [[Days]]: dateDurationRecord.[[Days]], [[NormalizedTime]]: norm  }.

7.5.12 ToTemporalDuration ( item )

The abstract operation ToTemporalDuration takes argument item (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration, or a throw completion. It returns its argument item if it is already a Temporal.Duration instance, converts item to a new Temporal.Duration instance if possible and returns that, and throws otherwise. It performs the following steps when called:

  1. If Type(item) is Object and item has an [[InitializedTemporalDuration]] internal slot, then
    1. Return item.
  2. Let result be ? ToTemporalDurationRecord(item).
  3. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).

7.5.13 ToTemporalDurationRecord ( temporalDurationLike )

The abstract operation ToTemporalDurationRecord takes argument temporalDurationLike (an ECMAScript language value) and returns either a normal completion containing a Duration Record, or an abrupt completion. The returned Record has its fields set according to the properties of temporalDurationLike, with absent or undefined properties corresponding to fields containing 0. It performs the following steps when called:

  1. If Type(temporalDurationLike) is not Object, then
    1. If temporalDurationLike is not a String, throw a TypeError exception.
    2. Return ? ParseTemporalDurationString(temporalDurationLike).
  2. If temporalDurationLike has an [[InitializedTemporalDuration]] internal slot, then
    1. Return CreateDurationRecord(temporalDurationLike.[[Years]], temporalDurationLike.[[Months]], temporalDurationLike.[[Weeks]], temporalDurationLike.[[Days]], temporalDurationLike.[[Hours]], temporalDurationLike.[[Minutes]], temporalDurationLike.[[Seconds]], temporalDurationLike.[[Milliseconds]], temporalDurationLike.[[Microseconds]], temporalDurationLike.[[Nanoseconds]]).
  3. Let result be a new Duration Record with each field set to 0.
  4. Let partial be ? ToTemporalPartialDurationRecord(temporalDurationLike).
  5. If partial.[[Years]] is not undefined, set result.[[Years]] to partial.[[Years]].
  6. If partial.[[Months]] is not undefined, set result.[[Months]] to partial.[[Months]].
  7. If partial.[[Weeks]] is not undefined, set result.[[Weeks]] to partial.[[Weeks]].
  8. If partial.[[Days]] is not undefined, set result.[[Days]] to partial.[[Days]].
  9. If partial.[[Hours]] is not undefined, set result.[[Hours]] to partial.[[Hours]].
  10. If partial.[[Minutes]] is not undefined, set result.[[Minutes]] to partial.[[Minutes]].
  11. If partial.[[Seconds]] is not undefined, set result.[[Seconds]] to partial.[[Seconds]].
  12. If partial.[[Milliseconds]] is not undefined, set result.[[Milliseconds]] to partial.[[Milliseconds]].
  13. If partial.[[Microseconds]] is not undefined, set result.[[Microseconds]] to partial.[[Microseconds]].
  14. If partial.[[Nanoseconds]] is not undefined, set result.[[Nanoseconds]] to partial.[[Nanoseconds]].
  15. If ! IsValidDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]) is false, then
    1. Throw a RangeError exception.
  16. Return result.

7.5.14 DurationSign ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation DurationSign takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer). It returns 1 if the most significant non-zero element in its arguments is positive, and -1 if the most significant non-zero element is negative. If all of its arguments are zero, it returns 0. It performs the following steps when called:

  1. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
    1. If v < 0, return -1.
    2. If v > 0, return 1.
  2. Return 0.

7.5.15 IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation IsValidDuration takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer). It returns true if its arguments form valid input from which to construct a Temporal.Duration, and false otherwise. It performs the following steps when called:

  1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
  2. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
    1. If 𝔽(v) is not finite, return false.
    2. If v < 0 and sign > 0, return false.
    3. If v > 0 and sign < 0, return false.
  3. If abs(years) ≥ 232, return false.
  4. If abs(months) ≥ 232, return false.
  5. If abs(weeks) ≥ 232, return false.
  6. Let normalizedSeconds be days × 86,400 + hours × 3600 + minutes × 60 + seconds + (𝔽(milliseconds)) × 10-3 + (𝔽(microseconds)) × 10-6 + (𝔽(nanoseconds)) × 10-9.
  7. NOTE: The above step cannot be implemented directly using floating-point arithmetic. Multiplying by 10-3, 10-6, and 10-9 respectively may be imprecise when milliseconds, microseconds, or nanoseconds is an unsafe integer. This multiplication can be implemented in C++ with an implementation of std::remquo() with sufficient bits in the quotient. String manipulation will also give an exact result, since the multiplication is by a power of 10.
  8. If abs(normalizedSeconds) ≥ 253, return false.
  9. Return true.

7.5.16 DefaultTemporalLargestUnit ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds )

The abstract operation DefaultTemporalLargestUnit takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), and microseconds (an integer). It implements the logic used in the Temporal.Duration.prototype.round() method and elsewhere, where the largestUnit option, if not given explicitly, is set to the largest non-zero unit in the input Temporal.Duration. It performs the following steps when called:

  1. If years ≠ 0, return "year".
  2. If months ≠ 0, return "month".
  3. If weeks ≠ 0, return "week".
  4. If days ≠ 0, return "day".
  5. If hours ≠ 0, return "hour".
  6. If minutes ≠ 0, return "minute".
  7. If seconds ≠ 0, return "second".
  8. If milliseconds ≠ 0, return "millisecond".
  9. If microseconds ≠ 0, return "microsecond".
  10. Return "nanosecond".

7.5.17 ToTemporalPartialDurationRecord ( temporalDurationLike )

The abstract operation ToTemporalPartialDurationRecord takes argument temporalDurationLike (an ECMAScript language value) and returns either a normal completion containing a partial Duration Record, or an abrupt completion. The returned Record has its fields set according to the properties of temporalDurationLike. It performs the following steps when called:

  1. If Type(temporalDurationLike) is not Object, then
    1. Throw a TypeError exception.
  2. Let result be a new partial Duration Record with each field set to undefined.
  3. NOTE: The following steps read properties and perform independent validation in alphabetical order.
  4. Let days be ? Get(temporalDurationLike, "days").
  5. If days is not undefined, set result.[[Days]] to ? ToIntegerIfIntegral(days).
  6. Let hours be ? Get(temporalDurationLike, "hours").
  7. If hours is not undefined, set result.[[Hours]] to ? ToIntegerIfIntegral(hours).
  8. Let microseconds be ? Get(temporalDurationLike, "microseconds").
  9. If microseconds is not undefined, set result.[[Microseconds]] to ? ToIntegerIfIntegral(microseconds).
  10. Let milliseconds be ? Get(temporalDurationLike, "milliseconds").
  11. If milliseconds is not undefined, set result.[[Milliseconds]] to ? ToIntegerIfIntegral(milliseconds).
  12. Let minutes be ? Get(temporalDurationLike, "minutes").
  13. If minutes is not undefined, set result.[[Minutes]] to ? ToIntegerIfIntegral(minutes).
  14. Let months be ? Get(temporalDurationLike, "months").
  15. If months is not undefined, set result.[[Months]] to ? ToIntegerIfIntegral(months).
  16. Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds").
  17. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? ToIntegerIfIntegral(nanoseconds).
  18. Let seconds be ? Get(temporalDurationLike, "seconds").
  19. If seconds is not undefined, set result.[[Seconds]] to ? ToIntegerIfIntegral(seconds).
  20. Let weeks be ? Get(temporalDurationLike, "weeks").
  21. If weeks is not undefined, set result.[[Weeks]] to ? ToIntegerIfIntegral(weeks).
  22. Let years be ? Get(temporalDurationLike, "years").
  23. If years is not undefined, set result.[[Years]] to ? ToIntegerIfIntegral(years).
  24. If years is undefined, and months is undefined, and weeks is undefined, and days is undefined, and hours is undefined, and minutes is undefined, and seconds is undefined, and milliseconds is undefined, and microseconds is undefined, and nanoseconds is undefined, throw a TypeError exception.
  25. Return result.

7.5.18 CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds [ , newTarget ] )

The abstract operation CreateTemporalDuration takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.Duration, or an abrupt completion. It creates a Temporal.Duration instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.Duration%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »).
  4. Set object.[[Years]] to (𝔽(years)).
  5. Set object.[[Months]] to (𝔽(months)).
  6. Set object.[[Weeks]] to (𝔽(weeks)).
  7. Set object.[[Days]] to (𝔽(days)).
  8. Set object.[[Hours]] to (𝔽(hours)).
  9. Set object.[[Minutes]] to (𝔽(minutes)).
  10. Set object.[[Seconds]] to (𝔽(seconds)).
  11. Set object.[[Milliseconds]] to (𝔽(milliseconds)).
  12. Set object.[[Microseconds]] to (𝔽(microseconds)).
  13. Set object.[[Nanoseconds]] to (𝔽(nanoseconds)).
  14. Return object.

7.5.19 CreateNegatedTemporalDuration ( duration )

The abstract operation CreateNegatedTemporalDuration takes argument duration (a Temporal.Duration). It returns a new Temporal.Duration instance that is the negation of duration. It performs the following steps when called:

  1. Return ! CreateTemporalDuration(-duration.[[Years]], -duration.[[Months]], -duration.[[Weeks]], -duration.[[Days]], -duration.[[Hours]], -duration.[[Minutes]], -duration.[[Seconds]], -duration.[[Milliseconds]], -duration.[[Microseconds]], -duration.[[Nanoseconds]]).

7.5.20 NormalizeTimeDuration ( hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation NormalizeTimeDuration takes arguments hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer) and returns a Normalized Time Duration Record. From the given units, it computes a normalized time duration consisting of whole seconds, and subseconds expressed in nanoseconds. The normalized time duration can be stored losslessly in two 64-bit floating point numbers. Alternatively, normalizedSeconds × 109 + subseconds can be stored as a 96-bit integer. It performs the following steps when called:

  1. Set minutes to minutes + hours × 60.
  2. Set seconds to seconds + minutes × 60.
  3. Set milliseconds to milliseconds + seconds × 1000.
  4. Set microseconds to microseconds + milliseconds × 1000.
  5. Set nanoseconds to nanoseconds + microseconds × 1000.
  6. Assert: abs(nanoseconds) ≤ maxTimeDuration.
  7. Return the Record { [[TotalNanoseconds]]: nanoseconds }.

7.5.21 NormalizedTimeDurationAbs ( d )

The abstract operation NormalizedTimeDurationAbs takes argument d (a Normalized Time Duration Record) and returns a Normalized Time Duration Record. It returns a new normalized time duration that is the absolute value of d. It performs the following steps when called:

  1. Return the Record { [[TotalNanoseconds]]: abs(d.[[TotalNanoseconds]]) }.

7.5.22 AddNormalizedTimeDuration ( one, two )

The abstract operation AddNormalizedTimeDuration takes arguments one (a Normalized Time Duration Record) and two (a Normalized Time Duration Record) and returns either a normal completion containing a Normalized Time Duration Record, or a throw completion. It returns a normalized time duration that is the sum of one and two, throwing an exception if the result is greater than the maximum normalized time duration. It performs the following steps when called:

  1. Let result be one.[[TotalNanoseconds]] + two.[[TotalNanoseconds]].
  2. If abs(result) > maxTimeDuration, throw a RangeError exception.
  3. Return the Record { [[TotalNanoseconds]]: result }.

7.5.23 Add24HourDaysToNormalizedTimeDuration ( d, days )

The abstract operation Add24HourDaysToNormalizedTimeDuration takes arguments d (a Normalized Time Duration Record) and days (an integer) and returns either a normal completion containing a Normalized Time Duration Record, or a throw completion. It returns a normalized time duration that is the sum of d and the number of 24-hour days indicated by days, throwing an exception if the result is greater than the maximum normalized time duration. This operation should not be used when adding days relative to a Temporal.ZonedDateTime, since the days may not be 24 hours long. It performs the following steps when called:

  1. Let result be d.[[TotalNanoseconds]] + days × nsPerDay.
  2. If abs(result) > maxTimeDuration, throw a RangeError exception.
  3. Return the Record { [[TotalNanoseconds]]: result }.

7.5.24 AddNormalizedTimeDurationToEpochNanoseconds ( d, epochNs )

The abstract operation AddNormalizedTimeDurationToEpochNanoseconds takes arguments d (a Normalized Time Duration Record) and epochNs (a BigInt) and returns a BigInt. It adds a normalized time duration d to an exact time in nanoseconds since the epoch, epochNs, and returns a new exact time. The returned exact time is not required to be valid according to IsValidEpochNanoseconds. It performs the following steps when called:

  1. Return epochNs + (d.[[TotalNanoseconds]]).

7.5.25 CompareNormalizedTimeDuration ( one, two )

The abstract operation CompareNormalizedTimeDuration takes arguments one (a Normalized Time Duration Record) and two (a Normalized Time Duration Record) and returns -1, 0, or 1. It performs a comparison of two Normalized Time Duration Records. It performs the following steps when called:

  1. If one.[[TotalNanoseconds]] > two.[[TotalNanoseconds]], return 1.
  2. If one.[[TotalNanoseconds]] < two.[[TotalNanoseconds]], return -1.
  3. Return 0.

7.5.26 DivideNormalizedTimeDuration ( d, divisor )

The abstract operation DivideNormalizedTimeDuration takes arguments d (a Normalized Time Duration Record) and divisor (an integer) and returns a mathematical value. It divides the total number of nanoseconds in the normalized time duration d by divisor. It performs the following steps when called:

  1. Assert: divisor ≠ 0.
  2. NOTE: The following step cannot be implemented directly using floating-point arithmetic when 𝔽(d.[[TotalNanoseconds]]) is not a safe integer. The division can be implemented in C++ with the __float128 type if the compiler supports it, or with software emulation such as in the SoftFP library.
  3. Return d.[[TotalNanoseconds]] / divisor.

7.5.27 NormalizedTimeDurationFromEpochNanosecondsDifference ( one, two )

The abstract operation NormalizedTimeDurationFromEpochNanosecondsDifference takes arguments one (a BigInt) and two (a BigInt) and returns a Normalized Time Duration Record. It creates a Normalized Time Duration Record with the difference between two exact times in nanoseconds since the epoch, which must not be greater than the maximum normalized time duration. It performs the following steps when called:

  1. Let result be (one) - (two).
  2. Assert: abs(result) ≤ maxTimeDuration.
  3. Return the Record { [[TotalNanoseconds]]: result }.

7.5.28 NormalizedTimeDurationIsZero ( d )

The abstract operation NormalizedTimeDurationIsZero takes argument d (a Normalized Time Duration Record) and returns a Boolean. It returns true if d is a zero duration, false otherwise. It performs the following steps when called:

  1. If d.[[TotalNanoseconds]] = 0, return true.
  2. Return false.

7.5.29 RoundNormalizedTimeDurationToIncrement ( d, increment, roundingMode )

The abstract operation RoundNormalizedTimeDurationToIncrement takes arguments d (a Normalized Time Duration Record), increment (an integer), and roundingMode (a String from the Identifier column of Table 19) and returns either a normal completion containing a Normalized Time Duration Record, or a throw completion. It rounds the total number of nanoseconds in the normalized time duration d to the nearest multiple of increment, up or down according to roundingMode. It performs the following steps when called:

  1. Let rounded be RoundNumberToIncrement(d.[[TotalNanoseconds]], increment, roundingMode).
  2. If abs(rounded) > maxTimeDuration, throw a RangeError exception.
  3. Return the Record { [[TotalNanoseconds]]: rounded }.

7.5.30 NormalizedTimeDurationSeconds ( d )

The abstract operation NormalizedTimeDurationSeconds takes argument d (a Normalized Time Duration Record) and returns an integer in the interval from -253 (exclusive) to 253 (exclusive). It returns the integer number of seconds in d. It performs the following steps when called:

  1. Return truncate(d.[[TotalNanoseconds]] / 109).

7.5.31 NormalizedTimeDurationSign ( d )

The abstract operation NormalizedTimeDurationSign takes argument d (a Normalized Time Duration Record) and returns -1, 0, or 1. It returns 0 if the duration is zero, or ±1 depending on the sign of the duration. It performs the following steps when called:

  1. If d.[[TotalNanoseconds]] < 0, return -1.
  2. If d.[[TotalNanoseconds]] > 0, return 1.
  3. Return 0.

7.5.32 NormalizedTimeDurationSubseconds ( d )

The abstract operation NormalizedTimeDurationSubseconds takes argument d (a Normalized Time Duration Record) and returns an integer in the interval from -109 (exclusive) to 109 (exclusive). It returns the integer number of nanoseconds in the subsecond part of d. It performs the following steps when called:

  1. Return remainder(d.[[TotalNanoseconds]], 109).

7.5.33 SubtractNormalizedTimeDuration ( one, two )

The abstract operation SubtractNormalizedTimeDuration takes arguments one (a Normalized Time Duration Record) and two (a Normalized Time Duration Record) and returns either a normal completion containing a Normalized Time Duration Record, or a throw completion. It returns a normalized time duration that is the difference between one and two, throwing an exception if the result is greater than the maximum normalized time duration. It performs the following steps when called:

  1. Let result be one.[[TotalNanoseconds]] - two.[[TotalNanoseconds]].
  2. If abs(result) > maxTimeDuration, throw a RangeError exception.
  3. Return the Record { [[TotalNanoseconds]]: result }.

7.5.34 ZeroTimeDuration ( )

The abstract operation ZeroTimeDuration takes no arguments and returns a Normalized Time Duration Record. It returns a normalized time duration of zero length. It performs the following steps when called:

  1. Return the Record { [[TotalNanoseconds]]: 0 }.

7.5.35 BalanceTimeDuration ( norm, largestUnit )

The abstract operation BalanceTimeDuration takes arguments norm (a Normalized Time Duration Record) and largestUnit (a String) and returns a Time Duration Record. It converts a normalized time duration into a time duration with separated units, up to largestUnit. It performs the following steps when called:

  1. Let days, hours, minutes, seconds, milliseconds, and microseconds be 0.
  2. Let sign be NormalizedTimeDurationSign(norm).
  3. Let nanoseconds be NormalizedTimeDurationAbs(norm).[[TotalNanoseconds]].
  4. If largestUnit is "year", "month", "week", or "day", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
    3. Set milliseconds to floor(microseconds / 1000).
    4. Set microseconds to microseconds modulo 1000.
    5. Set seconds to floor(milliseconds / 1000).
    6. Set milliseconds to milliseconds modulo 1000.
    7. Set minutes to floor(seconds / 60).
    8. Set seconds to seconds modulo 60.
    9. Set hours to floor(minutes / 60).
    10. Set minutes to minutes modulo 60.
    11. Set days to floor(hours / 24).
    12. Set hours to hours modulo 24.
  5. Else if largestUnit is "hour", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
    3. Set milliseconds to floor(microseconds / 1000).
    4. Set microseconds to microseconds modulo 1000.
    5. Set seconds to floor(milliseconds / 1000).
    6. Set milliseconds to milliseconds modulo 1000.
    7. Set minutes to floor(seconds / 60).
    8. Set seconds to seconds modulo 60.
    9. Set hours to floor(minutes / 60).
    10. Set minutes to minutes modulo 60.
  6. Else if largestUnit is "minute", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
    3. Set milliseconds to floor(microseconds / 1000).
    4. Set microseconds to microseconds modulo 1000.
    5. Set seconds to floor(milliseconds / 1000).
    6. Set milliseconds to milliseconds modulo 1000.
    7. Set minutes to floor(seconds / 60).
    8. Set seconds to seconds modulo 60.
  7. Else if largestUnit is "second", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
    3. Set milliseconds to floor(microseconds / 1000).
    4. Set microseconds to microseconds modulo 1000.
    5. Set seconds to floor(milliseconds / 1000).
    6. Set milliseconds to milliseconds modulo 1000.
  8. Else if largestUnit is "millisecond", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
    3. Set milliseconds to floor(microseconds / 1000).
    4. Set microseconds to microseconds modulo 1000.
  9. Else if largestUnit is "microsecond", then
    1. Set microseconds to floor(nanoseconds / 1000).
    2. Set nanoseconds to nanoseconds modulo 1000.
  10. Else,
    1. Assert: largestUnit is "nanosecond".
  11. NOTE: When largestUnit is "millisecond", "microsecond", or "nanosecond", milliseconds, microseconds, or nanoseconds may be an unsafe integer. In this case, care must be taken when implementing the calculation using floating point arithmetic. It can be implemented in C++ using std::fma(). String manipulation will also give an exact result, since the multiplication is by a power of 10.
  12. Return ! CreateTimeDurationRecord(days × sign, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).

7.5.36 BalanceTimeDurationRelative ( days, norm, largestUnit, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime )

The abstract operation BalanceTimeDurationRelative takes arguments days (an integer), norm (a Normalized Time Duration Record), largestUnit (a String), zonedRelativeTo (a Temporal.ZonedDateTime), timeZoneRec (a Time Zone Methods Record), and precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and returns either a normal completion containing a Time Duration Record, or an abrupt completion. It converts the time units of a duration into a form where lower units are converted into higher units as much as possible, up to largestUnit, taking day length of zonedRelativeTo into account. If the Number value for any unit is infinite, it returns abruptly with a RangeError.

This operation observably calls time zone and calendar methods.

  1. Let startNs be zonedRelativeTo.[[Nanoseconds]].
  2. Let startInstant be ! CreateTemporalInstant(startNs).
  3. Let intermediateNs be startNs.
  4. If days ≠ 0, then
    1. If precalculatedPlainDateTime is undefined, set precalculatedPlainDateTime to ? GetPlainDateTimeFor(timeZoneRec, startInstant, "iso8601").
    2. Let intermediateResult be ? AddDaysToZonedDateTime(startInstant, precalculatedPlainDateTime, timeZoneRec, "iso8601", days).
    3. Set intermediateNs to intermediateResult.[[EpochNanoseconds]].
  5. Let endNs be ? AddInstant(intermediateNs, norm).
  6. Set norm to NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, startNs).
  7. If NormalizedTimeDurationIsZero(norm) is true, return ! CreateTimeDurationRecord(0, 0, 0, 0, 0, 0, 0).
  8. If IsCalendarUnit(largestUnit) is true or largestUnit is "day", then
    1. If precalculatedPlainDateTime is undefined, set precalculatedPlainDateTime to ? GetPlainDateTimeFor(timeZoneRec, startInstant, "iso8601").
    2. Let result be ? NormalizedTimeDurationToDays(norm, zonedRelativeTo, timeZoneRec, precalculatedPlainDateTime).
    3. Set days to result.[[Days]].
    4. Set norm to result.[[NormalizedTime]].
    5. Set largestUnit to "hour".
  9. Else,
    1. Set days to 0.
  10. Let balanceResult be BalanceTimeDuration(norm, largestUnit).
  11. Return ! CreateTimeDurationRecord(days, balanceResult.[[Hours]], balanceResult.[[Minutes]], balanceResult.[[Seconds]], balanceResult.[[Milliseconds]], balanceResult.[[Microseconds]], balanceResult.[[Nanoseconds]]).

7.5.37 UnbalanceDateDurationRelative ( years, months, weeks, days, largestUnit, plainRelativeTo, calendarRec )

The abstract operation UnbalanceDateDurationRelative takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), largestUnit (a String), plainRelativeTo (undefined or a Temporal.PlainDate), and calendarRec (undefined or a Calendar Methods Record). It converts the calendar units of a duration into a form where no unit is larger than largestUnit, and returns the result as a Date Duration Record. It performs the following steps when called:

  1. Assert: If plainRelativeTo is not undefined, calendarRec is not undefined.
  2. Let defaultLargestUnit be DefaultTemporalLargestUnit(years, months, weeks, days, 0, 0, 0, 0, 0).
  3. Let effectiveLargestUnit be LargerOfTwoTemporalUnits(largestUnit, "day").
  4. If effectiveLargestUnit is LargerOfTwoTemporalUnits(defaultLargestUnit, effectiveLargestUnit), then
    1. Return ! CreateDateDurationRecord(years, months, weeks, days).
  5. Assert: effectiveLargestUnit is not "year".
  6. If calendarRec is undefined, then
    1. Throw a RangeError exception.
  7. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-add) is true.
  8. If effectiveLargestUnit is "month", then
    1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-until) is true.
    2. Let yearsDuration be ! CreateTemporalDuration(years, 0, 0, 0, 0, 0, 0, 0, 0, 0).
    3. Let later be ? CalendarDateAdd(calendarRec, plainRelativeTo, yearsDuration).
    4. Let untilOptions be OrdinaryObjectCreate(null).
    5. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month").
    6. Let untilResult be ? CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions).
    7. Let yearsInMonths be untilResult.[[Months]].
    8. Return ? CreateDateDurationRecord(0, months + yearsInMonths, weeks, days).
  9. If effectiveLargestUnit is "week", then
    1. Let yearsMonthsDuration be ! CreateTemporalDuration(years, months, 0, 0, 0, 0, 0, 0, 0, 0).
    2. Let later be ? CalendarDateAdd(calendarRec, plainRelativeTo, yearsMonthsDuration).
    3. Let yearsMonthsInDays be DaysUntil(plainRelativeTo, later).
    4. Return ? CreateDateDurationRecord(0, 0, weeks, days + yearsMonthsInDays).
  10. NOTE: largestUnit can be any time unit as well as "day".
  11. Let yearsMonthsWeeksDuration be ! CreateTemporalDuration(years, months, weeks, 0, 0, 0, 0, 0, 0, 0).
  12. Let later be ? CalendarDateAdd(calendarRec, plainRelativeTo, yearsMonthsWeeksDuration).
  13. Let yearsMonthsWeeksInDays be DaysUntil(plainRelativeTo, later).
  14. Return ? CreateDateDurationRecord(0, 0, 0, days + yearsMonthsWeeksInDays).

7.5.38 BalanceDateDurationRelative ( years, months, weeks, days, largestUnit, smallestUnit, plainRelativeTo, calendarRec )

The abstract operation BalanceDateDurationRelative takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), largestUnit (a String), smallestUnit (a String), plainRelativeTo (undefined or a Temporal.PlainDate), and calendarRec (undefined or a Calendar Methods Record). It converts the calendar units of a duration into a form where lower units are converted into higher units as much as possible, up to largestUnit and not lower than smallestUnit, and returns the result as a Date Duration Record. It performs the following steps when called:

  1. Assert: If plainRelativeTo is not undefined, calendarRec is not undefined.
  2. Let allZero be false.
  3. If years = 0, and months = 0, and weeks = 0, and days = 0, set allZero to true.
  4. If largestUnit is not one of "year", "month", or "week", or allZero is true, then
    1. Return ! CreateDateDurationRecord(years, months, weeks, days).
  5. If plainRelativeTo is undefined, then
    1. Throw a RangeError exception.
  6. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-add) is true.
  7. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-until) is true.
  8. Let untilOptions be OrdinaryObjectCreate(null).
  9. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", largestUnit).
  10. If largestUnit is "year", then
    1. If smallestUnit is "week", then
      1. Assert: days = 0.
      2. Let yearsMonthsDuration be ! CreateTemporalDuration(years, months, 0, 0, 0, 0, 0, 0, 0, 0).
      3. Let later be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsDuration).
      4. Let untilResult be ? CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions).
      5. Return ? CreateDateDurationRecord(untilResult.[[Years]], untilResult.[[Months]], weeks, 0).
    2. Let yearsMonthsWeeksDaysDuration be ! CreateTemporalDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0).
    3. Let later be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsWeeksDaysDuration).
    4. Let untilResult be ? CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions).
    5. Return ! CreateDateDurationRecord(untilResult.[[Years]], untilResult.[[Months]], untilResult.[[Weeks]], untilResult.[[Days]]).
  11. If largestUnit is "month", then
    1. Assert: years = 0.
    2. If smallestUnit is "week", then
      1. Assert: days = 0.
      2. Return ! CreateDateDurationRecord(0, months, weeks, 0).
    3. Let monthsWeeksDaysDuration be ! CreateTemporalDuration(0, months, weeks, days, 0, 0, 0, 0, 0, 0).
    4. Let later be ? AddDate(calendarRec, plainRelativeTo, monthsWeeksDaysDuration).
    5. Let untilResult be ? CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions).
    6. Return ! CreateDateDurationRecord(0, untilResult.[[Months]], untilResult.[[Weeks]], untilResult.[[Days]]).
  12. Assert: largestUnit is "week".
  13. Assert: years = 0.
  14. Assert: months = 0.
  15. Let weeksDaysDuration be ! CreateTemporalDuration(0, 0, weeks, days, 0, 0, 0, 0, 0, 0).
  16. Let later be ? AddDate(calendarRec, plainRelativeTo, weeksDaysDuration).
  17. Let untilResult be ? CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions).
  18. Return ! CreateDateDurationRecord(0, 0, untilResult.[[Weeks]], untilResult.[[Days]]).

7.5.39 AddDuration ( y1, mon1, w1, d1, h1, min1, s1, ms1, mus1, ns1, y2, mon2, w2, d2, h2, min2, s2, ms2, mus2, ns2, plainRelativeTo, calendarRec, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] )

The abstract operation AddDuration takes arguments y1 (an integer), mon1 (an integer), w1 (an integer), d1 (an integer), h1 (an integer), min1 (an integer), s1 (an integer), ms1 (an integer), mus1 (an integer), ns1 (an integer), y2 (an integer), mon2 (an integer), w2 (an integer), d2 (an integer), h2 (an integer), min2 (an integer), s2 (an integer), ms2 (an integer), mus2 (an integer), ns2 (an integer), plainRelativeTo (a Temporal.PlainDate or undefined), calendarRec (a Calendar Methods Record or undefined), zonedRelativeTo (a Temporal.ZonedDateTime or undefined), and timeZoneRec (a Time Zone Methods Record or undefined) and optional argument precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and returns either a normal completion containing a Duration Record, or a throw completion. It adds the components of a second duration represented by y2 through ns2 to those of a first duration represented by y1 through ns1, and balances the duration relative to the given date zonedRelativeTo or plainRelativeTo, to ensure that no mixed signs remain in the result. It performs the following steps when called:

  1. Assert: If zonedRelativeTo is not undefined, or plainRelativeTo is not undefined, calendarRec is not undefined.
  2. Assert: If zonedRelativeTo is not undefined, timeZoneRec is not undefined.
  3. Let largestUnit1 be ! DefaultTemporalLargestUnit(y1, mon1, w1, d1, h1, min1, s1, ms1, mus1).
  4. Let largestUnit2 be ! DefaultTemporalLargestUnit(y2, mon2, w2, d2, h2, min2, s2, ms2, mus2).
  5. Let largestUnit be LargerOfTwoTemporalUnits(largestUnit1, largestUnit2).
  6. If zonedRelativeTo is undefined and plainRelativeTo is undefined, then
    1. If largestUnit is one of "year", "month", or "week", then
      1. Throw a RangeError exception.
    2. Let norm1 be NormalizeTimeDuration(h1, min1, s1, ms1, mus1, ns1).
    3. Let norm2 be NormalizeTimeDuration(h2, min2, s2, ms2, mus2, ns2).
    4. Let normResult be ? AddNormalizedTimeDuration(norm1, norm2).
    5. Set normResult to ? Add24HourDaysToNormalizedTimeDuration(normResult, d1 + d2).
    6. Let result be BalanceTimeDuration(normResult, largestUnit).
    7. Return CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
  7. If plainRelativeTo is not undefined, then
    1. Assert: zonedRelativeTo is undefined.
    2. Let dateDuration1 be ! CreateTemporalDuration(y1, mon1, w1, d1, 0, 0, 0, 0, 0, 0).
    3. Let dateDuration2 be ! CreateTemporalDuration(y2, mon2, w2, d2, 0, 0, 0, 0, 0, 0).
    4. Let intermediate be ? AddDate(calendarRec, plainRelativeTo, dateDuration1).
    5. Let end be ? AddDate(calendarRec, intermediate, dateDuration2).
    6. Let dateLargestUnit be LargerOfTwoTemporalUnits("day", largestUnit).
    7. Let differenceOptions be OrdinaryObjectCreate(null).
    8. Perform ! CreateDataPropertyOrThrow(differenceOptions, "largestUnit", dateLargestUnit).
    9. Let dateDifference be ? DifferenceDate(calendarRec, plainRelativeTo, end, differenceOptions).
    10. Let norm1 be NormalizeTimeDuration(h1, min1, s1, ms1, mus1, ns1).
    11. Let norm2 be NormalizeTimeDuration(h2, min2, s2, ms2, mus2, ns2).
    12. Let norm1WithDays be ? Add24HourDaysToNormalizedTimeDuration(norm1, dateDifference.[[Days]]).
    13. Let normResult be ? AddNormalizedTimeDuration(norm1WithDays, norm2).
    14. Let result be BalanceTimeDuration(normResult, largestUnit).
    15. Return CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
  8. Assert: zonedRelativeTo is not undefined.
  9. If precalculatedPlainDateTime is not present, let precalculatedPlainDateTime be undefined.
  10. If IsCalendarUnit(largestUnit) is true, or largestUnit is "day", let startDateTimeNeeded be true; else let startDateTimeNeeded be false.
  11. If precalculatedPlainDateTime is undefined and startDateTimeNeeded is true, then
    1. Let startDateTime be ? GetPlainDateTimeFor(timeZoneRec, zonedRelativeTo.[[Nanoseconds]], calendarRec.[[Receiver]]).
  12. Else,
    1. Let startDateTime be precalculatedPlainDateTime.
  13. Let norm1 be NormalizeTimeDuration(h1, min1, s1, ms1, mus1, ns1).
  14. Let norm2 be NormalizeTimeDuration(h2, min2, s2, ms2, mus2, ns2).
  15. Let intermediateNs be ? AddZonedDateTime(zonedRelativeTo.[[Nanoseconds]], timeZoneRec, calendarRec, y1, mon1, w1, d1, norm1, startDateTime).
  16. Let endNs be ? AddZonedDateTime(intermediateNs, timeZoneRec, calendarRec, y2, mon2, w2, d2, norm2).
  17. If largestUnit is not one of "year", "month", "week", or "day", then
    1. Let norm be NormalizedTimeDurationFromEpochNanosecondsDifference(endNs, zonedRelativeTo.[[Nanoseconds]]).
    2. Let result be BalanceTimeDuration(norm, largestUnit).
    3. Return CreateDurationRecord(0, 0, 0, 0, result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
  18. Let diffResult be ? DifferenceZonedDateTime(zonedRelativeTo.[[Nanoseconds]], endNs, timeZoneRec, calendarRec, largestUnit, OrdinaryObjectCreate(null), startDateTime).
  19. Let timeResult be BalanceTimeDuration(diffResult.[[NormalizedTime]], "hour").
  20. Return CreateDurationRecord(diffResult.[[Years]], diffResult.[[Months]], diffResult.[[Weeks]], diffResult.[[Days]], timeResult.[[Hours]], timeResult.[[Minutes]], timeResult.[[Seconds]], timeResult.[[Milliseconds]], timeResult.[[Microseconds]], timeResult.[[Nanoseconds]]).

7.5.40 DaysUntil ( earlier, later )

The abstract operation DaysUntil takes arguments earlier (a Temporal.PlainDate) and later (a Temporal.PlainDate) and returns an integer. The returned value is the number of days elapsed between the calendar dates of two Temporal.PlainDate instances earlier and later. If earlier is later than later, then the result is negative. It performs the following steps when called:

  1. Let epochDays1 be ISODateToEpochDays(earlier.[[ISOYear]], earlier.[[ISOMonth]] - 1, earlier.[[ISODay]]).
  2. Let epochDays2 be ISODateToEpochDays(later.[[ISOYear]], later.[[ISOMonth]] - 1, later.[[ISODay]]).
  3. Return epochDays2 - epochDays1.

7.5.41 MoveRelativeDate ( calendarRec, relativeTo, duration )

The abstract operation MoveRelativeDate takes arguments calendarRec (a Calendar Methods Record), relativeTo (a Temporal.PlainDate), and duration (a Temporal.Duration). It adds duration to relativeTo, returning a Record with a field [[RelativeTo]] (a Temporal.PlainDate) containing the result, as well as a [[Days]] field (an integer) containing the number of days added according to the calendar reckoning of calendar. This is used when balancing or rounding durations relative to a particular date. It performs the following steps when called:

  1. Let newDate be ? AddDate(calendarRec, relativeTo, duration).
  2. Let days be DaysUntil(relativeTo, newDate).
  3. Return the Record { [[RelativeTo]]: newDate, [[Days]]: days  }.

7.5.42 MoveRelativeZonedDateTime ( zonedDateTime, calendarRec, timeZoneRec, years, months, weeks, days, precalculatedPlainDateTime )

The abstract operation MoveRelativeZonedDateTime takes arguments zonedDateTime (a Temporal.ZonedDateTime), calendarRec (a Calendar Methods Record), timeZoneRec (a Time Zone Methods Record), years (an integer), months (an integer), weeks (an integer), days (an integer), and precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and returns either a normal completion containing a Temporal.ZonedDateTime, or a throw completion. It adjusts the calendar part of zonedDateTime for use as the "relative-to" parameter of another operation and returns a new Temporal.ZonedDateTime instance. It performs the following steps when called:

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  2. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-possible-instants-for) is true.
  3. Let intermediateNs be ? AddZonedDateTime(zonedDateTime.[[Nanoseconds]], timeZoneRec, calendarRec, years, months, weeks, days, ZeroTimeDuration(), precalculatedPlainDateTime).
  4. Return ! CreateTemporalZonedDateTime(intermediateNs, zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]]).

7.5.43 RoundDuration ( years, months, weeks, days, norm, increment, unit, roundingMode [ , plainRelativeTo [ , calendarRec [ , zonedRelativeTo [ , timeZoneRec [ , precalculatedPlainDateTime ] ] ] ] ] )

The abstract operation RoundDuration takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), norm (a Normalized Time Duration Record), increment (an integer), unit (a String), and roundingMode (a String from the Identifier column of Table 19) and optional arguments plainRelativeTo (undefined or a Temporal.PlainDate), calendarRec (undefined or a Calendar Methods Record), zonedRelativeTo (undefined or a Temporal.ZonedDateTime), timeZoneRec (undefined or a Time Zone Methods Record), and precalculatedPlainDateTime (undefined or a Temporal.PlainDateTime) and returns either a normal completion containing a Record with fields [[NormalizedDuration]] (a Normalized Duration Record) and [[Total]] (a mathematical value), or a throw completion. It rounds a duration (denoted by years through nanoseconds) according to the rounding parameters unit, increment, and roundingMode, and returns a Record with the Normalized Duration Record result in its [[NormalizedDuration]] field. It also returns the total of the smallest unit before the rounding operation in its [[Total]] field, for use in Temporal.Duration.prototype.total. For rounding involving calendar units, the relativeTo parameter is required. It performs the following steps when called:

  1. Assert: If either of plainRelativeTo or zonedRelativeTo are present and not undefined, calendarRec is not undefined.
  2. Assert: If zonedRelativeTo is present and not undefined, timeZoneRec is not undefined.
  3. If plainRelativeTo is not present, set plainRelativeTo to undefined.
  4. If zonedRelativeTo is not present, set zonedRelativeTo to undefined.
  5. If precalculatedPlainDateTime is not present, set precalculatedPlainDateTime to undefined.
  6. If IsCalendarUnit(unit) is true, then
    1. If plainRelativeTo is undefined, throw a RangeError exception.
    2. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-add) is true.
    3. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, date-until) is true.
  7. If IsCalendarUnit(unit) is true or unit is "day", then
    1. If zonedRelativeTo is not undefined, then
      1. Let intermediate be ? MoveRelativeZonedDateTime(zonedRelativeTo, calendarRec, timeZoneRec, years, months, weeks, days, precalculatedPlainDateTime).
      2. Let result be ? NormalizedTimeDurationToDays(norm, intermediate, timeZoneRec).
      3. Let fractionalDays be days + result.[[Days]] + DivideNormalizedTimeDuration(result.[[Remainder]], result.[[DayLength]]).
    2. Else,
      1. Let fractionalDays be days + DivideNormalizedTimeDuration(norm, nsPerDay).
    3. Set days to 0.
  8. Else,
    1. Assert: fractionalDays is not used below.
  9. If unit is "year", then
    1. Let yearsDuration be ! CreateTemporalDuration(years, 0, 0, 0, 0, 0, 0, 0, 0, 0).
    2. Let yearsLater be ? AddDate(calendarRec, plainRelativeTo, yearsDuration).
    3. Let yearsMonthsWeeks be ! CreateTemporalDuration(years, months, weeks, 0, 0, 0, 0, 0, 0, 0).
    4. Let yearsMonthsWeeksLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsWeeks).
    5. Let monthsWeeksInDays be DaysUntil(yearsLater, yearsMonthsWeeksLater).
    6. Set plainRelativeTo to yearsLater.
    7. Set fractionalDays to fractionalDays + monthsWeeksInDays.
    8. Let isoResult be BalanceISODate(plainRelativeTo.[[ISOYear]], plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]] + truncate(fractionalDays)).
    9. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]).
    10. Let untilOptions be OrdinaryObjectCreate(null).
    11. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "year").
    12. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions).
    13. Let yearsPassed be timePassed.[[Years]].
    14. Set years to years + yearsPassed.
    15. Set yearsDuration to ! CreateTemporalDuration(yearsPassed, 0, 0, 0, 0, 0, 0, 0, 0, 0).
    16. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, yearsDuration).
    17. Set plainRelativeTo to moveResult.[[RelativeTo]].
    18. Let daysPassed be moveResult.[[Days]].
    19. Set fractionalDays to fractionalDays - daysPassed.
    20. If fractionalDays < 0, let sign be -1; else, let sign be 1.
    21. Let oneYear be ! CreateTemporalDuration(sign, 0, 0, 0, 0, 0, 0, 0, 0, 0).
    22. Set moveResult to ? MoveRelativeDate(calendarRec, plainRelativeTo, oneYear).
    23. Let oneYearDays be moveResult.[[Days]].
    24. If oneYearDays = 0, throw a RangeError exception.
    25. Let fractionalYears be years + fractionalDays / abs(oneYearDays).
    26. Set years to RoundNumberToIncrement(fractionalYears, increment, roundingMode).
    27. Let total be fractionalYears.
    28. Set months and weeks to 0.
    29. Set norm to ZeroTimeDuration().
  10. Else if unit is "month", then
    1. Let yearsMonths be ! CreateTemporalDuration(years, months, 0, 0, 0, 0, 0, 0, 0, 0).
    2. Let yearsMonthsLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonths).
    3. Let yearsMonthsWeeks be ! CreateTemporalDuration(years, months, weeks, 0, 0, 0, 0, 0, 0, 0).
    4. Let yearsMonthsWeeksLater be ? AddDate(calendarRec, plainRelativeTo, yearsMonthsWeeks).
    5. Let weeksInDays be DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater).
    6. Set plainRelativeTo to yearsMonthsLater.
    7. Set fractionalDays to fractionalDays + weeksInDays.
    8. Let isoResult be BalanceISODate(plainRelativeTo.[[ISOYear]], plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]] + truncate(fractionalDays)).
    9. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]).
    10. Let untilOptions be OrdinaryObjectCreate(null).
    11. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "month").
    12. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions).
    13. Let monthsPassed be timePassed.[[Months]].
    14. Set months to months + monthsPassed.
    15. Let monthsPassedDuration be ! CreateTemporalDuration(0, monthsPassed, 0, 0, 0, 0, 0, 0, 0, 0).
    16. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, monthsPassedDuration).
    17. Set plainRelativeTo to moveResult.[[RelativeTo]].
    18. Let daysPassed be moveResult.[[Days]].
    19. Set fractionalDays to fractionalDays - daysPassed.
    20. If fractionalDays < 0, let sign be -1; else, let sign be 1.
    21. Let oneMonth be ! CreateTemporalDuration(0, sign, 0, 0, 0, 0, 0, 0, 0, 0).
    22. Set moveResult to ? MoveRelativeDate(calendarRec, plainRelativeTo, oneMonth).
    23. Let oneMonthDays be moveResult.[[Days]].
    24. If oneMonthDays = 0, throw a RangeError exception.
    25. Let fractionalMonths be months + fractionalDays / abs(oneMonthDays).
    26. Set months to RoundNumberToIncrement(fractionalMonths, increment, roundingMode).
    27. Let total be fractionalMonths.
    28. Set weeks to 0.
    29. Set norm to ZeroTimeDuration().
  11. Else if unit is "week", then
    1. Let isoResult be BalanceISODate(plainRelativeTo.[[ISOYear]], plainRelativeTo.[[ISOMonth]], plainRelativeTo.[[ISODay]] + truncate(fractionalDays)).
    2. Let wholeDaysLater be ? CreateTemporalDate(isoResult.[[Year]], isoResult.[[Month]], isoResult.[[Day]], calendarRec.[[Receiver]]).
    3. Let untilOptions be OrdinaryObjectCreate(null).
    4. Perform ! CreateDataPropertyOrThrow(untilOptions, "largestUnit", "week").
    5. Let timePassed be ? DifferenceDate(calendarRec, plainRelativeTo, wholeDaysLater, untilOptions).
    6. Let weeksPassed be timePassed.[[Weeks]].
    7. Set weeks to weeks + weeksPassed.
    8. Let weeksPassedDuration be ! CreateTemporalDuration(0, 0, weeksPassed, 0, 0, 0, 0, 0, 0, 0).
    9. Let moveResult be ? MoveRelativeDate(calendarRec, plainRelativeTo, weeksPassedDuration).
    10. Set plainRelativeTo to moveResult.[[RelativeTo]].
    11. Let daysPassed be moveResult.[[Days]].
    12. Set fractionalDays to fractionalDays - daysPassed.
    13. If fractionalDays < 0, let sign be -1; else, let sign be 1.
    14. Let oneWeek be ! CreateTemporalDuration(0, 0, sign, 0, 0, 0, 0, 0, 0, 0).
    15. Set moveResult to ? MoveRelativeDate(calendarRec, plainRelativeTo, oneWeek).
    16. Let oneWeekDays be moveResult.[[Days]].
    17. If oneWeekDays = 0, throw a RangeError exception.
    18. Let fractionalWeeks be weeks + fractionalDays / abs(oneWeekDays).
    19. Set weeks to RoundNumberToIncrement(fractionalWeeks, increment, roundingMode).
    20. Let total be fractionalWeeks.
    21. Set norm to ZeroTimeDuration().
  12. Else if unit is "day", then
    1. Set days to RoundNumberToIncrement(fractionalDays, increment, roundingMode).
    2. Let total be fractionalDays.
    3. Set norm to ZeroTimeDuration().
  13. Else if unit is "hour", then
    1. Let divisor be 3.6 × 1012.
    2. Let total be DivideNormalizedTimeDuration(norm, divisor).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
  14. Else if unit is "minute", then
    1. Let divisor be 6 × 1010.
    2. Let total be DivideNormalizedTimeDuration(norm, divisor).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
  15. Else if unit is "second", then
    1. Let divisor be 109.
    2. Let total be DivideNormalizedTimeDuration(norm, divisor).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
  16. Else if unit is "millisecond", then
    1. Let divisor be 106.
    2. Let total be DivideNormalizedTimeDuration(norm, divisor).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
  17. Else if unit is "microsecond", then
    1. Let divisor be 103.
    2. Let total be DivideNormalizedTimeDuration(norm, divisor).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, divisor × increment, roundingMode).
  18. Else,
    1. Assert: unit is "nanosecond".
    2. Let total be NormalizedTimeDurationSeconds(norm) × 109 + NormalizedTimeDurationSubseconds(norm).
    3. Set norm to ? RoundNormalizedTimeDurationToIncrement(norm, increment, roundingMode).
  19. Return the Record { [[NormalizedDuration]]: ? CreateNormalizedDurationRecord(years, months, weeks, days, norm), [[Total]]: total  }.

7.5.44 AdjustRoundedDurationDays ( years, months, weeks, days, norm, increment, unit, roundingMode, zonedRelativeTo, calendarRec, timeZoneRec, precalculatedPlainDateTime )

The abstract operation AdjustRoundedDurationDays takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), norm (a Normalized Time Duration Record), increment (an integer), unit (a String), roundingMode (a String from the Identifier column of Table 19), zonedRelativeTo (a Temporal.ZonedDateTime), calendarRec (a Calendar Methods Record), timeZoneRec (a Time Zone Methods Record), and precalculatedPlainDateTime (a Temporal.PlainDateTime or undefined) and returns either a normal completion containing a Normalized Duration Record, or a throw completion. It adjusts, if necessary, a duration that was rounded to a unit of hours or lower relative to a Temporal.ZonedDateTime, and returns the result. On a calendar day that is not 24 hours in length due to time zone offset changes, it is possible for a duration's time units to round up to exceed the day's length. In this case, the days part of the duration is adjusted by one, and the time part is re-rounded. It performs the following steps when called:

  1. If IsCalendarUnit(unit) is true; or unit is "day"; or unit is "nanosecond" and increment is 1, then
    1. Return ! CreateNormalizedDurationRecord(years, months, weeks, days, norm).
  2. Assert: precalculatedPlainDateTime is not undefined.
  3. Let direction be NormalizedTimeDurationSign(norm).
  4. Let dayStart be ? AddZonedDateTime(zonedRelativeTo.[[Nanoseconds]], timeZoneRec, calendarRec, years, months, weeks, days, ZeroTimeDuration(), precalculatedPlainDateTime).
  5. Let dayStartInstant be ! CreateTemporalInstant(dayStart).
  6. Let dayStartDateTime be ? GetPlainDateTimeFor(timeZoneRec, dayStartInstant, zonedRelativeTo.[[Calendar]]).
  7. Let dayEnd be ? AddDaysToZonedDateTime(dayStartInstant, dayStartDateTime, timeZoneRec, zonedRelativeTo.[[Calendar]], direction).[[EpochNanoseconds]].
  8. Let dayLengthNs be NormalizedTimeDurationFromEpochNanosecondsDifference(dayEnd, dayStart).
  9. Let oneDayLess be ? SubtractNormalizedTimeDuration(norm, dayLengthNs).
  10. If NormalizedTimeDurationSign(oneDayLess) × direction < 0, then
    1. Return ! CreateNormalizedDurationRecord(years, months, weeks, days, norm).
  11. Let adjustedDateDuration be ? AddDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0, 0, 0, 0, direction, 0, 0, 0, 0, 0, 0, undefined, zonedRelativeTo, calendarRec, timeZoneRec, precalculatedPlainDateTime).
  12. Let roundRecord be ? RoundDuration(0, 0, 0, 0, oneDayLess, increment, unit, roundingMode).
  13. Return ? CombineDateAndNormalizedTimeDuration(adjustedDateDuration, roundRecord.[[NormalizedDuration]].[[NormalizedTime]]).

7.5.45 TemporalDurationToString ( years, months, weeks, days, hours, minutes, normSeconds, precision )

The abstract operation TemporalDurationToString takes arguments years (an integer), months (an integer), weeks (an integer), days (an integer), hours (an integer), minutes (an integer), normSeconds (a Normalized Time Duration Record), and precision (an integer between 0 and 9 inclusive, or "auto"). It returns a String which is the ISO 8601 representation of the duration denoted by years through nanoseconds, with the number of decimal places in the seconds value controlled by precision. It performs the following steps when called:

  1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, NormalizedTimeDurationSeconds(normSeconds), 0, 0, NormalizedTimeDurationSubseconds(normSeconds)).
  2. Let datePart be "".
  3. If years is not 0, then
    1. Set datePart to the string concatenation of abs(years) formatted as a decimal number and the code unit 0x0059 (LATIN CAPITAL LETTER Y).
  4. If months is not 0, then
    1. Set datePart to the string concatenation of datePart, abs(months) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
  5. If weeks is not 0, then
    1. Set datePart to the string concatenation of datePart, abs(weeks) formatted as a decimal number, and the code unit 0x0057 (LATIN CAPITAL LETTER W).
  6. If days is not 0, then
    1. Set datePart to the string concatenation of datePart, abs(days) formatted as a decimal number, and the code unit 0x0044 (LATIN CAPITAL LETTER D).
  7. Let timePart be "".
  8. If hours is not 0, then
    1. Set timePart to the string concatenation of abs(hours) formatted as a decimal number and the code unit 0x0048 (LATIN CAPITAL LETTER H).
  9. If minutes is not 0, then
    1. Set timePart to the string concatenation of timePart, abs(minutes) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
  10. Let zeroMinutesAndHigher be false.
  11. If years = 0, and months = 0, and weeks = 0, and days = 0, and hours = 0, and minutes = 0, set zeroMinutesAndHigher to true.
  12. If NormalizedTimeDurationIsZero(normSeconds) is false, or zeroMinutesAndHigher is true, or precision is not "auto", then
    1. Let secondsPart be abs(NormalizedTimeDurationSeconds(normSeconds)) formatted as a decimal number.
    2. Let subSecondsPart be FormatFractionalSeconds(abs(NormalizedTimeDurationSubseconds(normSeconds)), precision).
    3. Set timePart to the string concatenation of timePart, secondsPart, subSecondsPart, and the code unit 0x0053 (LATIN CAPITAL LETTER S).
  13. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
  14. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
  15. If timePart is not "", then
    1. Set result to the string concatenation of result, the code unit 0x0054 (LATIN CAPITAL LETTER T), and timePart.
  16. Return result.

7.5.46 AddDurationToOrSubtractDurationFromDuration ( operation, duration, other, options )

The abstract operation AddDurationToOrSubtractDurationFromDuration takes arguments operation (add or subtract), duration (a Temporal.Duration), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It adds/subtracts other to/from duration, resulting in a longer/shorter duration. It performs the following steps when called:

  1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalDurationRecord(other).
  3. Set options to ? GetOptionsObject(options).
  4. Let relativeToRecord be ? ToRelativeTemporalObject(options).
  5. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  6. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  7. Let timeZoneRec be relativeToRecord.[[TimeZoneRec]].
  8. Let calendarRec be ? CreateCalendarMethodsRecordFromRelativeTo(plainRelativeTo, zonedRelativeTo, « date-add, date-until »).
  9. Let result be ? AddDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], sign × other.[[Years]], sign × other.[[Months]], sign × other.[[Weeks]], sign × other.[[Days]], sign × other.[[Hours]], sign × other.[[Minutes]], sign × other.[[Seconds]], sign × other.[[Milliseconds]], sign × other.[[Microseconds]], sign × other.[[Nanoseconds]], plainRelativeTo, calendarRec, zonedRelativeTo, timeZoneRec).
  10. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).

8 Temporal.Instant Objects

A Temporal.Instant object is an Object referencing a fixed point in time with nanoseconds precision.

8.1 The Temporal.Instant Constructor

The Temporal.Instant constructor:

  • creates and initializes a new Temporal.Instant object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.Instant behaviour must include a super call to the %Temporal.Instant% constructor to create and initialize subclass instances with the necessary internal slots.

8.1.1 Temporal.Instant ( epochNanoseconds )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds).
  3. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  4. Return ? CreateTemporalInstant(epochNanoseconds, NewTarget).

8.2 Properties of the Temporal.Instant Constructor

The value of the [[Prototype]] internal slot of the Temporal.Instant constructor is the intrinsic object %Function.prototype%.

The Temporal.Instant constructor has the following properties:

8.2.1 Temporal.Instant.prototype

The initial value of Temporal.Instant.prototype is %Temporal.Instant.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

8.2.2 Temporal.Instant.from ( item )

This function performs the following steps when called:

  1. If Type(item) is Object and item has an [[InitializedTemporalInstant]] internal slot, then
    1. Return ! CreateTemporalInstant(item.[[Nanoseconds]]).
  2. Return ? ToTemporalInstant(item).

8.2.3 Temporal.Instant.fromEpochSeconds ( epochSeconds )

This function performs the following steps when called:

  1. Set epochSeconds to ? ToNumber(epochSeconds).
  2. Set epochSeconds to ? NumberToBigInt(epochSeconds).
  3. Let epochNanoseconds be epochSeconds × (109).
  4. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  5. Return ! CreateTemporalInstant(epochNanoseconds).

8.2.4 Temporal.Instant.fromEpochMilliseconds ( epochMilliseconds )

This function performs the following steps when called:

  1. Set epochMilliseconds to ? ToNumber(epochMilliseconds).
  2. Set epochMilliseconds to ? NumberToBigInt(epochMilliseconds).
  3. Let epochNanoseconds be epochMilliseconds × (106).
  4. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  5. Return ! CreateTemporalInstant(epochNanoseconds).

8.2.5 Temporal.Instant.fromEpochMicroseconds ( epochMicroseconds )

This function performs the following steps when called:

  1. Set epochMicroseconds to ? ToBigInt(epochMicroseconds).
  2. Let epochNanoseconds be epochMicroseconds × 1000.
  3. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  4. Return ! CreateTemporalInstant(epochNanoseconds).

8.2.6 Temporal.Instant.fromEpochNanoseconds ( epochNanoseconds )

This function performs the following steps when called:

  1. Set epochNanoseconds to ? ToBigInt(epochNanoseconds).
  2. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  3. Return ! CreateTemporalInstant(epochNanoseconds).

8.2.7 Temporal.Instant.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalInstant(one).
  2. Set two to ? ToTemporalInstant(two).
  3. Return 𝔽(CompareEpochNanoseconds(one.[[Nanoseconds]], two.[[Nanoseconds]])).

8.3 Properties of the Temporal.Instant Prototype Object

The Temporal.Instant prototype object

  • is itself an ordinary object.
  • is not a Temporal.Instant instance and does not have a [[InitializedTemporalInstant]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.

8.3.1 Temporal.Instant.prototype.constructor

The initial value of Temporal.Instant.prototype.constructor is %Temporal.Instant%.

8.3.2 Temporal.Instant.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.Instant".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

8.3.3 get Temporal.Instant.prototype.epochSeconds

Temporal.Instant.prototype.epochSeconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Let ns be instant.[[Nanoseconds]].
  4. Let s be floor((ns) / 109).
  5. Return 𝔽(s).

8.3.4 get Temporal.Instant.prototype.epochMilliseconds

Temporal.Instant.prototype.epochMilliseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Let ns be instant.[[Nanoseconds]].
  4. Let ms be floor((ns) / 106).
  5. Return 𝔽(ms).

8.3.5 get Temporal.Instant.prototype.epochMicroseconds

Temporal.Instant.prototype.epochMicroseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Let ns be instant.[[Nanoseconds]].
  4. Let µs be floor((ns) / 103).
  5. Return (µs).

8.3.6 get Temporal.Instant.prototype.epochNanoseconds

Temporal.Instant.prototype.epochNanoseconds is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Let ns be instant.[[Nanoseconds]].
  4. Return ns.

8.3.7 Temporal.Instant.prototype.add ( temporalDurationLike )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? AddDurationToOrSubtractDurationFromInstant(add, instant, temporalDurationLike).

8.3.8 Temporal.Instant.prototype.subtract ( temporalDurationLike )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? AddDurationToOrSubtractDurationFromInstant(subtract, instant, temporalDurationLike).

8.3.9 Temporal.Instant.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? DifferenceTemporalInstant(until, instant, other, options).

8.3.10 Temporal.Instant.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? DifferenceTemporalInstant(since, instant, other, options).

8.3.11 Temporal.Instant.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. If roundTo is undefined, then
    1. Throw a TypeError exception.
  4. If Type(roundTo) is String, then
    1. Let paramString be roundTo.
    2. Set roundTo to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(roundTo, "smallestUnit", paramString).
  5. Else,
    1. Set roundTo to ? GetOptionsObject(roundTo).
  6. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  7. Let roundingIncrement be ? ToTemporalRoundingIncrement(roundTo).
  8. Let roundingMode be ? ToTemporalRoundingMode(roundTo, "halfExpand").
  9. Let smallestUnit be ? GetTemporalUnit(roundTo, "smallestUnit", time, required).
  10. If smallestUnit is "hour", then
    1. Let maximum be HoursPerDay.
  11. Else if smallestUnit is "minute", then
    1. Let maximum be MinutesPerHour × HoursPerDay.
  12. Else if smallestUnit is "second", then
    1. Let maximum be SecondsPerMinute × MinutesPerHour × HoursPerDay.
  13. Else if smallestUnit is "millisecond", then
    1. Let maximum be (msPerDay).
  14. Else if smallestUnit is "microsecond", then
    1. Let maximum be 103 × (msPerDay).
  15. Else,
    1. Assert: smallestUnit is "nanosecond".
    2. Let maximum be nsPerDay.
  16. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, true).
  17. Let roundedNs be RoundTemporalInstant(instant.[[Nanoseconds]], roundingIncrement, smallestUnit, roundingMode).
  18. Return ! CreateTemporalInstant(roundedNs).

8.3.12 Temporal.Instant.prototype.equals ( other )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Set other to ? ToTemporalInstant(other).
  4. If instant.[[Nanoseconds]]other.[[Nanoseconds]], return false.
  5. Return true.

8.3.13 Temporal.Instant.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Set options to ? GetOptionsObject(options).
  4. NOTE: The following steps read options and perform independent validation in alphabetical order (ToFractionalSecondDigits reads "fractionalSecondDigits" and ToTemporalRoundingMode reads "roundingMode").
  5. Let digits be ? ToFractionalSecondDigits(options).
  6. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  7. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", time, undefined).
  8. If smallestUnit is "hour", throw a RangeError exception.
  9. Let timeZone be ? Get(options, "timeZone").
  10. If timeZone is not undefined, then
    1. Set timeZone to ? ToTemporalTimeZoneSlotValue(timeZone).
  11. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  12. Let roundedNs be RoundTemporalInstant(instant.[[Nanoseconds]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  13. Let roundedInstant be ! CreateTemporalInstant(roundedNs).
  14. Return ? TemporalInstantToString(roundedInstant, timeZone, precision.[[Precision]]).

8.3.14 Temporal.Instant.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? TemporalInstantToString(instant, undefined, "auto").

8.3.15 Temporal.Instant.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Return ? TemporalInstantToString(instant, undefined, "auto").

8.3.16 Temporal.Instant.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

8.3.17 Temporal.Instant.prototype.toZonedDateTime ( item )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. If Type(item) is not Object, then
    1. Throw a TypeError exception.
  4. Let calendarLike be ? Get(item, "calendar").
  5. If calendarLike is undefined, then
    1. Throw a TypeError exception.
  6. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike).
  7. Let temporalTimeZoneLike be ? Get(item, "timeZone").
  8. If temporalTimeZoneLike is undefined, then
    1. Throw a TypeError exception.
  9. Let timeZone be ? ToTemporalTimeZoneSlotValue(temporalTimeZoneLike).
  10. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, calendar).

8.3.18 Temporal.Instant.prototype.toZonedDateTimeISO ( timeZone )

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Set timeZone to ? ToTemporalTimeZoneSlotValue(timeZone).
  4. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, "iso8601").

8.4 Properties of Temporal.Instant Instances

Temporal.Instant instances are ordinary objects that inherit properties from the %Temporal.Instant.prototype% intrinsic object. Temporal.Instant instances are initially created with the internal slots described in Table 13.

Table 13: Internal Slots of Temporal.Instant Instances
Internal Slot Description
[[InitializedTemporalInstant]] The only specified use of this slot is for distinguishing Temporal.Instant instances from other objects.
[[Nanoseconds]] A BigInt value representing the number of nanoseconds since the epoch.

8.4.1 Temporal.Instant range

The [[Nanoseconds]] internal slot of a Temporal.Instant object supports a range of exactly -100,000,000 to 100,000,000 days relative to midnight at the beginning of 1 January 1970 UTC, as in 21.4.1.1.

The exact moment of midnight at the beginning of 1 January 1970 UTC is represented by the value 0.

The maximum value is (nsMaxInstant), where

nsMaxInstant = 108 × nsPerDay = 8.64 × 1021

where the number of nanoseconds per day is

nsPerDay = 106 × (msPerDay) = 8.64 × 1013

The minimum value is (nsMinInstant), where

nsMinInstant = -nsMaxInstant = -8.64 × 1021

8.5 Abstract Operations

8.5.1 IsValidEpochNanoseconds ( epochNanoseconds )

The abstract operation IsValidEpochNanoseconds returns true if its argument epochNanoseconds is within the allowed range of nanoseconds since the epoch for a Temporal.Instant and Temporal.ZonedDateTime, and false otherwise.

  1. Assert: Type(epochNanoseconds) is BigInt.
  2. If (epochNanoseconds) < nsMinInstant or (epochNanoseconds) > nsMaxInstant, then
    1. Return false.
  3. Return true.

8.5.2 CreateTemporalInstant ( epochNanoseconds [ , newTarget ] )

The abstract operation CreateTemporalInstant takes argument epochNanoseconds (a BigInt) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.Instant, or an abrupt completion. It creates a Temporal.Instant instance and fills the internal slots with valid values. It performs the following steps when called:

  1. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true.
  2. If newTarget is not present, set newTarget to %Temporal.Instant%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Instant.prototype%", « [[InitializedTemporalInstant]], [[Nanoseconds]] »).
  4. Set object.[[Nanoseconds]] to epochNanoseconds.
  5. Return object.

8.5.3 ToTemporalInstant ( item )

The abstract operation ToTemporalInstant returns its argument item if it is already a Temporal.Instant instance, converts item to a new Temporal.Instant instance if possible, and throws otherwise.

  1. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalInstant]] internal slot, then
      1. Return item.
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return ! CreateTemporalInstant(item.[[Nanoseconds]]).
    3. NOTE: This use of ToPrimitive allows Instant-like objects to be converted.
    4. Set item to ? ToPrimitive(item, string).
  2. If item is not a String, throw a TypeError exception.
  3. Let parsed be ? ParseTemporalInstantString(item).
  4. If parsed.[[Z]] is true, let offsetNanoseconds be 0; otherwise, let offsetNanoseconds be ! ParseDateTimeUTCOffset(parsed.[[OffsetString]]).
  5. If abs(ISODateToEpochDays(parsed.[[Year]], parsed.[[Month]] - 1, parsed.[[Day]])) > 108, throw a RangeError exception.
  6. Let epochNanoseconds be GetUTCEpochNanoseconds(parsed.[[Year]], parsed.[[Month]], parsed.[[Day]], parsed.[[Hour]], parsed.[[Minute]], parsed.[[Second]], parsed.[[Millisecond]], parsed.[[Microsecond]], parsed.[[Nanosecond]], offsetNanoseconds).
  7. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
  8. Return ! CreateTemporalInstant(epochNanoseconds).

8.5.4 CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo )

The abstract operation CompareEpochNanoseconds takes arguments epochNanosecondsOne (a BigInt) and epochNanosecondsTwo (a BigInt) and returns either -1, 0, or 1. It performs the following steps when called:

  1. If epochNanosecondsOne > epochNanosecondsTwo, return 1.
  2. If epochNanosecondsOne < epochNanosecondsTwo, return -1.
  3. Return 0.

8.5.5 AddInstant ( epochNanoseconds, norm )

The abstract operation AddInstant takes arguments epochNanoseconds (a BigInt value) and norm (a Normalized Time Duration Record) and returns either a normal completion containing a BigInt, or a throw completion. It adds a duration in various time units to a number of nanoseconds since the epoch. It performs the following steps when called:

  1. Let result be AddNormalizedTimeDurationToEpochNanoseconds(norm, epochNanoseconds).
  2. If ! IsValidEpochNanoseconds(result) is false, throw a RangeError exception.
  3. Return result.

8.5.6 DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, roundingMode )

The abstract operation DifferenceInstant takes arguments ns1 (a BigInt), ns2 (a BigInt), roundingIncrement (a positive integer), smallestUnit (a String), and roundingMode (a String from the Identifier column of Table 19) and returns a Normalized Time Duration Record. It computes the difference between two exact times ns1 and ns2 expressed in nanoseconds since the epoch, and rounds the result according to the parameters roundingIncrement, smallestUnit, and roundingMode. It performs the following steps when called:

  1. Let difference be NormalizedTimeDurationFromEpochNanosecondsDifference(ns2, ns1).
  2. If smallestUnit is "nanosecond" and roundingIncrement is 1, then
    1. Return difference.
  3. Let roundRecord be ! RoundDuration(0, 0, 0, 0, difference, roundingIncrement, smallestUnit, roundingMode).
  4. Return roundRecord.[[NormalizedDuration]].[[NormalizedTime]].

8.5.7 RoundTemporalInstant ( ns, increment, unit, roundingMode )

The abstract operation RoundTemporalInstant takes arguments ns (a BigInt), increment (a positive integer), unit (a String), and roundingMode (a String from the Identifier column of Table 19) and returns a BigInt. It rounds a number of nanoseconds ns since the epoch to the given rounding increment. It performs the following steps when called:

  1. If unit is "hour", then
    1. Let incrementNs be increment × 3.6 × 1012.
  2. Else if unit is "minute", then
    1. Let incrementNs be increment × 6 × 1010.
  3. Else if unit is "second", then
    1. Let incrementNs be increment × 109.
  4. Else if unit is "millisecond", then
    1. Let incrementNs be increment × 106.
  5. Else if unit is "microsecond", then
    1. Let incrementNs be increment × 103.
  6. Else,
    1. Assert: unit is "nanosecond".
    2. Let incrementNs be increment.
  7. Return (RoundNumberToIncrementAsIfPositive((ns), incrementNs, roundingMode)).

8.5.8 TemporalInstantToString ( instant, timeZone, precision )

  1. Assert: Type(instant) is Object.
  2. Assert: instant has an [[InitializedTemporalInstant]] internal slot.
  3. Let outputTimeZone be timeZone.
  4. If outputTimeZone is undefined, set outputTimeZone to "UTC".
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(outputTimeZone, « get-offset-nanoseconds-for »).
  6. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  7. Let dateTime be ! GetPlainDateTimeFor(timeZoneRec, instant, "iso8601", offsetNanoseconds).
  8. Let dateTimeString be ! TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], "iso8601", precision, "never").
  9. If timeZone is undefined, then
    1. Let timeZoneString be "Z".
  10. Else,
    1. Let timeZoneString be FormatDateTimeUTCOffsetRounded(offsetNanoseconds).
  11. Return the string-concatenation of dateTimeString and timeZoneString.

8.5.9 DifferenceTemporalInstant ( operation, instant, other, options )

The abstract operation DifferenceTemporalInstant takes arguments operation (since or until), instant (a Temporal.Instant), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by instant and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalInstant(other).
  3. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », "nanosecond", "second").
  5. Let norm be DifferenceInstant(instant.[[Nanoseconds]], other.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  6. Let result be BalanceTimeDuration(norm, settings.[[LargestUnit]]).
  7. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]).

8.5.10 AddDurationToOrSubtractDurationFromInstant ( operation, instant, temporalDurationLike )

The abstract operation AddDurationToOrSubtractDurationFromInstant takes arguments operation (add or subtract), instant (a Temporal.Instant), and temporalDurationLike (an ECMAScript language value) and returns either a normal completion containing a Temporal.Instant or an abrupt completion. It adds/subtracts temporalDurationLike to/from instant. It performs the following steps when called:

  1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
  2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
  3. If duration.[[Days]] is not 0, throw a RangeError exception.
  4. If duration.[[Months]] is not 0, throw a RangeError exception.
  5. If duration.[[Weeks]] is not 0, throw a RangeError exception.
  6. If duration.[[Years]] is not 0, throw a RangeError exception.
  7. Let norm be NormalizeTimeDuration(sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
  8. Let ns be ? AddInstant(instant.[[Nanoseconds]], norm).
  9. Return ! CreateTemporalInstant(ns).

9 Temporal.PlainYearMonth Objects

A Temporal.PlainYearMonth object is an Object that contains integers corresponding to a particular year and month in a particular calendar.

9.1 The Temporal.PlainYearMonth Constructor

The Temporal.PlainYearMonth constructor:

  • creates and initializes a new Temporal.PlainYearMonth object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.PlainYearMonth behaviour must include a super call to the %Temporal.PlainYearMonth% constructor to create and initialize subclass instances with the necessary internal slots.

9.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendarLike [ , referenceISODay ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If referenceISODay is undefined, then
    1. Set referenceISODay to 1𝔽.
  3. Let y be ? ToIntegerWithTruncation(isoYear).
  4. Let m be ? ToIntegerWithTruncation(isoMonth).
  5. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  6. Let ref be ? ToIntegerWithTruncation(referenceISODay).
  7. Return ? CreateTemporalYearMonth(y, m, calendar, ref, NewTarget).

9.2 Properties of the Temporal.PlainYearMonth Constructor

The value of the [[Prototype]] internal slot of the Temporal.PlainYearMonth constructor is the intrinsic object %Function.prototype%.

The Temporal.PlainYearMonth constructor has the following properties:

9.2.1 Temporal.PlainYearMonth.prototype

The initial value of Temporal.PlainYearMonth.prototype is %Temporal.PlainYearMonth.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

9.2.2 Temporal.PlainYearMonth.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. If Type(item) is Object and item has an [[InitializedTemporalYearMonth]] internal slot, then
    1. Perform ? ToTemporalOverflow(options).
    2. Return ! CreateTemporalYearMonth(item.[[ISOYear]], item.[[ISOMonth]], item.[[Calendar]], item.[[ISODay]]).
  3. Return ? ToTemporalYearMonth(item, options).

9.2.3 Temporal.PlainYearMonth.compare ( one, two )

This function performs the following steps when called:

  1. Set one to ? ToTemporalYearMonth(one).
  2. Set two to ? ToTemporalYearMonth(two).
  3. Return 𝔽(! CompareISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]])).

9.3 Properties of the Temporal.PlainYearMonth Prototype Object

The Temporal.PlainYearMonth prototype object

  • is itself an ordinary object.
  • is not a Temporal.PlainYearMonth instance and does not have a [[InitializedTemporalYearMonth]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

9.3.1 Temporal.PlainYearMonth.prototype.constructor

The initial value of Temporal.PlainYearMonth.prototype.constructor is %Temporal.PlainYearMonth%.

9.3.2 Temporal.PlainYearMonth.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.PlainYearMonth".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

9.3.3 get Temporal.PlainYearMonth.prototype.calendarId

Temporal.PlainYearMonth.prototype.calendarId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? ToTemporalCalendarIdentifier(yearMonth.[[Calendar]]).

9.3.4 get Temporal.PlainYearMonth.prototype.year

Temporal.PlainYearMonth.prototype.year is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return 𝔽(? CalendarYear(calendar, yearMonth)).

9.3.5 get Temporal.PlainYearMonth.prototype.month

Temporal.PlainYearMonth.prototype.month is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return 𝔽(? CalendarMonth(calendar, yearMonth)).

9.3.6 get Temporal.PlainYearMonth.prototype.monthCode

Temporal.PlainYearMonth.prototype.monthCode is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return ? CalendarMonthCode(calendar, yearMonth).

9.3.7 get Temporal.PlainYearMonth.prototype.daysInYear

Temporal.PlainYearMonth.prototype.daysInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInYear(calendar, yearMonth)).

9.3.8 get Temporal.PlainYearMonth.prototype.daysInMonth

Temporal.PlainYearMonth.prototype.daysInMonth is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return 𝔽(? CalendarDaysInMonth(calendar, yearMonth)).

9.3.9 get Temporal.PlainYearMonth.prototype.monthsInYear

Temporal.PlainYearMonth.prototype.monthsInYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return 𝔽(? CalendarMonthsInYear(calendar, yearMonth)).

9.3.10 get Temporal.PlainYearMonth.prototype.inLeapYear

Temporal.PlainYearMonth.prototype.inLeapYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be yearMonth.[[Calendar]].
  4. Return ? CalendarInLeapYear(calendar, yearMonth).

9.3.11 Temporal.PlainYearMonth.prototype.with ( temporalYearMonthLike [ , options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. If ? IsPartialTemporalObject(temporalYearMonthLike) is false, throw a TypeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(yearMonth.[[Calendar]], « fields, merge-fields, year-month-from-fields »).
  6. Let fieldNames be ? CalendarFields(calendarRec, « "month", "monthCode", "year" »).
  7. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
  8. Let partialYearMonth be ? PrepareTemporalFields(temporalYearMonthLike, fieldNames, partial).
  9. Set fields to ? CalendarMergeFields(calendarRec, fields, partialYearMonth).
  10. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»).
  11. Return ? CalendarYearMonthFromFields(calendarRec, fields, resolvedOptions).

9.3.12 Temporal.PlainYearMonth.prototype.add ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(add, yearMonth, temporalDurationLike, options).

9.3.13 Temporal.PlainYearMonth.prototype.subtract ( temporalDurationLike [ , options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? AddDurationToOrSubtractDurationFromPlainYearMonth(subtract, yearMonth, temporalDurationLike, options).

9.3.14 Temporal.PlainYearMonth.prototype.until ( other [ , options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? DifferenceTemporalPlainYearMonth(until, yearMonth, other, options).

9.3.15 Temporal.PlainYearMonth.prototype.since ( other [ , options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? DifferenceTemporalPlainYearMonth(since, yearMonth, other, options).

9.3.16 Temporal.PlainYearMonth.prototype.equals ( other )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Set other to ? ToTemporalYearMonth(other).
  4. If yearMonth.[[ISOYear]]other.[[ISOYear]], return false.
  5. If yearMonth.[[ISOMonth]]other.[[ISOMonth]], return false.
  6. If yearMonth.[[ISODay]]other.[[ISODay]], return false.
  7. Return ? CalendarEquals(yearMonth.[[Calendar]], other.[[Calendar]]).

9.3.17 Temporal.PlainYearMonth.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Set options to ? GetOptionsObject(options).
  4. Let showCalendar be ? ToCalendarNameOption(options).
  5. Return ? TemporalYearMonthToString(yearMonth, showCalendar).

9.3.18 Temporal.PlainYearMonth.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? TemporalYearMonthToString(yearMonth, "auto").

9.3.19 Temporal.PlainYearMonth.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ? TemporalYearMonthToString(yearMonth, "auto").

9.3.20 Temporal.PlainYearMonth.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

9.3.21 Temporal.PlainYearMonth.prototype.toPlainDate ( item )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. If Type(item) is not Object, then
    1. Throw a TypeError exception.
  4. Let calendarRec be ? CreateCalendarMethodsRecord(yearMonth.[[Calendar]], « date-from-fields, fields, merge-fields »).
  5. Let receiverFieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  6. Let fields be ? PrepareTemporalFields(yearMonth, receiverFieldNames, «»).
  7. Let inputFieldNames be ? CalendarFields(calendarRec, « "day" »).
  8. Let inputFields be ? PrepareTemporalFields(item, inputFieldNames, «»).
  9. Let mergedFields be ? CalendarMergeFields(calendarRec, fields, inputFields).
  10. Let concatenatedFieldNames be the list-concatenation of receiverFieldNames and inputFieldNames.
  11. Set mergedFields to ? PrepareTemporalFields(mergedFields, concatenatedFieldNames, «», «», ignore).
  12. Let options be OrdinaryObjectCreate(null).
  13. Perform ! CreateDataPropertyOrThrow(options, "overflow", "constrain").
  14. Return ? CalendarDateFromFields(calendarRec, mergedFields, options).

9.3.22 Temporal.PlainYearMonth.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", yearMonth.[[Calendar]]).
  5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(yearMonth.[[ISODay]])).
  6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(yearMonth.[[ISOMonth]])).
  7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(yearMonth.[[ISOYear]])).
  8. Return fields.

9.3.23 Temporal.PlainYearMonth.prototype.getCalendar ( )

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Return ToTemporalCalendarObject(yearMonth.[[Calendar]]).

9.4 Properties of Temporal.PlainYearMonth Instances

Temporal.PlainYearMonth instances are ordinary objects that inherit properties from the %Temporal.PlainYearMonth.prototype% intrinsic object. Temporal.PlainYearMonth instances are initially created with the internal slots described in Table 14.

Table 14: Internal Slots of Temporal.PlainYearMonth Instances
Internal Slot Description
[[InitializedTemporalYearMonth]] The only specified use of this slot is for distinguishing Temporal.PlainYearMonth instances from other objects.
[[ISOYear]] An integer representing the year in the ISO 8601 calendar.
[[ISOMonth]] An integer between 1 and 12, inclusive, representing the month of the year in the ISO 8601 calendar.
[[ISODay]] An integer between 1 and ISODaysInMonth([[ISOYear]], [[ISOMonth]]), inclusive, representing a reference day of the month in the ISO 8601 calendar. This slot is used by the calendar object in the [[Calendar]] slot to disambiguate if the [[ISOYear]] and [[ISOMonth]] slots are not enough to uniquely identify a year and month in that calendar.
[[Calendar]] A String or Object representing the calendar.

9.5 Abstract Operations

9.5.1 ToTemporalYearMonth ( item [ , options ] )

The abstract operation ToTemporalYearMonth takes argument item (an ECMAScript language value) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainYearMonth, or a throw completion. It returns its argument item if it is already a Temporal.PlainYearMonth instance, converts item to a new Temporal.PlainYearMonth instance if possible, and throws otherwise. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. If options is not undefined, set options to ? SnapshotOwnProperties(! GetOptionsObject(options), null).
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalYearMonth]] internal slot, then
      1. Return item.
    2. Let calendar be ? GetTemporalCalendarSlotValueWithISODefault(item).
    3. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « fields, year-month-from-fields »).
    4. Let fieldNames be ? CalendarFields(calendarRec, « "month", "monthCode", "year" »).
    5. Let fields be ? PrepareTemporalFields(item, fieldNames, «»).
    6. Return ? CalendarYearMonthFromFields(calendarRec, fields, options).
  4. If item is not a String, throw a TypeError exception.
  5. Let result be ? ParseTemporalYearMonthString(item).
  6. Let calendar be result.[[Calendar]].
  7. If calendar is undefined, set calendar to "iso8601".
  8. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
  9. Set calendar to the ASCII-lowercase of calendar.
  10. Perform ? ToTemporalOverflow(options).
  11. Set result to ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar, result.[[Day]]).
  12. NOTE: The following operation is called without options, in order for the calendar to store a canonical value in the [[ISODay]] internal slot of the result.
  13. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « year-month-from-fields »).
  14. Return ? CalendarYearMonthFromFields(calendarRec, result).

9.5.2 RegulateISOYearMonth ( year, month, overflow )

  1. Assert: year and month are integers.
  2. Assert: overflow is either "constrain" or "reject".
  3. If overflow is "constrain", then
    1. Set month to the result of clamping month between 1 and 12.
    2. Return the Record { [[Year]]: year, [[Month]]: month  }.
  4. Else,
    1. Assert: overflow is "reject".
    2. If month < 1 or month > 12, throw a RangeError exception.
    3. Return the Record { [[Year]]: year, [[Month]]: month  }.

9.5.3 ISOYearMonthWithinLimits ( year, month )

The abstract operation ISOYearMonthWithinLimits returns true if its arguments represent a month within the range that a Temporal.PlainYearMonth object can represent, and false otherwise.

Note

Temporal.PlainYearMonth objects can represent any month that contains a day that a Temporal.PlainDate can represent. This ensures that a Temporal.PlainDate object can always be converted into a Temporal.PlainYearMonth object.

  1. Assert: year and month are integers.
  2. If year < -271821 or year > 275760, then
    1. Return false.
  3. If year is -271821 and month < 4, then
    1. Return false.
  4. If year is 275760 and month > 9, then
    1. Return false.
  5. Return true.

9.5.4 BalanceISOYearMonth ( year, month )

  1. Assert: year and month are integers.
  2. Set year to year + floor((month - 1) / 12).
  3. Set month to ((month - 1) modulo 12) + 1.
  4. Return the Record { [[Year]]: year, [[Month]]: month  }.

9.5.5 CreateTemporalYearMonth ( isoYear, isoMonth, calendar, referenceISODay [ , newTarget ] )

The abstract operation CreateTemporalYearMonth takes arguments isoYear (an integer), isoMonth (an integer), calendar (a String or Object), and referenceISODay (an integer) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainYearMonth, or an abrupt completion. It creates a Temporal.PlainYearMonth instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If IsValidISODate(isoYear, isoMonth, referenceISODay) is false, throw a RangeError exception.
  2. If ! ISOYearMonthWithinLimits(isoYear, isoMonth) is false, throw a RangeError exception.
  3. If newTarget is not present, set newTarget to %Temporal.PlainYearMonth%.
  4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainYearMonth.prototype%", « [[InitializedTemporalYearMonth]], [[ISOYear]], [[ISOMonth]], [[ISODay]], [[Calendar]] »).
  5. Set object.[[ISOYear]] to isoYear.
  6. Set object.[[ISOMonth]] to isoMonth.
  7. Set object.[[Calendar]] to calendar.
  8. Set object.[[ISODay]] to referenceISODay.
  9. Return object.

9.5.6 TemporalYearMonthToString ( yearMonth, showCalendar )

  1. Assert: Type(yearMonth) is Object.
  2. Assert: yearMonth has an [[InitializedTemporalYearMonth]] internal slot.
  3. Let year be PadISOYear(yearMonth.[[ISOYear]]).
  4. Let month be ToZeroPaddedDecimalString(yearMonth.[[ISOMonth]], 2).
  5. Let result be the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and month.
  6. Let calendarIdentifier be ? ToTemporalCalendarIdentifier(yearMonth.[[Calendar]]).
  7. If showCalendar is one of "always" or "critical", or if calendarIdentifier is not "iso8601", then
    1. Let day be ToZeroPaddedDecimalString(yearMonth.[[ISODay]], 2).
    2. Set result to the string-concatenation of result, the code unit 0x002D (HYPHEN-MINUS), and day.
  8. Let calendarString be FormatCalendarAnnotation(calendarIdentifier, showCalendar).
  9. Set result to the string-concatenation of result and calendarString.
  10. Return result.

9.5.7 DifferenceTemporalPlainYearMonth ( operation, yearMonth, other, options )

The abstract operation DifferenceTemporalPlainYearMonth takes arguments operation (since or until), yearMonth (a Temporal.PlainYearMonth), other (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or an abrupt completion. It computes the difference between the two times represented by yearMonth and other, optionally rounds it, and returns it as a Temporal.Duration object. It performs the following steps when called:

  1. If operation is since, let sign be -1. Otherwise, let sign be 1.
  2. Set other to ? ToTemporalYearMonth(other).
  3. Let calendar be yearMonth.[[Calendar]].
  4. If ? CalendarEquals(calendar, other.[[Calendar]]) is false, throw a RangeError exception.
  5. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  6. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « "week", "day" », "month", "year").
  7. If yearMonth.[[ISOYear]] = other.[[ISOYear]] and yearMonth.[[ISOMonth]] = other.[[ISOMonth]] and yearMonth.[[ISODay]] = other.[[ISODay]], then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  8. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « date-add, date-from-fields, date-until, fields »).
  9. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  10. Let thisFields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
  11. Perform ! CreateDataPropertyOrThrow(thisFields, "day", 1𝔽).
  12. Let thisDate be ? CalendarDateFromFields(calendarRec, thisFields).
  13. Let otherFields be ? PrepareTemporalFields(other, fieldNames, «»).
  14. Perform ! CreateDataPropertyOrThrow(otherFields, "day", 1𝔽).
  15. Let otherDate be ? CalendarDateFromFields(calendarRec, otherFields).
  16. Perform ! CreateDataPropertyOrThrow(resolvedOptions, "largestUnit", settings.[[LargestUnit]]).
  17. Let result be ? CalendarDateUntil(calendarRec, thisDate, otherDate, resolvedOptions).
  18. If settings.[[SmallestUnit]] is not "month" or settings.[[RoundingIncrement]] ≠ 1, then
    1. Let roundRecord be ? RoundDuration(result.[[Years]], result.[[Months]], 0, 0, ZeroTimeDuration(), settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]], thisDate, calendarRec).
    2. Let roundResult be roundRecord.[[NormalizedDuration]].
    3. Set result to ? BalanceDateDurationRelative(roundResult.[[Years]], roundResult.[[Months]], 0, 0, settings.[[LargestUnit]], settings.[[SmallestUnit]], thisDate, calendarRec).
  19. Return ! CreateTemporalDuration(sign × result.[[Years]], sign × result.[[Months]], 0, 0, 0, 0, 0, 0, 0, 0).

9.5.8 AddDurationToOrSubtractDurationFromPlainYearMonth ( operation, yearMonth, temporalDurationLike, options )

The abstract operation AddDurationToOrSubtractDurationFromPlainYearMonth takes arguments operation (add or subtract), yearMonth (a Temporal.PlainYearMonth), temporalDurationLike (an ECMAScript language value), and options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainYearMonth or an abrupt completion. It adds/subtracts temporalDurationLike to/from yearMonth, returning a point in time that is in the future/past relative to yearMonth. It performs the following steps when called:

  1. Let duration be ? ToTemporalDuration(temporalDurationLike).
  2. If operation is subtract, then
    1. Set duration to ! CreateNegatedTemporalDuration(duration).
  3. Set options to ? GetOptionsObject(options).
  4. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  5. Let balanceResult be BalanceTimeDuration(norm, "day").
  6. Let days be duration.[[Days]] + balanceResult.[[Days]].
  7. Let sign be ! DurationSign(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], days, 0, 0, 0, 0, 0, 0).
  8. Let calendarRec be ? CreateCalendarMethodsRecord(yearMonth.[[Calendar]], « date-add, date-from-fields, day, fields, year-month-from-fields »).
  9. Let fieldNames be ? CalendarFields(calendarRec, « "monthCode", "year" »).
  10. Let fields be ? PrepareTemporalFields(yearMonth, fieldNames, «»).
  11. Let fieldsCopy be ! SnapshotOwnProperties(fields, null).
  12. Perform ! CreateDataPropertyOrThrow(fields, "day", 1𝔽).
  13. Let intermediateDate be ? CalendarDateFromFields(calendarRec, fields).
  14. If sign < 0, then
    1. Let oneMonthDuration be ! CreateTemporalDuration(0, 1, 0, 0, 0, 0, 0, 0, 0, 0).
    2. Let nextMonth be ? CalendarDateAdd(calendarRec, intermediateDate, oneMonthDuration).
    3. Let endOfMonthISO be BalanceISODate(nextMonth.[[ISOYear]], nextMonth.[[ISOMonth]], nextMonth.[[ISODay]] - 1).
    4. Let endOfMonth be ? CreateTemporalDate(endOfMonthISO.[[Year]], endOfMonthISO.[[Month]], endOfMonthISO.[[Day]], calendarRec.[[Receiver]]).
    5. Let day be ? CalendarDay(calendarRec, endOfMonth).
    6. Perform ! CreateDataPropertyOrThrow(fieldsCopy, "day", day).
    7. Let date be ? CalendarDateFromFields(calendarRec, fieldsCopy).
  15. Else,
    1. Let date be intermediateDate.
  16. Let durationToAdd be ! CreateTemporalDuration(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], days, 0, 0, 0, 0, 0, 0).
  17. Let optionsCopy be ? SnapshotOwnProperties(options, null).
  18. Let addedDate be ? AddDate(calendarRec, date, durationToAdd, options).
  19. Let addedDateFields be ? PrepareTemporalFields(addedDate, fieldNames, «»).
  20. Return ? CalendarYearMonthFromFields(calendarRec, addedDateFields, optionsCopy).

10 Temporal.PlainMonthDay Objects

A Temporal.PlainMonthDay object is an Object that contains integers corresponding to a particular month and day in a particular calendar.

10.1 The Temporal.PlainMonthDay Constructor

The Temporal.PlainMonthDay constructor:

  • creates and initializes a new Temporal.PlainMonthDay object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.PlainMonthDay behaviour must include a super call to the %Temporal.PlainMonthDay% constructor to create and initialize subclass instances with the necessary internal slots.

10.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendarLike [ , referenceISOYear ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If referenceISOYear is undefined, then
    1. Set referenceISOYear to 1972𝔽 (the first ISO 8601 leap year after the epoch).
  3. Let m be ? ToIntegerWithTruncation(isoMonth).
  4. Let d be ? ToIntegerWithTruncation(isoDay).
  5. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  6. Let y be ? ToIntegerWithTruncation(referenceISOYear).
  7. Return ? CreateTemporalMonthDay(m, d, calendar, y, NewTarget).

10.2 Properties of the Temporal.PlainMonthDay Constructor

The value of the [[Prototype]] internal slot of the Temporal.PlainMonthDay constructor is the intrinsic object %Function.prototype%.

The Temporal.PlainMonthDay constructor has the following properties:

10.2.1 Temporal.PlainMonthDay.prototype

The initial value of Temporal.PlainMonthDay.prototype is %Temporal.PlainMonthDay.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

10.2.2 Temporal.PlainMonthDay.from ( item [ , options ] )

This function performs the following steps when called:

  1. Set options to ? GetOptionsObject(options).
  2. If Type(item) is Object and item has an [[InitializedTemporalMonthDay]] internal slot, then
    1. Perform ? ToTemporalOverflow(options).
    2. Return ! CreateTemporalMonthDay(item.[[ISOMonth]], item.[[ISODay]], item.[[Calendar]], item.[[ISOYear]]).
  3. Return ? ToTemporalMonthDay(item, options).

10.3 Properties of the Temporal.PlainMonthDay Prototype Object

The Temporal.PlainMonthDay prototype object

  • is itself an ordinary object.
  • is not a Temporal.PlainMonthDay instance and does not have a [[InitializedTemporalMonthDay]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

10.3.1 Temporal.PlainMonthDay.prototype.constructor

The initial value of Temporal.PlainMonthDay.prototype.constructor is %Temporal.PlainMonthDay%.

10.3.2 Temporal.PlainMonthDay.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.PlainMonthDay".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

10.3.3 get Temporal.PlainMonthDay.prototype.calendarId

Temporal.PlainMonthDay.prototype.calendarId is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Return ? ToTemporalCalendarIdentifier(monthDay.[[Calendar]]).

10.3.4 get Temporal.PlainMonthDay.prototype.monthCode

Temporal.PlainMonthDay.prototype.monthCode is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Let calendar be monthDay.[[Calendar]].
  4. Return ? CalendarMonthCode(calendar, monthDay).

10.3.5 get Temporal.PlainMonthDay.prototype.day

Temporal.PlainMonthDay.prototype.day is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Let calendarRec be ? CreateCalendarMethodsRecord(monthDay.[[Calendar]], « day »).
  4. Return 𝔽(? CalendarDay(calendarRec, monthDay)).

10.3.6 Temporal.PlainMonthDay.prototype.with ( temporalMonthDayLike [ , options ] )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. If ? IsPartialTemporalObject(temporalMonthDayLike) is false, throw a TypeError exception.
  4. Let resolvedOptions be ? SnapshotOwnProperties(? GetOptionsObject(options), null).
  5. Let calendarRec be ? CreateCalendarMethodsRecord(monthDay.[[Calendar]], « fields, merge-fields, month-day-from-fields »).
  6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
  7. Let fields be ? PrepareTemporalFields(monthDay, fieldNames, «»).
  8. Let partialMonthDay be ? PrepareTemporalFields(temporalMonthDayLike, fieldNames, partial).
  9. Set fields to ? CalendarMergeFields(calendarRec, fields, partialMonthDay).
  10. Set fields to ? PrepareTemporalFields(fields, fieldNames, «»).
  11. Return ? CalendarMonthDayFromFields(calendarRec, fields, resolvedOptions).

10.3.7 Temporal.PlainMonthDay.prototype.equals ( other )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Set other to ? ToTemporalMonthDay(other).
  4. If monthDay.[[ISOMonth]]other.[[ISOMonth]], return false.
  5. If monthDay.[[ISODay]]other.[[ISODay]], return false.
  6. If monthDay.[[ISOYear]]other.[[ISOYear]], return false.
  7. Return ? CalendarEquals(monthDay.[[Calendar]], other.[[Calendar]]).

10.3.8 Temporal.PlainMonthDay.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Set options to ? GetOptionsObject(options).
  4. Let showCalendar be ? ToCalendarNameOption(options).
  5. Return ? TemporalMonthDayToString(monthDay, showCalendar).

10.3.9 Temporal.PlainMonthDay.prototype.toLocaleString ( [ locales [ , options ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Return ? TemporalMonthDayToString(monthDay, "auto").

10.3.10 Temporal.PlainMonthDay.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Return ? TemporalMonthDayToString(monthDay, "auto").

10.3.11 Temporal.PlainMonthDay.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.

10.3.12 Temporal.PlainMonthDay.prototype.toPlainDate ( item )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. If Type(item) is not Object, then
    1. Throw a TypeError exception.
  4. Let calendarRec be ? CreateCalendarMethodsRecord(monthDay.[[Calendar]], « date-from-fields, fields, merge-fields »).
  5. Let receiverFieldNames be ? CalendarFields(calendarRec, « "day", "monthCode" »).
  6. Let fields be ? PrepareTemporalFields(monthDay, receiverFieldNames, «»).
  7. Let inputFieldNames be ? CalendarFields(calendarRec, « "year" »).
  8. Let inputFields be ? PrepareTemporalFields(item, inputFieldNames, «»).
  9. Let mergedFields be ? CalendarMergeFields(calendarRec, fields, inputFields).
  10. Let concatenatedFieldNames be the list-concatenation of receiverFieldNames and inputFieldNames.
  11. Set mergedFields to ? PrepareTemporalFields(mergedFields, concatenatedFieldNames, «», «», ignore).
  12. Let options be OrdinaryObjectCreate(null).
  13. Perform ! CreateDataPropertyOrThrow(options, "overflow", "constrain").
  14. Return ? CalendarDateFromFields(calendarRec, mergedFields, options).

10.3.13 Temporal.PlainMonthDay.prototype.getISOFields ( )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Let fields be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(fields, "calendar", monthDay.[[Calendar]]).
  5. Perform ! CreateDataPropertyOrThrow(fields, "isoDay", 𝔽(monthDay.[[ISODay]])).
  6. Perform ! CreateDataPropertyOrThrow(fields, "isoMonth", 𝔽(monthDay.[[ISOMonth]])).
  7. Perform ! CreateDataPropertyOrThrow(fields, "isoYear", 𝔽(monthDay.[[ISOYear]])).
  8. Return fields.

10.3.14 Temporal.PlainMonthDay.prototype.getCalendar ( )

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Return ToTemporalCalendarObject(monthDay.[[Calendar]]).

10.4 Properties of Temporal.PlainMonthDay Instances

Temporal.PlainMonthDay instances are ordinary objects that inherit properties from the %Temporal.PlainMonthDay.prototype% intrinsic object. Temporal.PlainMonthDay instances are initially created with the internal slots described in Table 15.

Table 15: Internal Slots of Temporal.PlainMonthDay Instances
Internal Slot Description
[[InitializedTemporalMonthDay]] The only specified use of this slot is for distinguishing Temporal.PlainMonthDay instances from other objects.
[[ISOYear]] An integer representing the year in the ISO 8601 calendar. This slot is used by the calendar object in the [[Calendar]] slot to disambiguate if the [[ISOMonth]] and [[ISODay]] slots are not enough to uniquely identify a month and day in that calendar.
[[ISOMonth]] An integer between 1 and 12, inclusive, representing the month of the year in the ISO 8601 calendar.
[[ISODay]] An integer between 1 and ISODaysInMonth([[ISOYear]], [[ISOMonth]]), inclusive, representing the day of the month in the ISO 8601 calendar.
[[Calendar]] A String or Object representing the calendar.

10.5 Abstract Operations

10.5.1 ToTemporalMonthDay ( item [ , options ] )

The abstract operation ToTemporalMonthDay takes argument item (an ECMAScript language value) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainMonthDay, or a throw completion. It returns its argument item if it is already a Temporal.PlainMonthDay instance, converts item to a new Temporal.PlainMonthDay instance if possible, and throws otherwise. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. If options is not undefined, set options to ? SnapshotOwnProperties(! GetOptionsObject(options), null).
  3. If Type(item) is Object, then
    1. If item has an [[InitializedTemporalMonthDay]] internal slot, then
      1. Return item.
    2. If item has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let calendar be item.[[Calendar]].
    3. Else,
      1. Let calendarLike be ? Get(item, "calendar").
      2. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
    4. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « fields, month-day-from-fields »).
    5. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
    6. Let fields be ? PrepareTemporalFields(item, fieldNames, «»).
    7. Return ? CalendarMonthDayFromFields(calendarRec, fields, options).
  4. If item is not a String, throw a TypeError exception.
  5. Let result be ? ParseTemporalMonthDayString(item).
  6. Let calendar be result.[[Calendar]].
  7. If calendar is undefined, set calendar to "iso8601".
  8. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
  9. Set calendar to the ASCII-lowercase of calendar.
  10. Perform ? ToTemporalOverflow(options).
  11. If result.[[Year]] is undefined, then
    1. Assert: calendar is "iso8601".
    2. Let referenceISOYear be 1972 (the first ISO 8601 leap year after the epoch).
    3. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, referenceISOYear).
  12. Set result to ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar, result.[[Year]]).
  13. Let calendarRec be ! CreateCalendarMethodsRecord(calendar, « month-day-from-fields »).
  14. NOTE: The following operation is called without options, in order for the calendar to store a canonical value in the [[ISOYear]] internal slot of the result.
  15. Return ? CalendarMonthDayFromFields(calendarRec, result).

10.5.2 CreateTemporalMonthDay ( isoMonth, isoDay, calendar, referenceISOYear [ , newTarget ] )

The abstract operation CreateTemporalMonthDay takes arguments isoMonth (an integer), isoDay (an integer), calendar (a String or Object), and referenceISOYear (an integer) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainMonthDay, or an abrupt completion. It creates a Temporal.PlainMonthDay instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If IsValidISODate(referenceISOYear, isoMonth, isoDay) is false, throw a RangeError exception.
  2. If ISODateTimeWithinLimits(referenceISOYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0) is false, throw a RangeError exception.
  3. If newTarget is not present, set newTarget to %Temporal.PlainMonthDay%.
  4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainMonthDay.prototype%", « [[InitializedTemporalMonthDay]], [[ISOMonth]], [[ISODay]], [[ISOYear]], [[Calendar]] »).
  5. Set object.[[ISOMonth]] to isoMonth.
  6. Set object.[[ISODay]] to isoDay.
  7. Set object.[[Calendar]] to calendar.
  8. Set object.[[ISOYear]] to referenceISOYear.
  9. Return object.
Note

Deferring to ISODateTimeWithinLimits with an hour of 12 avoids trouble at the extremes of the representable range of dates, which stop just before midnight on each end.

10.5.3 TemporalMonthDayToString ( monthDay, showCalendar )

  1. Assert: Type(monthDay) is Object.
  2. Assert: monthDay has an [[InitializedTemporalMonthDay]] internal slot.
  3. Let month be ToZeroPaddedDecimalString(monthDay.[[ISOMonth]], 2).
  4. Let day be ToZeroPaddedDecimalString(monthDay.[[ISODay]], 2).
  5. Let result be the string-concatenation of month, the code unit 0x002D (HYPHEN-MINUS), and day.
  6. Let calendarIdentifier be ? ToTemporalCalendarIdentifier(monthDay.[[Calendar]]).
  7. If showCalendar is one of "always" or "critical", or if calendarIdentifier is not "iso8601", then
    1. Let year be PadISOYear(monthDay.[[ISOYear]]).
    2. Set result to the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and result.
  8. Let calendarString be FormatCalendarAnnotation(calendarIdentifier, showCalendar).
  9. Set result to the string-concatenation of result and calendarString.
  10. Return result.

11 Temporal.TimeZone Objects

A Temporal.TimeZone object is an Object referencing a time zone.

11.1 The Temporal.TimeZone Constructor

The Temporal.TimeZone constructor:

  • creates and initializes a new Temporal.TimeZone object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.TimeZone behaviour must include a super call to the %Temporal.TimeZone% constructor to create and initialize subclass instances with the necessary internal slots.

11.1.1 Temporal.TimeZone ( identifier )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If identifier is not a String, throw a TypeError exception.
  3. Let parseResult be ? ParseTimeZoneIdentifier(identifier).
  4. If parseResult.[[OffsetMinutes]] is not empty, then
    1. Set identifier to FormatOffsetTimeZoneIdentifier(parseResult.[[OffsetMinutes]]).
  5. Else,
    1. Let timeZoneIdentifierRecord be GetAvailableNamedTimeZoneIdentifier(identifier).
    2. If timeZoneIdentifierRecord is empty, throw a RangeError exception.
    3. Set identifier to timeZoneIdentifierRecord.[[Identifier]].
  6. Return ? CreateTemporalTimeZone(identifier, NewTarget).

11.2 Properties of the Temporal.TimeZone Constructor

The value of the [[Prototype]] internal slot of the Temporal.TimeZone constructor is the intrinsic object %Function.prototype%.

The Temporal.TimeZone constructor has the following properties:

11.2.1 Temporal.TimeZone.prototype

The initial value of Temporal.TimeZone.prototype is %Temporal.TimeZone.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

11.2.2 Temporal.TimeZone.from ( item )

This function performs the following steps when called:

  1. Let slotValue be ? ToTemporalTimeZoneSlotValue(item).
  2. Return ToTemporalTimeZoneObject(slotValue).

11.3 Properties of the Temporal.TimeZone Prototype Object

The Temporal.TimeZone prototype object

  • is itself an ordinary object.
  • is not a Temporal.TimeZone instance and does not have a [[InitializedTemporalTimeZone]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.

11.3.1 Temporal.TimeZone.prototype.constructor

The initial value of Temporal.TimeZone.prototype.constructor is %Temporal.TimeZone%.

11.3.2 Temporal.TimeZone.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.TimeZone".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

11.3.3 get Temporal.TimeZone.prototype.id

Temporal.TimeZone.prototype.id is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. If timeZone.[[OffsetMinutes]] is not empty, return FormatOffsetTimeZoneIdentifier(timeZone.[[OffsetMinutes]]).
  4. Return timeZone.[[Identifier]].

11.3.4 Temporal.TimeZone.prototype.equals ( timeZoneLike )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Let other be ? ToTemporalTimeZoneSlotValue(timeZoneLike).
  4. Return ? TimeZoneEquals(timeZone, other).

11.3.5 Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( instant )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set instant to ? ToTemporalInstant(instant).
  4. If timeZone.[[OffsetMinutes]] is not empty, return 𝔽(timeZone.[[OffsetMinutes]] × (60 × 109)).
  5. Return 𝔽(GetNamedTimeZoneOffsetNanoseconds(timeZone.[[Identifier]], instant.[[Nanoseconds]])).

11.3.6 Temporal.TimeZone.prototype.getOffsetStringFor ( instant )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set instant to ? ToTemporalInstant(instant).
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for »).
  5. Return ? GetOffsetStringFor(timeZoneRec, instant).

11.3.7 Temporal.TimeZone.prototype.getPlainDateTimeFor ( instant [ , calendarLike ] )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set instant to ? ToTemporalInstant(instant).
  4. Let calendar be ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for »).
  6. Return ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).

11.3.8 Temporal.TimeZone.prototype.getInstantFor ( dateTime [ , options ] )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set dateTime to ? ToTemporalDateTime(dateTime).
  4. Set options to ? GetOptionsObject(options).
  5. Let disambiguation be ? ToTemporalDisambiguation(options).
  6. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  7. Return ? GetInstantFor(timeZoneRec, dateTime, disambiguation).

11.3.9 Temporal.TimeZone.prototype.getPossibleInstantsFor ( dateTime )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set dateTime to ? ToTemporalDateTime(dateTime).
  4. If timeZone.[[OffsetMinutes]] is not empty, then
    1. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], timeZone.[[OffsetMinutes]] × (60 × 109)).
    2. Let possibleEpochNanoseconds be « epochNanoseconds ».
  5. Else,
    1. Let possibleEpochNanoseconds be GetNamedTimeZoneEpochNanoseconds(timeZone.[[Identifier]], dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).
  6. Let possibleInstants be a new empty List.
  7. For each value epochNanoseconds in possibleEpochNanoseconds, do
    1. If IsValidEpochNanoseconds(epochNanoseconds) is false, throw a RangeError exception.
    2. Let instant be ! CreateTemporalInstant(epochNanoseconds).
    3. Append instant to possibleInstants.
  8. Return CreateArrayFromList(possibleInstants).

11.3.10 Temporal.TimeZone.prototype.getNextTransition ( startingPoint )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set startingPoint to ? ToTemporalInstant(startingPoint).
  4. If timeZone.[[OffsetMinutes]] is not empty, return null.
  5. Let transition be GetNamedTimeZoneNextTransition(timeZone.[[Identifier]], startingPoint.[[Nanoseconds]]).
  6. If transition is null, return null.
  7. Return ! CreateTemporalInstant(transition).

11.3.11 Temporal.TimeZone.prototype.getPreviousTransition ( startingPoint )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. Set startingPoint to ? ToTemporalInstant(startingPoint).
  4. If timeZone.[[OffsetMinutes]] is not empty, return null.
  5. Let transition be GetNamedTimeZonePreviousTransition(timeZone.[[Identifier]], startingPoint.[[Nanoseconds]]).
  6. If transition is null, return null.
  7. Return ! CreateTemporalInstant(transition).

11.3.12 Temporal.TimeZone.prototype.toString ( )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. If timeZone.[[OffsetMinutes]] is not empty, return FormatOffsetTimeZoneIdentifier(timeZone.[[OffsetMinutes]]).
  4. Return timeZone.[[Identifier]].

11.3.13 Temporal.TimeZone.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let timeZone be the this value.
  2. Perform ? RequireInternalSlot(timeZone, [[InitializedTemporalTimeZone]]).
  3. If timeZone.[[OffsetMinutes]] is not empty, return FormatOffsetTimeZoneIdentifier(timeZone.[[OffsetMinutes]]).
  4. Return timeZone.[[Identifier]].

11.4 Properties of Temporal.TimeZone Instances

Temporal.TimeZone instances are ordinary objects that inherit properties from the %Temporal.TimeZone.prototype% intrinsic object. Temporal.TimeZone instances are initially created with the internal slots described in Table 16.

Table 16: Internal Slots of Temporal.TimeZone Instances
Internal Slot Description
[[InitializedTemporalTimeZone]] The only specified use of this slot is for distinguishing Temporal.TimeZone instances from other objects.
[[Identifier]] A String value representing the identifier of an available named time zone, or empty if the instance represents an offset time zone.
[[OffsetMinutes]] An integer for minutes representing the constant offset of this time zone relative to UTC, or empty if the instance represents a named time zone. If not empty, this value must be in the interval from -1440 (exclusive) to 1440 (exclusive) (i.e., strictly less than 24 hours in magnitude).

11.5 Abstract Operations

Editor's Note
In ECMA-262, many time-zone-related sections and abstract operations are contained in the Date Objects section of the specification. Now that ECMAScript has a built-in %Temporal.TimeZone% object, it may be appropriate to move those sections here, for example:

11.5.1 Time Zone Methods Records

A Time Zone Methods Record is a Record value used to store a Temporal.TimeZone object, or an Object implementing the time zone protocol, along with any methods that have been observably looked up on that object during the current operation. Time Zone Methods Records are produced by the abstract operation CreateTimeZoneMethodsRecord.

Time Zone Methods Records have the fields listed in Table 17.

Table 17: Time Zone Methods Record Fields
Field Name Value Meaning
[[Receiver]] a String or Object The time zone object, or a string indicating a built-in time zone.
[[GetOffsetNanosecondsFor]] a function object or undefined The time zone's getOffsetNanosecondsFor method. For a built-in time zone this is always %Temporal.TimeZone.prototype.getOffsetNanosecondsFor%.
[[GetPossibleInstantsFor]] a function object or undefined The time zone's getPossibleInstantsFor method. For a built-in time zone this is always %Temporal.TimeZone.prototype.getPossibleInstantsFor%.

11.5.2 CreateTimeZoneMethodsRecord ( timeZone, methods )

The abstract operation CreateTimeZoneMethodsRecord takes arguments timeZone (a String or Object) and methods (a List of either get-offset-nanoseconds-for or get-possible-instants-for) and returns either a normal completion containing a Time Zone Methods Record, or a throw completion. It creates a Time Zone Methods Record from the given timeZone, looking up the methods given in methods. It performs the following steps when called:

  1. Let record be the Time Zone Methods Record { [[Receiver]]: timeZone, [[GetOffsetNanosecondsFor]]: undefined, [[GetPossibleInstantsFor]]: undefined  }.
  2. For each element methodName in methods, do
    1. Perform ? TimeZoneMethodsRecordLookup(record, methodName).
  3. Return record.

11.5.3 TimeZoneMethodsRecordLookup ( timeZoneRec, methodName )

The abstract operation TimeZoneMethodsRecordLookup takes arguments timeZoneRec (a Time Zone Methods Record) and methodName (get-offset-nanoseconds-for or get-possible-instants-for) and returns either a normal completion containing unused, or a throw completion. It looks up the given method on the given time zone. For a built-in time zone, this lookup is unobservable and results in the intrinsic method. If the time zone is an Object, the lookup is observable and may result in a user-code method. It performs the following steps when called:

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, methodName) is false.
  2. If methodName is get-offset-nanoseconds-for, then
    1. If timeZoneRec.[[Receiver]] is a String, then
      1. Set timeZoneRec.[[GetOffsetNanosecondsFor]] to %Temporal.TimeZone.prototype.getOffsetNanosecondsFor%.
    2. Else,
      1. Set timeZoneRec.[[GetOffsetNanosecondsFor]] to ? GetMethod(timeZoneRec.[[Receiver]], "getOffsetNanosecondsFor").
      2. If timeZoneRec.[[GetOffsetNanosecondsFor]] is undefined, throw a TypeError exception.
  3. Else if methodName is get-possible-instants-for, then
    1. If timeZoneRec.[[Receiver]] is a String, then
      1. Set timeZoneRec.[[GetPossibleInstantsFor]] to %Temporal.TimeZone.prototype.getPossibleInstantsFor%.
    2. Else,
      1. Set timeZoneRec.[[GetPossibleInstantsFor]] to ? GetMethod(timeZoneRec.[[Receiver]], "getPossibleInstantsFor").
      2. If timeZoneRec.[[GetPossibleInstantsFor]] is undefined, throw a TypeError exception.
  4. Return unused.

11.5.4 TimeZoneMethodsRecordHasLookedUp ( timeZoneRec, methodName )

The abstract operation TimeZoneMethodsRecordHasLookedUp takes arguments timeZoneRec (a Time Zone Methods Record) and methodName (get-offset-nanoseconds-for or get-possible-instants-for) and returns true or false. It determines whether the given Time Zone Methods Record has already looked up the given method. It performs the following steps when called:

  1. If methodName is get-offset-nanoseconds-for, then
    1. Let method be timeZoneRec.[[GetOffsetNanosecondsFor]].
  2. Else if methodName is get-possible-instants-for, then
    1. Let method be timeZoneRec.[[GetPossibleInstantsFor]].
  3. If method is undefined, return false.
  4. Return true.

11.5.5 TimeZoneMethodsRecordIsBuiltin ( timeZoneRec )

The abstract operation TimeZoneMethodsRecordIsBuiltin takes argument timeZoneRec (a Time Zone Methods Record) and returns true or false. It determines whether the given Time Zone Methods Record represents a built-in time zone (that is never exposed to user code.) It performs the following steps when called:

  1. If timeZoneRec.[[Receiver]] is a String, return true.
  2. Return false.

11.5.6 TimeZoneMethodsRecordCall ( timeZoneRec, methodName, arguments )

The abstract operation TimeZoneMethodsRecordCall takes arguments timeZoneRec (a Time Zone Methods Record), methodName (get-offset-nanoseconds-for or get-possible-instants-for), and arguments (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value, or a throw completion. It calls the method methodName stored in the Time Zone Methods Record, with the stored receiver as the receiver, and the given arguments, and returns the result. It performs the following steps when called:

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, methodName) is true.
  2. Let receiver be timeZoneRec.[[Receiver]].
  3. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec) is true, then
    1. Set receiver to ! CreateTemporalTimeZone(timeZoneRec.[[Receiver]]).
  4. If methodName is get-offset-nanoseconds-for, then
    1. Return ? Call(timeZoneRec.[[GetOffsetNanosecondsFor]], receiver, arguments).
  5. If methodName is get-possible-instants-for, then
    1. Return ? Call(timeZoneRec.[[GetPossibleInstantsFor]], receiver, arguments).

11.5.7 CreateTemporalTimeZone ( identifier [ , newTarget ] )

The abstract operation CreateTemporalTimeZone takes argument identifier (a String) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.TimeZone, or an abrupt completion. It creates a new Temporal.TimeZone instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If newTarget is not present, set newTarget to %Temporal.TimeZone%.
  2. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.TimeZone.prototype%", « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetMinutes]] »).
  3. Assert: identifier is an available named time zone identifier or an offset time zone identifier.
  4. Let parseResult be ! ParseTimeZoneIdentifier(identifier).
  5. If parseResult.[[OffsetMinutes]] is not empty, then
    1. Set object.[[Identifier]] to empty.
    2. Set object.[[OffsetMinutes]] to parseResult.[[OffsetMinutes]].
  6. Else,
    1. Assert: parseResult.[[Name]] is not empty.
    2. Assert: GetAvailableNamedTimeZoneIdentifier(identifier).[[Identifier]] is identifier.
    3. Set object.[[Identifier]] to identifier.
    4. Set object.[[OffsetMinutes]] to empty.
  7. Return object.
Note

Most implementations support only a short, fixed list of available named time zone identifiers. For example, the IANA Time Zone Database in 2022 contained fewer than 600 identifiers. Although the [[Identifier]] internal slot is a String in this specification, implementations may choose to store named time zone identifiers it in any other form (for example as an enumeration or index into a List of identifier strings) as long as the String can be regenerated when needed.

Similar flexibility exists for the storage of the [[OffsetMinutes]] internal slot, which can be interchangeably represented as a 12-bit signed integer or as a 6-character ±HH:MM String value. ParseTimeZoneIdentifier and FormatOffsetTimeZoneIdentifier may be used to losslessly convert one representation to the other. Implementations are free to store either or both representations.

11.5.8 GetAvailableNamedTimeZoneIdentifier ( timeZoneIdentifier )

The abstract operation GetAvailableNamedTimeZoneIdentifier takes argument timeZoneIdentifier (a String) and returns either a Time Zone Identifier Record or empty. If timeZoneIdentifier is an available named time zone identifier, then it returns one of the records in the List returned by AvailableNamedTimeZoneIdentifiers. Otherwise, empty will be returned. It performs the following steps when called:

  1. For each element record of AvailableNamedTimeZoneIdentifiers(), do
    1. If record.[[Identifier]] is an ASCII-case-insensitive match for timeZoneIdentifier, return record.
  2. Return empty.
Note

For any timeZoneIdentifier, or any value that is an ASCII-case-insensitive match for it, the result of this operation must remain the same for the lifetime of the surrounding agent. Specifically, if that result is a Time Zone Identifier Record, its fields must contain the same values.

Furthermore, time zone identifiers must not dynamically change from primary to non-primary or vice versa during the lifetime of the surrounding agent, meaning that if timeZoneIdentifier is an ASCII-case-insensitive match for the [[PrimaryIdentifier]] field of the result of a previous call to GetAvailableNamedTimeZoneIdentifier, then GetAvailableNamedTimeZoneIdentifier(timeZoneIdentifier) must return a record where [[Identifier]] is [[PrimaryIdentifier]].

Due to the complexity of supporting these requirements, it is recommended that the result of AvailableNamedTimeZoneIdentifiers (and therefore GetAvailableNamedTimeZoneIdentifier) remains the same for the lifetime of the surrounding agent.

11.5.9 GetISOPartsFromEpoch ( epochNanoseconds )

The abstract operation GetISOPartsFromEpoch takes argument epochNanoseconds (an integer). It returns the components of a date in UTC corresponding to the given number of nanoseconds since the epoch. It performs the following steps when called:

  1. Assert: ! IsValidEpochNanoseconds((epochNanoseconds)) is true.
  2. Let remainderNs be epochNanoseconds modulo 106.
  3. Let epochMilliseconds be 𝔽((epochNanoseconds - remainderNs) / 106).
  4. Let year be EpochTimeToEpochYear(epochMilliseconds).
  5. Let month be EpochTimeToMonthInYear(epochMilliseconds) + 1.
  6. Let day be EpochTimeToDate(epochMilliseconds).
  7. Let hour be (HourFromTime(epochMilliseconds)).
  8. Let minute be (MinFromTime(epochMilliseconds)).
  9. Let second be (SecFromTime(epochMilliseconds)).
  10. Let millisecond be (msFromTime(epochMilliseconds)).
  11. Let microsecond be floor(remainderNs / 1000).
  12. Assert: microsecond < 1000.
  13. Let nanosecond be remainderNs modulo 1000.
  14. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond  }.

11.5.10 GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZoneNextTransition takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns a BigInt or null.

The returned value t represents the number of nanoseconds since the epoch that corresponds to the first time zone transition after epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which t(nsMaxInstant).

A transition is a point in time where the UTC offset of a time zone changes, for example when Daylight Saving Time starts or stops. The returned value t represents the first nanosecond where the new UTC offset is used in this time zone, not the last nanosecond where the previous UTC offset is used.

Given the same values of timeZoneIdentifier and epochNanoseconds, the result must be the same for the lifetime of the surrounding agent.

The minimum implementation of GetNamedTimeZoneNextTransition for ECMAScript implementations that do not include local political rules for any time zones performs the following steps when called:

  1. Assert: timeZoneIdentifier is "UTC".
  2. Return null.

11.5.11 GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZonePreviousTransition takes arguments timeZoneIdentifier (a String) and epochNanoseconds (a BigInt) and returns a BigInt or null.

The returned value t represents the number of nanoseconds since the epoch that corresponds to the last time zone transition before epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which t(nsMinInstant).

A transition is a point in time where the UTC offset of a time zone changes, for example when Daylight Saving Time starts or stops. The returned value t represents the first nanosecond where the new UTC offset is used in this time zone, not the last nanosecond where the previous UTC offset is used.

Given the same values of timeZoneIdentifier and epochNanoseconds, the result must be the same for the lifetime of the surrounding agent.

The minimum implementation of GetNamedTimeZonePreviousTransition for ECMAScript implementations that do not include local political rules for any time zones performs the following steps when called:

  1. Assert: timeZoneIdentifier is "UTC".
  2. Return null.

11.5.12 FormatOffsetTimeZoneIdentifier ( offsetMinutes [ , style ] )

The abstract operation FormatOffsetTimeZoneIdentifier takes argument offsetMinutes (an integer) and optional argument style (separated or unseparated) and returns a String. It formats a UTC offset, in minutes, into a UTC offset string. If style is separated or not present, then the output will be formatted like ±HH:MM. If style is unseparated, then the output will be formatted like ±HHMM. It performs the following steps when called:

  1. If offsetMinutes ≥ 0, let sign be the code unit 0x002B (PLUS SIGN); otherwise, let sign be the code unit 0x002D (HYPHEN-MINUS).
  2. Let absoluteMinutes be abs(offsetMinutes).
  3. Let hour be floor(absoluteMinutes / 60).
  4. Let minute be absoluteMinutes modulo 60.
  5. Let timeString be FormatTimeString(hour, minute, 0, 0, "minute", style).
  6. Return the string-concatenation of sign and timeString.

11.5.13 FormatUTCOffsetNanoseconds ( offsetNanoseconds )

The abstract operation FormatUTCOffsetNanoseconds takes argument offsetNanoseconds (an integer) and returns a String. If the offset represents an integer number of minutes, then the output will be formatted like ±HH:MM. Otherwise, the output will be formatted like ±HH:MM:SS or (if the offset does not evenly divide into seconds) ±HH:MM:SS.fff… where the "fff" part is a sequence of at least 1 and at most 9 fractional seconds digits with no trailing zeroes. It performs the following steps when called:

  1. If offsetNanoseconds ≥ 0, let sign be the code unit 0x002B (PLUS SIGN); otherwise, let sign be the code unit 0x002D (HYPHEN-MINUS).
  2. Let absoluteNanoseconds be abs(offsetNanoseconds).
  3. Let hour be floor(absoluteNanoseconds / (3600 × 109)).
  4. Let minute be floor(absoluteNanoseconds / (60 × 109)) modulo 60.
  5. Let second be floor(absoluteNanoseconds / 109) modulo 60.
  6. Let subSecondNanoseconds be absoluteNanoseconds modulo 109.
  7. If second = 0 and subSecondNanoseconds = 0, let precision be "minute"; otherwise, let precision be "auto".
  8. Let timeString be FormatTimeString(hour, minute, second, subSecondNanoseconds, precision).
  9. Return the string-concatenation of sign and timeString.

11.5.14 FormatDateTimeUTCOffsetRounded ( offsetNanoseconds )

The abstract operation FormatDateTimeUTCOffsetRounded takes argument offsetNanoseconds (an integer) and returns a String. It rounds offsetNanoseconds to the nearest minute boundary and formats the rounded value into a ±HH:MM format, to support available named time zones that may have sub-minute offsets. It performs the following steps when called:

  1. Set offsetNanoseconds to RoundNumberToIncrement(offsetNanoseconds, 60 × 109, "halfExpand").
  2. Let offsetMinutes be offsetNanoseconds / (60 × 109).
  3. Assert: offsetMinutes is an integer.
  4. Return FormatOffsetTimeZoneIdentifier(offsetMinutes).

11.5.15 ObjectImplementsTemporalTimeZoneProtocol ( object )

The abstract operation ObjectImplementsTemporalTimeZoneProtocol takes argument object (an Object) and returns either a normal completion containing a Boolean, or a throw completion. It determines whether the given object is a Temporal.TimeZone instance or implements the required methods from the Temporal.TimeZone protocol. For ordinary objects, and some exotic objects, this operation is infallible and will always return a normal completion. However, if object is a Proxy or has one in its prototype chain, user code may be called. It performs the following steps when called:

  1. If object has an [[InitializedTemporalTimeZone]] internal slot, return true.
  2. For each property key key of « "getOffsetNanosecondsFor", "getPossibleInstantsFor", "id" », do
    1. If ? HasProperty(object, key) is false, return false.
  3. Return true.
Note
This operation is a convenience which makes it easier to catch bugs in custom time zones. For web compatibility reasons, the list of required property keys will not be extended in future editions, even if the Temporal.TimeZone protocol gains more methods.

11.5.16 ToTemporalTimeZoneSlotValue ( temporalTimeZoneLike )

The abstract operation ToTemporalTimeZoneSlotValue takes argument temporalTimeZoneLike (an ECMAScript value) and returns either a normal completion containing either a String or an Object, or a throw completion. It attempts to derive a value from temporalTimeZoneLike that is suitable for storing in a Temporal.ZonedDateTime's [[TimeZone]] internal slot, and returns that value if found or throws an exception if not. It performs the following steps when called:

  1. If Type(temporalTimeZoneLike) is Object, then
    1. If temporalTimeZoneLike has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return temporalTimeZoneLike.[[TimeZone]].
    2. If ? ObjectImplementsTemporalTimeZoneProtocol(temporalTimeZoneLike) is false, throw a TypeError exception.
    3. Return temporalTimeZoneLike.
  2. If temporalTimeZoneLike is not a String, throw a TypeError exception.
  3. Let parseResult be ? ParseTemporalTimeZoneString(temporalTimeZoneLike).
  4. Let offsetMinutes be parseResult.[[OffsetMinutes]].
  5. If offsetMinutes is not empty, return FormatOffsetTimeZoneIdentifier(offsetMinutes).
  6. Let name be parseResult.[[Name]].
  7. Let timeZoneIdentifierRecord be GetAvailableNamedTimeZoneIdentifier(name).
  8. If timeZoneIdentifierRecord is empty, throw a RangeError exception.
  9. Return timeZoneIdentifierRecord.[[Identifier]].

11.5.17 ToTemporalTimeZoneIdentifier ( timeZoneSlotValue )

The abstract operation ToTemporalTimeZoneIdentifier takes argument timeZoneSlotValue (a String or Object) and returns either a normal completion containing a String, or a throw completion. It obtains the identifier string for a value timeZoneSlotValue stored in a Temporal.ZonedDateTime's [[TimeZone]] internal slot. It performs the following steps when called:

  1. If timeZoneSlotValue is a String, then
    1. Assert: Either IsOffsetTimeZoneIdentifier(timeZoneSlotValue) is true, or GetAvailableNamedTimeZoneIdentifier(timeZoneSlotValue) is not empty.
    2. Return timeZoneSlotValue.
  2. Let identifier be ? Get(timeZoneSlotValue, "id").
  3. If identifier is not a String, throw a TypeError exception.
  4. Return identifier.

11.5.18 ToTemporalTimeZoneObject ( timeZoneSlotValue )

The abstract operation ToTemporalTimeZoneObject takes argument timeZoneSlotValue (a String or Object) and returns an Object. It obtains a time zone object for a value timeZoneSlotValue stored in a Temporal.ZonedDateTime's [[TimeZone]] internal slot. It performs the following steps when called:

  1. If timeZoneSlotValue is an Object, return timeZoneSlotValue.
  2. Return ! CreateTemporalTimeZone(timeZoneSlotValue).

11.5.19 GetOffsetNanosecondsFor ( timeZoneRec, instant )

The abstract operation GetOffsetNanosecondsFor takes arguments timeZoneRec (a Time Zone Methods Record) and instant (a Temporal.Instant) and returns either a normal completion containing an integer, or an abrupt completion. It determines the UTC offset of an instant, in nanoseconds, by calling the getOffsetNanosecondsFor method of the given time zone. It performs the following steps when called:

  1. Let offsetNanoseconds be ? TimeZoneMethodsRecordCall(timeZoneRec, get-offset-nanoseconds-for, « instant »).
  2. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec), return (offsetNanoseconds).
  3. If Type(offsetNanoseconds) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(offsetNanoseconds) is false, throw a RangeError exception.
  5. Set offsetNanoseconds to (offsetNanoseconds).
  6. If abs(offsetNanoseconds) ≥ nsPerDay, throw a RangeError exception.
  7. Return offsetNanoseconds.

11.5.20 GetOffsetStringFor ( timeZoneRec, instant )

The abstract operation GetOffsetStringFor takes arguments timeZoneRec (a Time Zone Methods Record) and instant (a Temporal.Instant) and returns either a normal completion containing a String, or an abrupt completion. This operation is the internal implementation of the Temporal.TimeZone.prototype.getOffsetStringFor method. If the given time zone is not built-in, it observably calls the time zone's getOffsetNanosecondsFor method. It performs the following steps when called:

  1. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  2. Return FormatUTCOffsetNanoseconds(offsetNanoseconds).

11.5.21 GetPlainDateTimeFor ( timeZoneRec, instant, calendar [ , precalculatedOffsetNanoseconds ] )

The abstract operation GetPlainDateTimeFor takes arguments timeZoneRec (a Time Zone Methods Record), instant (a Temporal.Instant), and calendar (a String or Object) and optional argument precalculatedOffsetNanoseconds (an integer) and returns either a normal completion containing a Temporal.PlainDateTime, or an abrupt completion. This operation is the internal implementation of the Temporal.TimeZone.prototype.getPlainDateTimeFor method. If the given time zone is not built-in, it observably calls timeZone's getOffsetNanosecondsFor method unless precalculatedOffsetNanoseconds is supplied. It performs the following steps when called:

  1. Assert: If precalculatedOffsetNanoseconds is not present, TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  2. If precalculatedOffsetNanoseconds is present, let offsetNanoseconds be precalculatedOffsetNanoseconds.
  3. Else, let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZoneRec, instant).
  4. Assert: abs(offsetNanoseconds) < nsPerDay.
  5. Let result be ! GetISOPartsFromEpoch((instant.[[Nanoseconds]])).
  6. Set result to BalanceISODateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]] + offsetNanoseconds).
  7. Return ! CreateTemporalDateTime(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], calendar).

11.5.22 GetInstantFor ( timeZoneRec, dateTime, disambiguation )

The abstract operation GetInstantFor takes arguments timeZoneRec (a Time Zone Methods Record), dateTime (a Temporal.PlainDateTime), and disambiguation ("compatible", "earlier", "later", or "reject") and returns either a normal completion containing a Temporal.Instant, or an abrupt completion. It is the internal implementation of the Temporal.TimeZone.prototype.getInstantFor method. It calls the timeZoneRec's getPossibleInstantsFor method at least once. If that call returns an empty array and disambiguation is not "reject", it calls timeZoneRec's getOffsetNanosecondsFor method twice, and getPossibleInstantsFor an additional time. It performs the following steps when called:

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  2. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-possible-instants-for) is true.
  3. Let possibleInstants be ? GetPossibleInstantsFor(timeZoneRec, dateTime).
  4. Return ? DisambiguatePossibleInstants(possibleInstants, timeZoneRec, dateTime, disambiguation).

11.5.23 DisambiguatePossibleInstants ( possibleInstants, timeZoneRec, dateTime, disambiguation )

The abstract operation DisambiguatePossibleInstants takes arguments possibleInstants (a List of Temporal.Instant objects), timeZoneRec (a Time Zone Methods Record), dateTime (a Temporal.PlainDateTime), and disambiguation ("compatible", "earlier", "later", or "reject") and returns either a normal completion containing a Temporal.Instant, or an abrupt completion. It chooses from a List of possible Temporal.Instant instances the one indicated by the disambiguation parameter.

The possibleInstants List may be empty, in which case it calls the time zone's getOffsetNanosecondsFor method twice, and getPossibleInstantsFor once, if disambiguation is not "reject".

  1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-possible-instants-for) is true.
  2. Assert: If possibleInstants is empty, and disambiguation is not "reject", TimeZoneMethodsRecordHasLookedUp(timeZoneRec, get-offset-nanoseconds-for) is true.
  3. Let n be possibleInstants's length.
  4. If n = 1, then
    1. Return possibleInstants[0].
  5. If n ≠ 0, then
    1. If disambiguation is "earlier" or "compatible", then
      1. Return possibleInstants[0].
    2. If disambiguation is "later", then
      1. Return possibleInstants[n - 1].
    3. Assert: disambiguation is "reject".
    4. Throw a RangeError exception.
  6. Assert: n = 0.
  7. If disambiguation is "reject", then
    1. Throw a RangeError exception.
  8. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).
  9. Let dayBeforeNs be epochNanoseconds - (nsPerDay).
  10. If IsValidEpochNanoseconds(dayBeforeNs) is false, throw a RangeError exception.
  11. Let dayBefore be ! CreateTemporalInstant(dayBeforeNs).
  12. Let dayAfterNs be epochNanoseconds + (nsPerDay).
  13. If IsValidEpochNanoseconds(dayAfterNs) is false, throw a RangeError exception.
  14. Let dayAfter be ! CreateTemporalInstant(dayAfterNs).
  15. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZoneRec, dayBefore).
  16. Let offsetAfter be ? GetOffsetNanosecondsFor(timeZoneRec, dayAfter).
  17. Let nanoseconds be offsetAfter - offsetBefore.
  18. If abs(nanoseconds) > nsPerDay, throw a RangeError exception.
  19. If disambiguation is "earlier", then
    1. Let norm be NormalizeTimeDuration(0, 0, 0, 0, 0, -nanoseconds).
    2. Let earlierTime be AddTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], norm).
    3. Let earlierDate be BalanceISODate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]] + earlierTime.[[Days]]).
    4. Let earlierDateTime be ! CreateTemporalDateTime(earlierDate.[[Year]], earlierDate.[[Month]], earlierDate.[[Day]], earlierTime.[[Hour]], earlierTime.[[Minute]], earlierTime.[[Second]], earlierTime.[[Millisecond]], earlierTime.[[Microsecond]], earlierTime.[[Nanosecond]], "iso8601").
    5. Set possibleInstants to ? GetPossibleInstantsFor(timeZoneRec, earlierDateTime).
    6. If possibleInstants is empty, throw a RangeError exception.
    7. Return possibleInstants[0].
  20. Assert: disambiguation is "compatible" or "later".
  21. Let norm be NormalizeTimeDuration(0, 0, 0, 0, 0, nanoseconds).
  22. Let laterTime be AddTime(dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], norm).
  23. Let laterDate be BalanceISODate(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]] + laterTime.[[Days]]).
  24. Let laterDateTime be ! CreateTemporalDateTime(laterDate.[[Year]], laterDate.[[Month]], laterDate.[[Day]], laterTime.[[Hour]], laterTime.[[Minute]], laterTime.[[Second]], laterTime.[[Millisecond]], laterTime.[[Microsecond]], laterTime.[[Nanosecond]], "iso8601").
  25. Set possibleInstants to ? GetPossibleInstantsFor(timeZoneRec, laterDateTime).
  26. Set n to possibleInstants's length.
  27. If n = 0, throw a RangeError exception.
  28. Return possibleInstants[n - 1].

11.5.24 GetPossibleInstantsFor ( timeZoneRec, dateTime )

The abstract operation GetPossibleInstantsFor takes arguments timeZoneRec (a Time Zone Methods Record) and dateTime (a Temporal.PlainDateTime) and returns either a normal completion containing a List of Temporal.Instant objects, or an abrupt completion. It determines the possible Temporal.Instant exact times that may correspond to dateTime, by calling the getPossibleInstantsFor method of the given time zone. It performs the following steps when called:

  1. Let possibleInstants be ? TimeZoneMethodsRecordCall(timeZoneRec, get-possible-instants-for, « dateTime »).
  2. If TimeZoneMethodsRecordIsBuiltin(timeZoneRec), return ! CreateListFromArrayLike(possibleInstants, « Object »).
  3. Let iteratorRecord be ? GetIterator(possibleInstants, sync).
  4. Let list be a new empty List.
  5. Repeat,
    1. Let value be ? IteratorStepValue(iteratorRecord).
    2. If value is done, then
      1. Let numResults be list's length.
      2. If numResults > 1, then
        1. Let epochNs be a new empty List.
        2. For each value instant in list, do
          1. Append instant.[[EpochNanoseconds]] to the end of the List epochNs.
        3. Let min be the least element of the List epochNs.
        4. Let max be the greatest element of the List epochNs.
        5. If abs((max - min)) > nsPerDay, throw a RangeError exception.
      3. Return list.
    3. If value is not an Object or value does not have an [[InitializedTemporalInstant]] internal slot, then
      1. Let completion be ThrowCompletion(a newly created TypeError object).
      2. Return ? IteratorClose(iteratorRecord, completion).
    4. Append value to the end of the List list.

11.5.25 TimeZoneEquals ( one, two )

The abstract operation TimeZoneEquals takes arguments one (a String or Object) and two (a String or Object) and returns either a normal completion containing either true or false, or a throw completion. It returns true if its arguments represent time zones using the same identifier. It performs the following steps when called:

  1. If one and two are the same Object value, return true.
  2. Let timeZoneOne be ? ToTemporalTimeZoneIdentifier(one).
  3. Let timeZoneTwo be ? ToTemporalTimeZoneIdentifier(two).
  4. If timeZoneOne is timeZoneTwo, return true.
  5. Let offsetMinutesOne be ? ParseTimeZoneIdentifier(timeZoneOne).[[OffsetMinutes]].
  6. Let offsetMinutesTwo be ? ParseTimeZoneIdentifier(timeZoneTwo).[[OffsetMinutes]].
  7. If offsetMinutesOne is empty and offsetMinutesTwo is empty, then
    1. Let recordOne be GetAvailableNamedTimeZoneIdentifier(timeZoneOne).
    2. Let recordTwo be GetAvailableNamedTimeZoneIdentifier(timeZoneTwo).
    3. If recordOne is not empty and recordTwo is not empty and recordOne.[[PrimaryIdentifier]] is recordTwo.[[PrimaryIdentifier]], return true.
  8. Else,
    1. If offsetMinutesOne is not empty and offsetMinutesTwo is not empty and offsetMinutesOne = offsetMinutesTwo, return true.
  9. Return false.

11.5.26 ParseTimeZoneIdentifier ( identifier )

The abstract operation ParseTimeZoneIdentifier takes argument identifier (a String) and returns either a normal completion containing a Record containing [[Name]] and [[OffsetMinutes]] fields, or a throw completion. If identifier is a named time zone identifier, [[Name]] will be identifier and [[OffsetMinutes]] will be empty. If identifier is an offset time zone identifier, [[Name]] will be empty and [[OffsetMinutes]] will be a signed integer. Otherwise, a RangeError will be thrown. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(identifier), TimeZoneIdentifier).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a TimeZoneIANAName Parse Node, then
    1. Let name be the source text matched by the TimeZoneIANAName Parse Node contained within parseResult.
    2. NOTE: name is syntactically valid, but does not necessarily conform to IANA Time Zone Database naming guidelines or correspond with an available named time zone identifier.
    3. Return the Record { [[Name]]: name, [[OffsetMinutes]]: empty }.
  4. Else,
    1. Assert: parseResult contains a TimeZoneUTCOffsetName Parse Node.
    2. Let offsetString be the source text matched by the TimeZoneUTCOffsetName Parse Node contained within parseResult.
    3. Let offsetNanoseconds be ! ParseDateTimeUTCOffset(offsetString).
    4. Let offsetMinutes be offsetNanoseconds / (60 × 109).
    5. Assert: offsetMinutes is an integer.
    6. Return the Record { [[Name]]: empty, [[OffsetMinutes]]: offsetMinutes }.

12 Temporal.Calendar Objects

A Temporal.Calendar object is an Object representing a calendar.

12.1 Calendar Types

At a minimum, ECMAScript implementations must support a built-in calendar named "iso8601", representing the ISO 8601 calendar. In addition, implementations may support any number of other built-in calendars corresponding with those of the Unicode Common Locale Data Repository (CLDR).

ECMAScript implementations identify built-in calendars using a calendar type as defined by Unicode Technical Standard #35, Part 4, Section 2. Their canonical form is a string containing only Unicode Basic Latin lowercase letters (U+0061 LATIN SMALL LETTER A through U+007A LATIN SMALL LETTER Z, inclusive) and/or digits (U+0030 DIGIT ZERO through U+0039 DIGIT NINE, inclusive), with zero or more medial hyphens (U+002D HYPHEN-MINUS).

The Temporal.Calendar constructor, when called with the name of a built-in calendar as the argument, will return a valid Temporal.Calendar object. When called with any other string, it will throw a RangeError exception.

12.1.1 IsBuiltinCalendar ( id )

The abstract operation IsBuiltinCalendar takes argument id (a String) and returns a Boolean. The returned value is true if id is a calendar type denoting a built-in calendar, and false otherwise. It performs the following steps when called:

  1. Let calendars be AvailableCalendars().
  2. If calendars contains the ASCII-lowercase of id, return true.
  3. Return false.

12.1.2 AvailableCalendars ( )

The implementation-defined abstract operation AvailableCalendars takes no arguments and returns a List of Strings. Each element in the returned List represents a calendar type supported by the implementation. It performs the following steps when called:

  1. Let calendars be the List of String values representing calendar types supported by the implementation.
  2. Assert: calendars contains "iso8601".
  3. Assert: calendars does not contain any element S for which the ASCII-lowercase of S is not S.
  4. Assert: calendars does not contain any element that does not identify a calendar type in the Unicode Common Locale Data Repository (CLDR).
  5. Return SortStringListByCodeUnit(calendars).

12.2 Abstract Operations for Temporal.Calendar Objects

12.2.1 Calendar Methods Records

A Calendar Methods Record is a Record value used to store a Temporal.Calendar object, or an Object implementing the calendar protocol, along with any methods that have been observably looked up on that object during the current operation. Calendar Methods Records are produced by the abstract operation CreateCalendarMethodsRecord.

Calendar Methods Records have the fields listed in Table 18.

Table 18: Calendar Methods Record Fields
Field Name Value Meaning
[[Receiver]] a String or Object The calendar object, or a string indicating a built-in time zone.
[[DateAdd]] a function object or undefined The calendar's dateAdd method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateAdd%.
[[DateFromFields]] a function object or undefined The calendar's dateFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateFromFields%.
[[DateUntil]] a function object or undefined The calendar's dateUntil method. For a built-in calendar this is always %Temporal.Calendar.prototype.dateUntil%.
[[Day]] a function object or undefined The calendar's day method. For a built-in calendar this is always %Temporal.Calendar.prototype.day%.
[[Fields]] a function object or undefined The calendar's fields method. For a built-in calendar this is always %Temporal.Calendar.prototype.fields%.
[[MergeFields]] a function object or undefined The calendar's mergeFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.mergeFields%.
[[MonthDayFromFields]] a function object or undefined The calendar's monthDayFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.monthDayFromFields%.
[[YearMonthFromFields]] a function object or undefined The calendar's yearMonthFromFields method. For a built-in calendar this is always %Temporal.Calendar.prototype.yearMonthFromFields%.

12.2.2 CreateCalendarMethodsRecord ( calendar, methods )

The abstract operation CreateCalendarMethodsRecord takes arguments calendar (a String or Object) and methods (a List of one of date-add, date-from-fields, date-until, day, fields, merge-fields, month-day-from-fields, or year-month-from-fields) and returns either a normal completion containing a Calendar Methods Record, or a throw completion. It creates a Calendar Methods Record from the given calendar, looking up the methods given in methods. It performs the following steps when called:

  1. Let record be the Calendar Methods Record { [[Receiver]]: calendar, [[DateAdd]]: undefined, [[DateFromFields]]: undefined, [[DateUntil]]: undefined, [[Day]]: undefined, [[Fields]]: undefined, [[MergeFields]]: undefined, [[MonthDayFromFields]]: undefined, [[YearMonthFromFields]]: undefined  }.
  2. For each element methodName in methods, do
    1. Perform ? CalendarMethodsRecordLookup(record, methodName).
  3. Return record.

12.2.3 CreateCalendarMethodsRecordFromRelativeTo ( plainRelativeTo, zonedRelativeTo, methods )

The abstract operation CreateCalendarMethodsRecordFromRelativeTo takes arguments plainRelativeTo (a Temporal.PlainDate or undefined), zonedRelativeTo (a Temporal.ZonedDateTime or undefined), and methods (a List of one of date-add, date-from-fields, date-until, day, fields, merge-fields, month-day-from-fields, or year-month-from-fields) and returns either a normal completion containing either a Calendar Methods Record or undefined, or a throw completion. It creates a Calendar Methods Record from the calendar of the given relativeTo object, looking up the methods given in methods. If no relativeTo object is given, it returns undefined instead of a Calendar Methods Record. It performs the following steps when called:

  1. If zonedRelativeTo is not undefined, return ? CreateCalendarMethodsRecord(zonedRelativeTo.[[Calendar]], methods).
  2. If plainRelativeTo is not undefined, return ? CreateCalendarMethodsRecord(plainRelativeTo.[[Calendar]], methods).
  3. Return undefined.

12.2.4 CalendarMethodsRecordLookup ( calendarRec, methodName )

The abstract operation CalendarMethodsRecordLookup takes arguments calendarRec (a Calendar Methods Record) and methodName (one of date-add, date-from-fields, date-until, day, fields, merge-fields, month-day-from-fields, or year-month-from-fields) and returns either a normal completion containing unused, or a throw completion. It looks up the given method on the given calendar. For a built-in calendar, this lookup is unobservable and results in the intrinsic method. If the calendar is an Object, the lookup is observable and may result in a user-code method. It performs the following steps when called:

  1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, methodName) is false.
  2. If methodName is date-add, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[DateAdd]] to %Temporal.Calendar.prototype.dateAdd%.
    2. Else,
      1. Set calendarRec.[[DateAdd]] to ? GetMethod(calendarRec.[[Receiver]], "dateAdd").
      2. If calendarRec.[[DateAdd]] is undefined, throw a TypeError exception.
  3. Else if methodName is date-from-fields, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[DateFromFields]] to %Temporal.Calendar.prototype.dateFromFields%.
    2. Else,
      1. Set calendarRec.[[DateFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "dateFromFields").
      2. If calendarRec.[[DateFromFields]] is undefined, throw a TypeError exception.
  4. Else if methodName is date-until, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[DateUntil]] to %Temporal.Calendar.prototype.dateUntil%.
    2. Else,
      1. Set calendarRec.[[DateUntil]] to ? GetMethod(calendarRec.[[Receiver]], "dateUntil").
      2. If calendarRec.[[DateUntil]] is undefined, throw a TypeError exception.
  5. Else if methodName is day, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[Day]] to %Temporal.Calendar.prototype.day%.
    2. Else,
      1. Set calendarRec.[[Day]] to ? GetMethod(calendarRec.[[Receiver]], "day").
      2. If calendarRec.[[Day]] is undefined, throw a TypeError exception.
  6. Else if methodName is fields, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[Fields]] to %Temporal.Calendar.prototype.fields%.
    2. Else,
      1. Set calendarRec.[[Fields]] to ? GetMethod(calendarRec.[[Receiver]], "fields").
      2. If calendarRec.[[Fields]] is undefined, throw a TypeError exception.
  7. Else if methodName is merge-fields, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[MergeFields]] to %Temporal.Calendar.prototype.mergeFields%.
    2. Else,
      1. Set calendarRec.[[MergeFields]] to ? GetMethod(calendarRec.[[Receiver]], "mergeFields").
      2. If calendarRec.[[MergeFields]] is undefined, throw a TypeError exception.
  8. Else if methodName is month-day-from-fields, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[MonthDayFromFields]] to %Temporal.Calendar.prototype.monthDayFromFields%.
    2. Else,
      1. Set calendarRec.[[MonthDayFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "monthDayFromFields").
      2. If calendarRec.[[MonthDayFromFields]] is undefined, throw a TypeError exception.
  9. Else if methodName is year-month-from-fields, then
    1. If calendarRec.[[Receiver]] is a String, then
      1. Set calendarRec.[[YearMonthFromFields]] to %Temporal.Calendar.prototype.yearMonthFromFields%.
    2. Else,
      1. Set calendarRec.[[YearMonthFromFields]] to ? GetMethod(calendarRec.[[Receiver]], "yearMonthFromFields").
      2. If calendarRec.[[YearMonthFromFields]] is undefined, throw a TypeError exception.
  10. Return unused.

12.2.5 CalendarMethodsRecordHasLookedUp ( calendarRec, methodName )

The abstract operation CalendarMethodsRecordHasLookedUp takes arguments calendarRec (a Calendar Methods Record) and methodName (one of date-add, date-from-fields, date-until, day, fields, merge-fields, month-day-from-fields, or year-month-from-fields) and returns true or false. It determines whether the given Calendar Methods Record has already looked up the given method. It performs the following steps when called:

  1. If methodName is date-add, then
    1. Let method be calendarRec.[[DateAdd]].
  2. Else if methodName is date-from-fields, then
    1. Let method be calendarRec.[[DateFromFields]].
  3. Else if methodName is date-until, then
    1. Let method be calendarRec.[[DateUntil]].
  4. Else if methodName is day, then
    1. Let method be calendarRec.[[Day]].
  5. Else if methodName is fields, then
    1. Let method be calendarRec.[[Fields]].
  6. Else if methodName is merge-fields, then
    1. Let method be calendarRec.[[MergeFields]].
  7. Else if methodName is month-day-from-fields, then
    1. Let method be calendarRec.[[MonthDayFromFields]].
  8. Else if methodName is year-month-from-fields, then
    1. Let method be calendarRec.[[YearMonthFromFields]].
  9. If method is undefined, return false.
  10. Return true.

12.2.6 CalendarMethodsRecordIsBuiltin ( calendarRec )

The abstract operation CalendarMethodsRecordIsBuiltin takes argument calendarRec (a Calendar Methods Record) and returns true or false. It determines whether the given Calendar Methods Record represents a built-in calendar (that is never exposed to user code.) It performs the following steps when called:

  1. If calendarRec.[[Receiver]] is a String, return true.
  2. Return false.

12.2.7 CalendarMethodsRecordCall ( calendarRec, methodName, arguments )

The abstract operation CalendarMethodsRecordCall takes arguments calendarRec (a Calendar Methods Record), methodName (one of date-add, date-from-fields, date-until, day, fields, merge-fields, month-day-from-fields, or year-month-from-fields), and arguments (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value, or a throw completion. It calls the method methodName stored in the Calendar Methods Record, with the stored receiver as the receiver, and the given arguments, and returns the result. It performs the following steps when called:

  1. Assert: CalendarMethodsRecordHasLookedUp(calendarRec, methodName) is true.
  2. Let receiver be calendarRec.[[Receiver]].
  3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, then
    1. Set receiver to ! CreateTemporalCalendar(calendarRec.[[Receiver]]).
  4. If methodName is date-add, then
    1. Return ? Call(calendarRec.[[DateAdd]], receiver, arguments).
  5. If methodName is date-from-fields, then
    1. Return ? Call(calendarRec.[[DateFromFields]], receiver, arguments).
  6. If methodName is date-until, then
    1. Return ? Call(calendarRec.[[DateUntil]], receiver, arguments).
  7. If methodName is day, then
    1. Return ? Call(calendarRec.[[Day]], receiver, arguments).
  8. If methodName is fields, then
    1. Return ? Call(calendarRec.[[Fields]], receiver, arguments).
  9. If methodName is merge-fields, then
    1. Return ? Call(calendarRec.[[MergeFields]], receiver, arguments).
  10. If methodName is month-day-from-fields, then
    1. Return ? Call(calendarRec.[[MonthDayFromFields]], receiver, arguments).
  11. If methodName is year-month-from-fields, then
    1. Return ? Call(calendarRec.[[YearMonthFromFields]], receiver, arguments).

12.2.8 CreateTemporalCalendar ( identifier [ , newTarget ] )

The abstract operation CreateTemporalCalendar takes argument identifier (a String) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.Calendar, or an abrupt completion. It creates a Temporal.Calendar instance and fills the internal slots with valid values. It performs the following steps when called:

  1. Assert: IsBuiltinCalendar(identifier) is true.
  2. If newTarget is not provided, set newTarget to %Temporal.Calendar%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Calendar.prototype%", « [[InitializedTemporalCalendar]], [[Identifier]] »).
  4. Set object.[[Identifier]] to the ASCII-lowercase of identifier.
  5. Return object.

12.2.9 CalendarFields ( calendarRec, fieldNames )

The abstract operation CalendarFields takes arguments calendarRec (a Calendar Methods Record) and fieldNames (a List of Strings) and returns either a normal completion containing a List of Strings, or a throw completion. It calls the fields method of the given calendar with an array representation of fieldNames, and returns a List representation of the result. It performs the following steps when called:

  1. Assert: fieldNames contains zero or one of each of the Strings "day", "month", "monthCode", and "year", in that order.
  2. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, then
    1. NOTE: %Temporal.Calendar.prototype.fields% is not called in this clause in order to avoid an unnecessary observable Array iteration.
    2. If calendarRec.[[Receiver]] is "iso8601", return fieldNames.
    3. Let extraFieldDescriptors be CalendarFieldDescriptors(calendarRec.[[Receiver]], fieldNames).
    4. For each Calendar Field Descriptor Record desc of extraFieldDescriptors, do
      1. Append desc.[[Property]] to fieldNames.
    5. Return fieldNames.
  3. Let fieldsArray be ? CalendarMethodsRecordCall(calendarRec, fields, « CreateArrayFromList(fieldNames) »).
  4. Let iteratorRecord be ? GetIterator(fieldsArray, sync).
  5. Return ? IteratorToListOfType(iteratorRecord, « String »).

12.2.10 CalendarMergeFields ( calendarRec, fields, additionalFields )

The abstract operation CalendarMergeFields takes arguments calendarRec (a Calendar Methods Record), fields (an Object), and additionalFields (an Object) and returns either a normal completion containing an Object, or a throw completion. It merges the properties of fields and additionalFields by calling the mergeFields method of the given calendar. It performs the following steps when called:

  1. Let result be ? CalendarMethodsRecordCall(calendarRec, merge-fields, « fields, additionalFields »).
  2. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return result.
  3. If Type(result) is not Object, throw a TypeError exception.
  4. Return result.

12.2.11 CalendarDateAdd ( calendarRec, date, duration [ , options ] )

The abstract operation CalendarDateAdd takes arguments calendarRec (a Calendar Methods Record), date (a Temporal.PlainDate), and duration (a Temporal.Duration) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainDate, or an abrupt completion. It adds duration to date by calling the dateAdd method of the given calendar. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let addedDate be ? CalendarMethodsRecordCall(calendarRec, date-add, « date, duration, options »).
  3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return addedDate.
  4. Perform ? RequireInternalSlot(addedDate, [[InitializedTemporalDate]]).
  5. Return addedDate.

12.2.12 CalendarDateUntil ( calendarRec, one, two, options )

The abstract operation CalendarDateUntil takes arguments calendarRec (a Calendar Methods Record), one (a Temporal.PlainDate), two (a Temporal.PlainDate), and options (an Object or undefined) and returns either a normal completion containing a Temporal.Duration, or an abrupt completion. It determines the difference between the dates one and two by calling the dateUntil method of the given calendar. It performs the following steps when called:

  1. Let duration be ? CalendarMethodsRecordCall(calendarRec, date-until, « one, two, options »).
  2. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return duration.
  3. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  4. Return duration.

12.2.13 CalendarYear ( calendar, dateLike )

The abstract operation CalendarYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's year() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.year%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "year", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. Return (result).

12.2.14 CalendarMonth ( calendar, dateLike )

The abstract operation CalendarMonth takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's month() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.month%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "month", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.15 CalendarMonthCode ( calendar, dateLike )

The abstract operation CalendarMonthCode takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainYearMonth, or Temporal.PlainMonthDay) and returns either a normal completion containing a String, or an abrupt completion. It calls the given calendar's monthCode() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.monthCode%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "monthCode", « dateLike »).
  3. If Type(result) is not String, throw a TypeError exception.
  4. Return result.

12.2.16 CalendarDay ( calendarRec, dateLike )

The abstract operation CalendarDay takes arguments calendarRec (a Calendar Methods Record) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainMonthDay) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's day() method and validates the result. It performs the following steps when called:

  1. Let result be ? CalendarMethodsRecordCall(calendarRec, day, « dateLike »).
  2. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return result.
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.17 CalendarDayOfWeek ( calendar, dateLike )

The abstract operation CalendarDayOfWeek takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime or Temporal.PlainDate) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's dayOfWeek() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.dayOfWeek%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "dayOfWeek", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.18 CalendarDayOfYear ( calendar, dateLike )

The abstract operation CalendarDayOfYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime or Temporal.PlainDate) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's dayOfYear() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.dayOfYear%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "dayOfYear", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.19 CalendarWeekOfYear ( calendar, dateLike )

The abstract operation CalendarWeekOfYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime or Temporal.PlainDate) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's weekOfYear() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.weekOfYear%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "weekOfYear", « dateLike »).
  3. If result is undefined, return undefined.
  4. If Type(result) is not Number, throw a TypeError exception.
  5. If IsIntegralNumber(result) is false, throw a RangeError exception.
  6. If result < 1𝔽, throw a RangeError exception.
  7. Return (result).

12.2.20 CalendarYearOfWeek ( calendar, dateLike )

The abstract operation CalendarYearOfWeek takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime or Temporal.PlainDate) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's yearOfWeek() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.yearOfWeek%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "yearOfWeek", « dateLike »).
  3. If result is undefined, return undefined.
  4. If Type(result) is not Number, throw a TypeError exception.
  5. If IsIntegralNumber(result) is false, throw a RangeError exception.
  6. Return (result).

12.2.21 CalendarDaysInWeek ( calendar, dateLike )

The abstract operation CalendarDaysInWeek takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime or Temporal.PlainDate) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's daysInWeek() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.daysInWeek%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "daysInWeek", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.22 CalendarDaysInMonth ( calendar, dateLike )

The abstract operation CalendarDaysInMonth takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's daysInMonth() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.daysInMonth%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "daysInMonth", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.23 CalendarDaysInYear ( calendar, dateLike )

The abstract operation CalendarDaysInYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's daysInYear() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.daysInYear%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "daysInYear", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.24 CalendarMonthsInYear ( calendar, dateLike )

The abstract operation CalendarMonthsInYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing an integer, or an abrupt completion. It calls the given calendar's monthsInYear() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.monthsInYear%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "monthsInYear", « dateLike »).
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. If result < 1𝔽, throw a RangeError exception.
  6. Return (result).

12.2.25 CalendarInLeapYear ( calendar, dateLike )

The abstract operation CalendarInLeapYear takes arguments calendar (a String or Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing a Boolean, or an abrupt completion. It calls the given calendar's inLeapYear() method and validates the result. It performs the following steps when called:

  1. If calendar is a String, then
    1. Set calendar to ! CreateTemporalCalendar(calendar).
    2. Return ? Call(%Temporal.Calendar.prototype.inLeapYear%, calendar, « dateLike »).
  2. Let result be ? Invoke(calendar, "inLeapYear", « dateLike »).
  3. If Type(result) is not Boolean, throw a TypeError exception.
  4. Return result.

12.2.26 ObjectImplementsTemporalCalendarProtocol ( object )

The abstract operation ObjectImplementsTemporalCalendarProtocol takes argument object (an Object) and returns either a normal completion containing a Boolean, or a throw completion. It determines whether the given object is a Temporal.Calendar instance or implements the required methods from the Temporal.Calendar protocol. For ordinary objects, and some exotic objects, this operation is infallible and will always return a normal completion. However, if object is a Proxy or has one in its prototype chain, it may call into user code. It performs the following steps when called:

  1. If object has an [[InitializedTemporalCalendar]] internal slot, return true.
  2. For each property key key of « "dateAdd", "dateFromFields", "dateUntil", "day", "dayOfWeek", "dayOfYear", "daysInMonth", "daysInWeek", "daysInYear", "fields", "id", "inLeapYear", "mergeFields", "month", "monthCode", "monthDayFromFields", "monthsInYear", "weekOfYear", "year", "yearMonthFromFields", "yearOfWeek" », do
    1. If ? HasProperty(object, key) is false, return false.
  3. Return true.
Note
This operation is a convenience which makes it easier to catch bugs in custom calendars. For web compatibility reasons, the list of required property keys will not be extended in future editions, even if the Temporal.Calendar protocol gains more methods.

12.2.27 ToTemporalCalendarSlotValue ( temporalCalendarLike [ , default ] )

The abstract operation ToTemporalCalendarSlotValue takes argument temporalCalendarLike (an ECMAScript value) and optional argument default (a String) and returns either a normal completion containing either a String or an Object, or a throw completion. It attempts to derive a value from temporalCalendarLike that is suitable for storing in a Temporal object's [[Calendar]] internal slot, and returns that value if found or throws an exception if not. An optional default built-in calendar identifier may be provided, which is returned if temporalCalendarLike is undefined. It performs the following steps when called:

  1. If temporalCalendarLike is undefined and default is present, then
    1. Assert: IsBuiltinCalendar(default) is true.
    2. Return default.
  2. If Type(temporalCalendarLike) is Object, then
    1. If temporalCalendarLike has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return temporalCalendarLike.[[Calendar]].
    2. If ? ObjectImplementsTemporalCalendarProtocol(temporalCalendarLike) is false, throw a TypeError exception.
    3. Return temporalCalendarLike.
  3. If temporalCalendarLike is not a String, throw a TypeError exception.
  4. Let identifier be ? ParseTemporalCalendarString(temporalCalendarLike).
  5. If IsBuiltinCalendar(identifier) is false, throw a RangeError exception.
  6. Return the ASCII-lowercase of identifier.

12.2.28 GetTemporalCalendarSlotValueWithISODefault ( item )

The abstract operation GetTemporalCalendarSlotValueWithISODefault takes argument item (an Object) and returns either a normal completion containing either a String or an Object, or a throw completion. It looks for a calendar property on the given item and converts its value into another value suitable for storing in a Temporal object's [[Calendar]] internal slot. If no such property is present, the built-in ISO 8601 calendar is returned. It performs the following steps when called:

  1. If item has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
    1. Return item.[[Calendar]].
  2. Let calendarLike be ? Get(item, "calendar").
  3. Return ? ToTemporalCalendarSlotValue(calendarLike, "iso8601").

12.2.29 ToTemporalCalendarIdentifier ( calendarSlotValue )

The abstract operation ToTemporalCalendarIdentifier takes argument calendarSlotValue (a String or Object) and returns either a normal completion containing a String, or a throw completion. It obtains the identifier string for a value calendarSlotValue stored in a Temporal object's [[Calendar]] internal slot. It performs the following steps when called:

  1. If calendarSlotValue is a String, then
    1. Assert: IsBuiltinCalendar(calendarSlotValue) is true.
    2. Return calendarSlotValue.
  2. Let identifier be ? Get(calendarSlotValue, "id").
  3. If identifier is not a String, throw a TypeError exception.
  4. Return identifier.

12.2.30 ToTemporalCalendarObject ( calendarSlotValue )

The abstract operation ToTemporalCalendarObject takes argument calendarSlotValue (a String or Object) and returns an Object. It obtains a calendar object for a value calendarSlotValue stored in a Temporal object's [[Calendar]] internal slot. It performs the following steps when called:

  1. If calendarSlotValue is an Object, return calendarSlotValue.
  2. Return ! CreateTemporalCalendar(calendarSlotValue).

12.2.31 CalendarDateFromFields ( calendarRec, fields [ , options ] )

The abstract operation CalendarDateFromFields takes arguments calendarRec (a Calendar Methods Record) and fields (an Object) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainDate or an abrupt completion. It calls the given calendar's dateFromFields() method and validates the result. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let date be ? CalendarMethodsRecordCall(calendarRec, date-from-fields, « fields, options »).
  3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return date.
  4. Perform ? RequireInternalSlot(date, [[InitializedTemporalDate]]).
  5. Return date.

12.2.32 CalendarYearMonthFromFields ( calendarRec, fields [ , options ] )

The abstract operation CalendarYearMonthFromFields takes arguments calendarRec (a Calendar Methods Record) and fields (an Object) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainYearMonth or an abrupt completion. It calls the given calendar's yearMonthFromFields() method and validates the result. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let yearMonth be ? CalendarMethodsRecordCall(calendarRec, year-month-from-fields, « fields, options »).
  3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return yearMonth.
  4. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  5. Return yearMonth.

12.2.33 CalendarMonthDayFromFields ( calendarRec, fields [ , options ] )

The abstract operation CalendarMonthDayFromFields takes arguments calendarRec (a Calendar Methods Record) and fields (an Object) and optional argument options (an Object or undefined) and returns either a normal completion containing a Temporal.PlainMonthDay or an abrupt completion. It calls the given calendar's monthDayFromFields() method and validates the result. It performs the following steps when called:

  1. If options is not present, set options to undefined.
  2. Let monthDay be ? CalendarMethodsRecordCall(calendarRec, month-day-from-fields, « fields, options »).
  3. If CalendarMethodsRecordIsBuiltin(calendarRec) is true, return monthDay.
  4. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  5. Return monthDay.

12.2.34 MaybeFormatCalendarAnnotation ( calendar, showCalendar )

The abstract operation MaybeFormatCalendarAnnotation takes arguments calendar (a String or Object) and showCalendar (one of "auto", "always", "never", or "critical") and returns either a normal completion containing a String, or an abrupt completion. It returns a string with a calendar annotation suitable for concatenating to the end of an ISO 8601 string. Depending on the given calendar and the value of showCalendar, the string may be empty if no calendar annotation need be included. This operation may invoke an observable Get operation on calendar if it is a custom calendar, but not if showCalendar is "never". It performs the following steps when called:

  1. If showCalendar is "never", return the empty String.
  2. Let calendarIdentifier be ? ToTemporalCalendarIdentifier(calendar).
  3. Return FormatCalendarAnnotation(calendarIdentifier, showCalendar).

12.2.35 FormatCalendarAnnotation ( id, showCalendar )

The abstract operation FormatCalendarAnnotation takes arguments id (a String) and showCalendar (one of "auto", "always", "never", or "critical") and returns a String. It returns a string with a calendar annotation suitable for concatenating to the end of an ISO 8601 string. Depending on the given id and value of showCalendar, the string may be empty if no calendar annotation need be included. It performs the following steps when called:

  1. If showCalendar is "never", return the empty String.
  2. If showCalendar is "auto" and id is "iso8601", return the empty String.
  3. If showCalendar is "critical", let flag be "!"; else, let flag be the empty String.
  4. Return the string-concatenation of "[", flag, "u-ca=", id, and "]".

12.2.36 CalendarEquals ( one, two )

The abstract operation CalendarEquals takes arguments one (a String or Object) and two (a String or Object) and returns either a normal completion containing either true or false, or a throw completion. It returns true if its arguments represent calendars using the same identifier. It performs the following steps when called:

  1. If one and two are the same Object value, return true.
  2. Let calendarOne be ? ToTemporalCalendarIdentifier(one).
  3. Let calendarTwo be ? ToTemporalCalendarIdentifier(two).
  4. If calendarOne is calendarTwo, return true.
  5. Return false.

12.2.37 ConsolidateCalendars ( one, two )

The abstract operation ConsolidateCalendars takes arguments one (a String or Object) and two (a String or Object) and returns either a normal completion containing either a String or Object, or a throw completion. It returns the calendar that should take priority when combining two Temporal objects with different calendars, or throws an exception if the calendars cannot be combined. Calendars can be combined when they have the same identifier or exactly one of them has identifier "iso8601", and calendarTwo takes priority in any combination unless it is the calendar with that identifier. It performs the following steps when called:

  1. If one and two are the same Object value, return two.
  2. Let calendarOne be ? ToTemporalCalendarIdentifier(one).
  3. Let calendarTwo be ? ToTemporalCalendarIdentifier(two).
  4. If calendarOne is calendarTwo, return two.
  5. If calendarOne is "iso8601", return two.
  6. If calendarTwo is "iso8601", return one.
  7. Throw a RangeError exception.

12.2.38 ISODaysInMonth ( year, month )

The abstract operation ISODaysInMonth takes arguments year (an integer) and month (an integer in the inclusive interval from 1 to 12) and returns a positive integer. It returns the number of days in the given year and month in the ISO 8601 calendar. It performs the following steps when called:

  1. If month is 1, 3, 5, 7, 8, 10, or 12, return 31.
  2. If month is 4, 6, 9, or 11, return 30.
  3. Assert: month is 2.
  4. Return 28 + MathematicalInLeapYear(EpochTimeForYear(year)).

12.2.39 ToISOWeekOfYear ( year, month, day )

The abstract operation ToISOWeekOfYear takes arguments year (an integer), month (an integer), and day (an integer) and returns a Year-Week Record. It determines where a calendar day falls in the ISO 8601 week calendar and calculates its calendar week of year, which is the 1-based ordinal number of its calendar week within the corresponding week calendar year (which may differ from year by up to 1 in either direction). It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. Let wednesday be 3.
  3. Let thursday be 4.
  4. Let friday be 5.
  5. Let saturday be 6.
  6. Let daysInWeek be 7.
  7. Let maxWeekNumber be 53.
  8. Let dayOfYear be ToISODayOfYear(year, month, day).
  9. Let dayOfWeek be ToISODayOfWeek(year, month, day).
  10. Let week be floor((dayOfYear + daysInWeek - dayOfWeek + wednesday ) / daysInWeek).
  11. If week < 1, then
    1. NOTE: This is the last week of the previous year.
    2. Let dayOfJan1st be ToISODayOfWeek(year, 1, 1).
    3. If dayOfJan1st is friday, then
      1. Return the Year-Week Record { [[Week]]: maxWeekNumber, [[Year]]: year - 1 }.
    4. If dayOfJan1st is saturday, and MathematicalInLeapYear(EpochTimeForYear(year - 1)) is 1, then
      1. Return the Year-Week Record { [[Week]]: maxWeekNumber. [[Year]]: year - 1 }.
    5. Return the Year-Week Record { [[Week]]: maxWeekNumber - 1, [[Year]]: year - 1 }.
  12. If week is maxWeekNumber, then
    1. Let daysInYear be MathematicalDaysInYear(year).
    2. Let daysLaterInYear be daysInYear - dayOfYear.
    3. Let daysAfterThursday be thursday - dayOfWeek.
    4. If daysLaterInYear < daysAfterThursday, then
      1. Return the Year-Week Record { [[Week]]: 1, [[Year]]: year + 1 }.
  13. Return the Year-Week Record { [[Week]]: week, [[Year]]: year }.
Note 1
In the ISO 8601 week calendar, calendar week number 1 of a calendar year is the week including the first Thursday of that year (based on the principle that a week belongs to the same calendar year as the majority of its calendar days), which always includes January 4 and starts on the Monday on or immediately before then. Because of this, some calendar days of the first calendar week of a calendar year may be part of the preceding [proleptic Gregorian] date calendar year, and some calendar days of the last calendar week of a calendar year may be part of the following [proleptic Gregorian] date calendar year. See ISO 8601 for details.
Note 2
For example, week calendar year 2020 includes both 31 December 2019 (a Tuesday belonging to its calendar week 1) and 1 January 2021 (a Friday belonging to its calendar week 53).

12.2.40 ISOMonthCode ( month )

The abstract operation ISOMonthCode takes argument month (an integer in the inclusive interval from 1 to 12) and returns a String. It returns the string month code for a month in the ISO 8601 calendar. It performs the following steps when called:

  1. Let numberPart be ToZeroPaddedDecimalString(month, 2).
  2. Return the string-concatenation of "M" and numberPart.

12.2.41 ISOResolveMonth ( fields )

The abstract operation ISOResolveMonth takes argument fields (an Object) and returns either a normal completion containing unused or a throw completion. It ensures that the "month" property of fields, if undefined, is set to the integral Number value in the inclusive interval from 1 to 12 that corresponds to the "monthCode" property of fields. It throws an exception if both properties are undefined, or if either property is invalid, or if the properties are inconsistent. It performs the following steps when called:

  1. Assert: fields is an ordinary Object that is not directly observable from ECMAScript code and for which the value of the [[Prototype]] internal slot is null and every property is a data property.
  2. Let month be ! Get(fields, "month").
  3. Assert: month is undefined or month is a Number.
  4. Let monthCode be ! Get(fields, "monthCode").
  5. If monthCode is undefined, then
    1. If month is undefined, throw a TypeError exception.
    2. Return unused.
  6. Assert: monthCode is a String.
  7. NOTE: The ISO 8601 calendar does not include leap months.
  8. If the length of monthCode is not 3, throw a RangeError exception.
  9. If the first code unit of monthCode is not 0x004D (LATIN CAPITAL LETTER M), throw a RangeError exception.
  10. Let monthCodeDigits be the substring of monthCode from 1.
  11. If ParseText(StringToCodePoints(monthCodeDigits), DateMonth) is a List of errors, throw a RangeError exception.
  12. Let monthCodeInteger be ! ToIntegerOrInfinity(monthCodeDigits).
  13. Assert: SameValue(monthCode, ISOMonthCode(monthCodeInteger)) is true.
  14. If month is not undefined and (month) ≠ monthCodeInteger, throw a RangeError exception.
  15. Perform ! CreateDataPropertyOrThrow(fields, "month", 𝔽(monthCodeInteger)).
  16. Return unused.

12.2.42 ISODateFromFields ( fields, overflow )

The ISODateFromFields abstract operation implements the calendar-specific logic in the Temporal.Calendar.prototype.dateFromFields method for the ISO 8601 calendar.

  1. Assert: Type(fields) is Object.
  2. Assert: overflow is either "constrain" or "reject".
  3. Let year be ! Get(fields, "year").
  4. Let month be ! Get(fields, "month").
  5. Let day be ! Get(fields, "day").
  6. Assert: year, month, and day are all Numbers.
  7. Return ? RegulateISODate((year), (month), (day), overflow).

12.2.43 ISOYearMonthFromFields ( fields, overflow )

The ISOYearMonthFromFields abstract operation implements the calendar-specific logic in the Temporal.Calendar.prototype.yearMonthFromFields method for the ISO 8601 calendar. It returns a Record with three fields ([[Year]], [[Month]], and [[ReferenceISODay]]). [[Month]], and [[ReferenceISODay]] are positive integers, while [[Year]] is a signed integer.

  1. Assert: Type(fields) is Object.
  2. Assert: overflow is either "constrain" or "reject".
  3. Let year be ! Get(fields, "year").
  4. Let month be ! Get(fields, "month").
  5. Assert: year and month are Numbers.
  6. Let result be ? RegulateISOYearMonth((year), (month), overflow).
  7. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[ReferenceISODay]]: 1  }.

12.2.44 ISOMonthDayFromFields ( fields, overflow )

The ISOMonthDayFromFields abstract operation implements the calendar-specific logic in the Temporal.Calendar.prototype.monthDayFromFields method for the ISO 8601 calendar.

  1. Assert: Type(fields) is Object.
  2. Assert: overflow is either "constrain" or "reject".
  3. Let month be ! Get(fields, "month").
  4. Let day be ! Get(fields, "day").
  5. Assert: month and day are Numbers.
  6. Let year be ! Get(fields, "year").
  7. Let referenceISOYear be 1972 (the first ISO 8601 leap year after the epoch).
  8. If year is undefined, then
    1. Let result be ? RegulateISODate(referenceISOYear, (month), (day), overflow).
  9. Else,
    1. Assert: year is a Number.
    2. Let result be ? RegulateISODate((year), (month), (day), overflow).
  10. Return the Record { [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[ReferenceISOYear]]: referenceISOYear  }.

12.2.45 ISOFieldKeysToIgnore ( keys )

The abstract operation ISOFieldKeysToIgnore takes argument keys (a List of property keys) and returns a List of property keys. It determines which calendar date fields changing any of the fields named in keys can potentially conflict with or invalidate, for the ISO 8601 calendar. It performs the following steps when called:

  1. Let ignoredKeys be an empty Set.
  2. For each element key of keys, do
    1. Add key to ignoredKeys.
    2. If key is "month", add "monthCode" to ignoredKeys.
    3. Else if key is "monthCode", add "month" to ignoredKeys.
  3. Return the List of ignoredKeys' elements.

12.2.46 ToISODayOfYear ( year, month, day )

The abstract operation ToISODayOfYear takes arguments year (an integer), month (an integer), and day (an integer) and returns an integer. It returns the ISO 8601 calendar day of year of a calendar day, which is its 1-based ordinal number within its ISO 8601 calendar year. It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. Let epochDays be ISODateToEpochDays(year, month - 1, day).
  3. Return EpochTimeToDayInYear(EpochDaysToEpochMs(epochDays, 0)) + 1.

12.2.47 ToISODayOfWeek ( year, month, day )

The abstract operation ToISODayOfWeek takes arguments year (an integer), month (an integer), and day (an integer) and returns an integer. It returns the ISO 8601 calendar day of week of a calendar day, which is its 1-based ordinal position within the sequence of week calendar days that starts with Monday at 1 and ends with Sunday at 7. It performs the following steps when called:

  1. Assert: IsValidISODate(year, month, day) is true.
  2. Let epochDays be ISODateToEpochDays(year, month - 1, day).
  3. Let dayOfWeek be EpochTimeToWeekDay(EpochDaysToEpochMs(epochDays, 0)).
  4. If dayOfWeek = 0, return 7.
  5. Return dayOfWeek.

12.3 The Temporal.Calendar Constructor

The Temporal.Calendar constructor:

  • creates and initializes a new Temporal.Calendar object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Temporal.Calendar behaviour must include a super call to the %Temporal.Calendar% constructor to create and initialize subclass instances with the necessary internal slots.

12.3.1 Temporal.Calendar ( id )

The Temporal.Calendar function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Throw a TypeError exception.
  2. If id is not a String, throw a TypeError exception.
  3. If IsBuiltinCalendar(id) is false, then
    1. Throw a RangeError exception.
  4. Return ? CreateTemporalCalendar(id, NewTarget).

12.4 Properties of the Temporal.Calendar Constructor

The Temporal.Calendar prototype:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

12.4.1 Temporal.Calendar.prototype

The initial value of Temporal.Calendar.prototype is %Temporal.Calendar.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

12.4.2 Temporal.Calendar.from ( calendarLike )

The Temporal.Calendar.from function performs the following steps when called:

  1. Let calendarSlotValue be ? ToTemporalCalendarSlotValue(calendarLike).
  2. Return ToTemporalCalendarObject(calendarSlotValue).

12.5 Properties of the Temporal.Calendar Prototype Object

The Temporal.Calendar prototype object

  • is itself an ordinary object.
  • is not a Temporal.Calendar instance and does not have a [[InitializedTemporalCalendar]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

12.5.1 Temporal.Calendar.prototype.constructor

The initial value of Temporal.Calendar.prototype.constructor is %Temporal.Calendar%.

12.5.2 Temporal.Calendar.prototype[ @@toStringTag ]

The initial value of the @@toStringTag property is the String value "Temporal.Calendar".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

12.5.3 get Temporal.Calendar.prototype.id

Temporal.Calendar.prototype.id is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Return calendar.[[Identifier]].

12.5.4 Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.dateFromFields method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(fields) is not Object, throw a TypeError exception.
  5. Set options to ? GetOptionsObject(options).
  6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "year", "day" »).
  7. Let overflow be ? ToTemporalOverflow(options).
  8. Perform ? ISOResolveMonth(fields).
  9. Let result be ? ISODateFromFields(fields, overflow).
  10. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], "iso8601").

12.5.5 Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.yearMonthFromFields method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(fields) is not Object, throw a TypeError exception.
  5. Set options to ? GetOptionsObject(options).
  6. Set fields to ? PrepareTemporalFields(fields, « "month", "monthCode", "year" », « "year" »).
  7. Let overflow be ? ToTemporalOverflow(options).
  8. Perform ? ISOResolveMonth(fields).
  9. Let result be ? ISOYearMonthFromFields(fields, overflow).
  10. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], "iso8601", result.[[ReferenceISODay]]).

12.5.6 Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.monthDayFromFields method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(fields) is not Object, throw a TypeError exception.
  5. Set options to ? GetOptionsObject(options).
  6. Set fields to ? PrepareTemporalFields(fields, « "day", "month", "monthCode", "year" », « "day" »).
  7. Let overflow be ? ToTemporalOverflow(options).
  8. Perform ? ISOResolveMonth(fields).
  9. Let result be ? ISOMonthDayFromFields(fields, overflow).
  10. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], "iso8601", result.[[ReferenceISOYear]]).

12.5.7 Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.dateAdd method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Set date to ? ToTemporalDate(date).
  5. Set duration to ? ToTemporalDuration(duration).
  6. Set options to ? GetOptionsObject(options).
  7. Let overflow be ? ToTemporalOverflow(options).
  8. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  9. Let balanceResult be BalanceTimeDuration(norm, "day").
  10. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]] + balanceResult.[[Days]], overflow).
  11. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], "iso8601").

12.5.8 Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.dateUntil method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Set one to ? ToTemporalDate(one).
  5. Set two to ? ToTemporalDate(two).
  6. Set options to ? GetOptionsObject(options).
  7. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", date, "auto").
  8. If largestUnit is "auto", set largestUnit to "day".
  9. Let result be DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit).
  10. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0).

12.5.9 Temporal.Calendar.prototype.year ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.year method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. Assert: temporalDateLike has an [[ISOYear]] internal slot.
  6. Return 𝔽(temporalDateLike.[[ISOYear]]).

12.5.10 Temporal.Calendar.prototype.month ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.month method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is Object and temporalDateLike has an [[InitializedTemporalMonthDay]] internal slot, then
    1. Throw a TypeError exception.
  5. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  6. Assert: temporalDateLike has an [[ISOMonth]] internal slot.
  7. Return 𝔽(temporalDateLike.[[ISOMonth]]).

12.5.11 Temporal.Calendar.prototype.monthCode ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.monthCode method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. Assert: temporalDateLike has an [[ISOMonth]] internal slot.
  6. Return ISOMonthCode(temporalDateLike.[[ISOMonth]]).

12.5.12 Temporal.Calendar.prototype.day ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.day method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalMonthDay]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. Assert: temporalDateLike has an [[ISODay]] internal slot.
  6. Return 𝔽(temporalDateLike.[[ISODay]]).

12.5.13 Temporal.Calendar.prototype.dayOfWeek ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.dayOfWeek method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  5. Return 𝔽(ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])).

12.5.14 Temporal.Calendar.prototype.dayOfYear ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.dayOfYear method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  5. Return 𝔽(ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])).

12.5.15 Temporal.Calendar.prototype.weekOfYear ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.weekOfYear method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  5. Let isoYearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]).
  6. Return 𝔽(isoYearWeek.[[Week]]).

12.5.16 Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  5. Let isoYearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]).
  6. Return 𝔽(isoYearWeek.[[Year]]).

12.5.17 Temporal.Calendar.prototype.daysInWeek ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.daysInWeek method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Perform ? ToTemporalDate(temporalDateLike).
  5. Return 7𝔽.

12.5.18 Temporal.Calendar.prototype.daysInMonth ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.daysInMonth method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slots, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. Return 𝔽(ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]])).

12.5.19 Temporal.Calendar.prototype.daysInYear ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.daysInYear method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. Return 𝔽(MathematicalDaysInYear(temporalDateLike.[[ISOYear]])).

12.5.20 Temporal.Calendar.prototype.monthsInYear ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.monthsInYear method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Perform ? ToTemporalDate(temporalDateLike).
  5. Return 12𝔽.

12.5.21 Temporal.Calendar.prototype.inLeapYear ( temporalDateLike )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.inLeapYear method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. If MathematicalInLeapYear(EpochTimeForYear(temporalDateLike.[[ISOYear]])) is 1, return true.
  6. Return false.

12.5.22 Temporal.Calendar.prototype.fields ( fields )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.fields method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Assert: calendar.[[Identifier]] is "iso8601".
  4. Let iteratorRecord be ? GetIterator(fields, sync).
  5. Let fieldNames be a new empty List.
  6. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Return CreateArrayFromList(fieldNames).
    3. If next is not a String, then
      1. Let completion be ThrowCompletion(a newly created TypeError object).
      2. Return ? IteratorClose(iteratorRecord, completion).
    4. If fieldNames contains next, then
      1. Let completion be ThrowCompletion(a newly created RangeError object).
      2. Return ? IteratorClose(iteratorRecord, completion).
    5. If next is not one of "year", "month", "monthCode", or "day", then
      1. Let completion be ThrowCompletion(a newly created RangeError object).
      2. Return ? IteratorClose(iteratorRecord, completion).
    6. Append next to the end of the List fieldNames.

12.5.23 Temporal.Calendar.prototype.mergeFields ( fields, additionalFields )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement the Temporal.Calendar.prototype.mergeFields method as specified in the ECMA-402 specification.

An ECMAScript implementation that does not include the ECMA-402 API, may still include support for built-in calendars (see 12.1). The minimum implementation of this method for ECMAScript implementations that do not include the ECMA-402 API and do not support built-in calendars other than "iso8601" performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let fieldsCopy be ? SnapshotOwnProperties(? ToObject(fields), null, « », « undefined »).
  4. Let additionalFieldsCopy be ? SnapshotOwnProperties(? ToObject(additionalFields), null, « », « undefined »).
  5. NOTE: Every property of fieldsCopy and additionalFieldsCopy is an enumerable data property with a non-undefined value, but some property keys may be Symbols.
  6. Let additionalKeys be ! additionalFieldsCopy.[[OwnPropertyKeys]]().
  7. Assert: calendar.[[Identifier]] is "iso8601".
  8. Let overriddenKeys be ISOFieldKeysToIgnore(additionalKeys).
  9. Let merged be OrdinaryObjectCreate(null).
  10. NOTE: The following steps ensure that property iteration order of merged matches that of fields as modified by omitting overridden properties and appending non-overlapping properties from additionalFields in iteration order.
  11. Let fieldsKeys be ! fieldsCopy.[[OwnPropertyKeys]]().
  12. For each element key of fieldsKeys, do
    1. If overriddenKeys contains key, then
      1. Let propValue be ! Get(additionalFieldsCopy, key).
    2. Else,
      1. Let propValue be ! Get(fieldsCopy, key).
    3. If propValue is not undefined, perform ! CreateDataPropertyOrThrow(merged, key, propValue).
  13. Perform ! CopyDataProperties(merged, additionalFieldsCopy, « »).
  14. Return merged.

12.5.24 Temporal.Calendar.prototype.toString ( )

The Temporal.Calendar.prototype.toString method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Return calendar.[[Identifier]].

12.5.25 Temporal.Calendar.prototype.toJSON ( )

The Temporal.Calendar.prototype.toJSON method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Return calendar.[[Identifier]].

12.6 Properties of Temporal.Calendar Instances

Temporal.Calendar instances are ordinary objects that inherit properties from the %Temporal.Calendar.prototype%. Temporal.Calendar instances also have a [[Identifier]] internal slot. The value of this internal slot is a string.

13 Abstract Operations

13.1 IteratorToListOfType ( iteratorRecord, elementTypes )

The abstract operation IteratorToListOfType takes arguments iteratorRecord (an Iterator Record) and elementTypes (a List of names of ECMAScript language types) and returns either a normal completion containing a list of ECMAScript language values or a throw completion. elementTypes contains the names of ECMAScript language types that are allowed for element values of the returned List. It performs the following steps when called:

  1. Let values be a new empty List.
  2. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Return values.
    3. If Type(next) is not an element of elementTypes, then
      1. Let completion be ThrowCompletion(a newly created TypeError object).
      2. Return ? IteratorClose(iteratorRecord, completion).
    4. Append next to the end of the List values.

13.2 ISODateToEpochDays ( year, month, date )

The abstract operation ISODateToEpochDays takes arguments year (an integer), month (an integer), and date (an integer) and returns an integer. It calculates a number of days. It performs the following steps when called:

  1. Let resolvedYear be year + floor(month / 12).
  2. Let resolvedMonth be month modulo 12.
  3. Find a time t such that EpochTimeToEpochYear(t) is resolvedYear, EpochTimeToMonthInYear(t) is resolvedMonth, and EpochTimeToDate(t) is 1.
  4. Return EpochTimeToDayNumber(t) + date - 1.
Editor's Note
This operation corresponds to ECMA-262 operation MakeDay(year, month, date). It calculates the result in mathematical values instead of Number values. These two operations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.

13.3 EpochDaysToEpochMs ( day, time )

The abstract operation EpochDaysToEpochMs takes arguments day (an integer) and time (an integer) and returns an integer. It calculates a number of milliseconds. It performs the following steps when called:

  1. Return day × (msPerDay) + time.
Editor's Note
This operation corresponds to ECMA-262 operation MakeDate(date, time). It calculates the result in mathematical values instead of Number values. These two operations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.

13.4 Date Equations

A given time t belongs to day number

EpochTimeToDayNumber(t) = floor(t / (msPerDay))

Number of days in year are given by:

MathematicalDaysInYear(y)
= 365 if ((y) modulo 4) ≠ 0
= 366 if ((y) modulo 4) = 0 and ((y) modulo 100) ≠ 0
= 365 if ((y) modulo 100) = 0 and ((y) modulo 400) ≠ 0
= 366 if ((y) modulo 400) = 0

The day number of the first day of year y is given by:

EpochDayNumberForYear(y) = 365 × (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) + floor((y - 1601) / 400)

The time of the start of a year is:

EpochTimeForYear(y) = (msPerDay) × EpochDayNumberForYear(y)

Epoch year from time t is given by:

EpochTimeToEpochYear(t) = the largest integral Number y (closest to +∞) such that EpochTimeForYear(y) ≤ t

The following function returns 1 for a time within leap year otherwise it returns 0:

MathematicalInLeapYear(t)

The month number for a time t is given by:

EpochTimeToMonthInYear(t)
= 0 if 0 ≤ EpochTimeToDayInYear(t) < 31
= 1 if 31 ≤ EpochTimeToDayInYear(t) < 59 + MathematicalInLeapYear(t)

where

A month value of 0 specifies January; 1 specifies February; 2 specifies March; 3 specifies April; 4 specifies May; 5 specifies June; 6 specifies July; 7 specifies August; 8 specifies September; 9 specifies October; 10 specifies November; and 11 specifies December. Note that EpochTimeToMonthInYear(0) = 0, corresponding to Thursday, 1 January 1970.

The date number for a time t is given by:

EpochTimeToDate(t)

The weekday for a particular time t is defined as:

EpochTimeToWeekDay(t) =(EpochTimeToDayNumber(t) + 4) modulo 7

A weekday value of 0 specifies Sunday; 1 specifies Monday; 2 specifies Tuesday; 3 specifies Wednesday; 4 specifies Thursday; 5 specifies Friday; and 6 specifies Saturday. Note that EpochTimeToWeekDay(0) = 4, corresponding to Thursday, 1 January 1970.

Editor's Note
These equations correspond to ECMA-262 equations defined in Days in Year, Month from Time, Date from Time, Week Day respectively. These calculate the result in mathematical values instead of Number values. These equations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.
Editor's Note
Note that the operation EpochTimeToMonthInYear(t) uses 0-based months unlike rest of Temporal since it's intended to be unified with MonthFromTime(t) when the above mentioned issue is fixed.

13.5 GetOptionsObject ( options )

The abstract operation GetOptionsObject takes argument options (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It returns an Object suitable for use with GetOption, either options itself or a default empty Object. It throws a TypeError if options is not undefined and not an Object. It performs the following steps when called:

  1. If options is undefined, then
    1. Return OrdinaryObjectCreate(null).
  2. If Type(options) is Object, then
    1. Return options.
  3. Throw a TypeError exception.

13.6 GetOption ( options, property, type, values, default )

The abstract operation GetOption takes arguments options (an Object), property (a property key), type (boolean or string), values (empty or a List of ECMAScript language values), and default (required or an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It extracts the value of the specified property of options, converts it to the required type, checks whether it is allowed by values if values is not empty, and substitutes default if the value is undefined. It performs the following steps when called:

  1. Let value be ? Get(options, property).
  2. If value is undefined, then
    1. If default is required, throw a RangeError exception.
    2. Return default.
  3. If type is boolean, then
    1. Set value to ToBoolean(value).
  4. Else,
    1. Assert: type is string.
    2. Set value to ? ToString(value).
  5. If values is not empty and values does not contain value, throw a RangeError exception.
  6. Return value.

13.7 ToTemporalOverflow ( options )

The abstract operation ToTemporalOverflow takes argument options (an Object or undefined) and returns either a normal completion containing either "constrain" or "reject", or a throw completion. It fetches and validates the "overflow" property of options, returning a default if absent. It performs the following steps when called:

  1. If options is undefined, return "constrain".
  2. Return ? GetOption(options, "overflow", string, « "constrain", "reject" », "constrain").

13.8 ToTemporalDisambiguation ( options )

The abstract operation ToTemporalDisambiguation takes argument options (an Object or undefined) and returns either a normal completion containing either "compatible", "earlier", "later", or "reject", or a throw completion. It fetches and validates the "disambiguation" property of options, returning a default if absent. It performs the following steps when called:

  1. If options is undefined, return "compatible".
  2. Return ? GetOption(options, "disambiguation", string, « "compatible", "earlier", "later", "reject" », "compatible").

13.9 ToTemporalRoundingMode ( normalizedOptions, fallback )

The abstract operation ToTemporalRoundingMode takes arguments normalizedOptions (an Object) and fallback (a String from the Identifier column of Table 19) and returns either a normal completion containing a String from the Identifier column of Table 19, or a throw completion. It extracts the value of the property named "roundingMode" from normalizedOptions and makes sure it is a valid value for the option. The value fallback is returned if the property is not present. It performs the following steps when called:

  1. Let roundingModes be the List of Strings from the Identifier column of Table 19.
  2. Return ? GetOption(normalizedOptions, "roundingMode", string, roundingModes, fallback).
Table 19: Rounding modes
Identifier Description Examples: Round to 0 fraction digits
-1.5 0.4 0.5 0.6 1.5
"ceil" Toward positive infinity ⬆️ [-1] ⬆️ [1] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"floor" Toward negative infinity ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬇️ [0] ⬇️ [1]
"expand" Away from zero ⬇️ [-2] ⬆️ [1] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"trunc" Toward zero ⬆️ [-1] ⬇️ [0] ⬇️ [0] ⬇️ [0] ⬇️ [1]
"halfCeil" Ties toward positive infinity ⬆️ [-1] ⬇️ [0] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"halfFloor" Ties toward negative infinity ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬇️ [1]
"halfExpand" Ties away from zero ⬇️ [-2] ⬇️ [0] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"halfTrunc" Ties toward zero ⬆️ [-1] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬇️ [1]
"halfEven" Ties toward an even rounding increment multiple ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬆️ [2]
Note
The examples are illustrative of the unique behaviour of each option. ⬆️ means "resolves toward positive infinity"; ⬇️ means "resolves toward negative infinity".

13.10 NegateTemporalRoundingMode ( roundingMode )

The abstract operation NegateTemporalRoundingMode takes argument roundingMode (a String from the Identifier column of Table 19) and returns a String from the Identifier column of Table 19. It returns the correct rounding mode to use when rounding the negative of a value that was originally given with roundingMode It performs the following steps when called:

  1. If roundingMode is "ceil", return "floor".
  2. If roundingMode is "floor", return "ceil".
  3. If roundingMode is "halfCeil", return "halfFloor".
  4. If roundingMode is "halfFloor", return "halfCeil".
  5. Return roundingMode.

13.11 ToTemporalOffset ( options, fallback )

The abstract operation ToTemporalOffset takes arguments options (an Object or undefined) and fallback ("prefer", "use", "ignore", or "reject") and returns either a normal completion containing either "prefer", "use", "ignore", or "reject", or a throw completion. It fetches and validates the "offset" property of options, returning fallback as a default if absent. It performs the following steps when called:

  1. If options is undefined, return fallback.
  2. Return ? GetOption(options, "offset", string, « "prefer", "use", "ignore", "reject" », fallback).

13.12 ToCalendarNameOption ( normalizedOptions )

The abstract operation ToCalendarNameOption takes argument normalizedOptions (an Object) and returns either a normal completion containing either "auto", "always", "never", or "critical", or a throw completion. It extracts the value of the property named "calendarName" from normalizedOptions and makes sure it is a valid value for the option.

Note
This property is used in toString methods in Temporal to control whether a calendar annotation should be output.

It performs the following steps when called:

  1. Return ? GetOption(normalizedOptions, "calendarName", string, « "auto", "always", "never", "critical" », "auto").

13.13 ToTimeZoneNameOption ( normalizedOptions )

The abstract operation ToTimeZoneNameOption takes argument normalizedOptions (an Object) and returns either a normal completion containing either "auto", "never", or "critical", or a throw completion. It extracts the value of the property named "timeZoneName" from normalizedOptions and makes sure it is a valid value for the option.

Note
This property is used in Temporal.ZonedDateTime.prototype.toString(). It is different from the timeZone property passed to Temporal.ZonedDateTime.from() and from the timeZone property in the options passed to Temporal.Instant.prototype.toString().

It performs the following steps when called:

  1. Return ? GetOption(normalizedOptions, "timeZoneName", string, « "auto", "never", "critical" », "auto").

13.14 ToShowOffsetOption ( normalizedOptions )

The abstract operation ToShowOffsetOption takes argument normalizedOptions (an Object) and returns either a normal completion containing either "auto" or "never", or a throw completion. It extracts the value of the property named "offset" from normalizedOptions and makes sure it is a valid value for the option.

Note
This property is used in Temporal.ZonedDateTime.prototype.toString(). It is different from the offset property passed to Temporal.ZonedDateTime.from().

It performs the following steps when called:

  1. Return ? GetOption(normalizedOptions, "offset", string, « "auto", "never" », "auto").

13.15 ToTemporalRoundingIncrement ( normalizedOptions )

The abstract operation ToTemporalRoundingIncrement takes argument normalizedOptions (an Object) and returns either a normal completion containing a positive integer, or a throw completion. It extracts the value of the property named "roundingIncrement" from normalizedOptions, makes sure it represents a number in the inclusive interval from 1 to 109, and returns that value truncated to an integer. It performs the following steps when called:

  1. Let value be ? Get(normalizedOptions, "roundingIncrement").
  2. If value is undefined, return 1𝔽.
  3. Let increment be ? ToNumber(value).
  4. If increment is not finite, throw a RangeError exception.
  5. Let integerIncrement be truncate((increment)).
  6. If integerIncrement < 1 or integerIncrement > 109, throw a RangeError exception.
  7. Return integerIncrement.

13.16 ValidateTemporalRoundingIncrement ( increment, dividend, inclusive )

The abstract operation ValidateTemporalRoundingIncrement takes arguments increment (a positive integer), dividend (a positive integer), and inclusive (a Boolean) and returns either a normal completion containing unused, or a throw completion. It verifies that increment evenly divides dividend, otherwise throwing a RangeError. dividend must be divided into more than one part unless inclusive is true. It performs the following steps when called:

  1. If inclusive is true, then
    1. Let maximum be dividend.
  2. Else,
    1. Assert: dividend > 1.
    2. Let maximum be dividend - 1.
  3. If increment > maximum, throw a RangeError exception.
  4. If dividend modulo increment ≠ 0, then
    1. Throw a RangeError exception.
  5. Return unused.

13.17 ToFractionalSecondDigits ( normalizedOptions )

The abstract operation ToFractionalSecondDigits takes argument normalizedOptions (an Object) and returns either a normal completion containing either "auto" or an integer in the inclusive interval from 0 to 9, or a throw completion. It extracts the value of the property named "fractionalSecondDigits" from normalizedOptions and makes sure it is a valid value for the option. It performs the following steps when called:

  1. Let digitsValue be ? Get(normalizedOptions, "fractionalSecondDigits").
  2. If digitsValue is undefined, return "auto".
  3. If digitsValue is not a Number, then
    1. If ? ToString(digitsValue) is not "auto", throw a RangeError exception.
    2. Return "auto".
  4. If digitsValue is NaN, +∞𝔽, or -∞𝔽, throw a RangeError exception.
  5. Let digitCount be floor((digitsValue)).
  6. If digitCount < 0 or digitCount > 9, throw a RangeError exception.
  7. Return digitCount.

13.18 ToSecondsStringPrecisionRecord ( smallestUnit, fractionalDigitCount )

The abstract operation ToSecondsStringPrecisionRecord takes arguments smallestUnit ("minute", "second", "millisecond", "microsecond", "nanosecond", or undefined) and fractionalDigitCount ("auto" or an integer in the inclusive interval from 0 to 9) and returns a Record with fields [[Precision]] ("minute", "auto", or an integer in the inclusive interval from 0 to 9), [[Unit]] ("minute", "second", "millisecond", "microsecond", or "nanosecond"), and [[Increment]] (1, 10, or 100). The returned Record represents details for serializing minutes and seconds to a string subject to the specified smallestUnit or (when smallestUnit is undefined) fractionalDigitCount digits after the decimal point in the seconds. Its [[Precision]] field is either that count of digits, the string "auto" signifying that there should be no insignificant trailing zeroes, or the string "minute" signifying that seconds should not be included at all. Its [[Unit]] field is the most precise unit that can contribute to the string, and its [[Increment]] field indicates the rounding increment that should be applied to that unit. It performs the following steps when called:

  1. If smallestUnit is "minute", then
    1. Return the Record { [[Precision]]: "minute", [[Unit]]: "minute", [[Increment]]: 1  }.
  2. If smallestUnit is "second", then
    1. Return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1  }.
  3. If smallestUnit is "millisecond", then
    1. Return the Record { [[Precision]]: 3, [[Unit]]: "millisecond", [[Increment]]: 1  }.
  4. If smallestUnit is "microsecond", then
    1. Return the Record { [[Precision]]: 6, [[Unit]]: "microsecond", [[Increment]]: 1  }.
  5. If smallestUnit is "nanosecond", then
    1. Return the Record { [[Precision]]: 9, [[Unit]]: "nanosecond", [[Increment]]: 1  }.
  6. Assert: smallestUnit is undefined.
  7. If fractionalDigitCount is "auto", then
    1. Return the Record { [[Precision]]: "auto", [[Unit]]: "nanosecond", [[Increment]]: 1  }.
  8. If fractionalDigitCount is 0, then
    1. Return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1  }.
  9. If fractionalDigitCount is 1, 2, or 3, then
    1. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "millisecond", [[Increment]]: 103 - fractionalDigitCount  }.
  10. If fractionalDigitCount is 4, 5, or 6, then
    1. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "microsecond", [[Increment]]: 106 - fractionalDigitCount  }.
  11. Assert: fractionalDigitCount is 7, 8, or 9.
  12. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "nanosecond", [[Increment]]: 109 - fractionalDigitCount  }.

13.19 GetTemporalUnit ( normalizedOptions, key, unitGroup, default [ , extraValues ] )

The abstract operation GetTemporalUnit takes arguments normalizedOptions (an Object), key (a property key), unitGroup (date, time, or datetime), and default (required or an ECMAScript language value) and optional argument extraValues (a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value, or a throw completion. It attempts to read from the specified property of normalizedOptions a Temporal unit that is covered by the union of unitGroup and extraValues, substituting default if the property value is undefined.

Both singular and plural unit names are accepted, but only the singular form is used internally.

  1. Let singularNames be a new empty List.
  2. For each row of Table 20, except the header row, in table order, do
    1. Let unit be the value in the Singular column of the row.
    2. If the Category column of the row is date and unitGroup is date or datetime, append unit to singularNames.
    3. Else if the Category column of the row is time and unitGroup is time or datetime, append unit to singularNames.
  3. If extraValues is present, then
    1. Set singularNames to the list-concatenation of singularNames and extraValues.
  4. If default is required, then
    1. Let defaultValue be undefined.
  5. Else,
    1. Let defaultValue be default.
    2. If defaultValue is not undefined and singularNames does not contain defaultValue, then
      1. Append defaultValue to singularNames.
  6. Let allowedValues be a copy of singularNames.
  7. For each element singularName of singularNames, do
    1. If singularName is listed in the Singular column of Table 20, then
      1. Let pluralName be the value in the Plural column of the corresponding row.
      2. Append pluralName to allowedValues.
  8. NOTE: For each singular Temporal unit name that is contained within allowedValues, the corresponding plural name is also contained within it.
  9. Let value be ? GetOption(normalizedOptions, key, string, allowedValues, defaultValue).
  10. If value is undefined and default is required, throw a RangeError exception.
  11. If value is listed in the Plural column of Table 20, then
    1. Set value to the value in the Singular column of the corresponding row.
  12. Return value.
Table 20: Temporal units by descending magnitude
Singular Plural Category
"year" "years" date
"month" "months" date
"week" "weeks" date
"day" "days" date
"hour" "hours" time
"minute" "minutes" time
"second" "seconds" time
"millisecond" "milliseconds" time
"microsecond" "microseconds" time
"nanosecond" "nanoseconds" time

13.20 ToRelativeTemporalObject ( options )

The abstract operation ToRelativeTemporalObject takes argument options (an Object) and returns either a normal completion containing a Record with fields [[PlainRelativeTo]], [[ZonedRelativeTo]], and [[TimeZoneRec]], or a throw completion. It examines the value of the relativeTo property of its options argument. If the value is undefined, both the [[PlainRelativeTo]] and [[ZonedRelativeTo]] fields of the returned Record are undefined. If the value is not a String or an Object, it throws a TypeError. Otherwise, it attempts to return a Temporal.ZonedDateTime instance in the [[ZonedRelativeTo]] field, or a Temporal.PlainDate instance in the [[PlainRelativeTo]] field, in order of preference, by converting the value. If neither of those are possible, it throws a RangeError.

If the returned Record's [[ZonedRelativeTo]] field is undefined, then the [[TimeZoneRec]] field is also undefined, and vice versa.

  1. Let value be ? Get(options, "relativeTo").
  2. If value is undefined, return the Record { [[PlainRelativeTo]]: undefined, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }.
  3. Let offsetBehaviour be option.
  4. Let matchBehaviour be match-exactly.
  5. If Type(value) is Object, then
    1. If value has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(value.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
      2. Return the Record { [[PlainRelativeTo]]: undefined, [[ZonedRelativeTo]]: value, [[TimeZoneRec]]: timeZoneRec }.
    2. If value has an [[InitializedTemporalDate]] internal slot, then
      1. Return the Record { [[PlainRelativeTo]]: value, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }.
    3. If value has an [[InitializedTemporalDateTime]] internal slot, then
      1. Let plainDate be ! CreateTemporalDate(value.[[ISOYear]], value.[[ISOMonth]], value.[[ISODay]], value.[[Calendar]]).
      2. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }.
    4. Let calendar be ? GetTemporalCalendarSlotValueWithISODefault(value).
    5. Let calendarRec be ? CreateCalendarMethodsRecord(calendar, « date-from-fields, fields »).
    6. Let fieldNames be ? CalendarFields(calendarRec, « "day", "month", "monthCode", "year" »).
    7. Append "hour", "microsecond", "millisecond", "minute", "nanosecond", "offset", "second", and "timeZone" to fieldNames.
    8. Let fields be ? PrepareTemporalFields(value, fieldNames, «»).
    9. Let dateOptions be OrdinaryObjectCreate(null).
    10. Perform ! CreateDataPropertyOrThrow(dateOptions, "overflow", "constrain").
    11. Let result be ? InterpretTemporalDateTimeFields(calendarRec, fields, dateOptions).
    12. Let offsetString be ! Get(fields, "offset").
    13. Let timeZone be ! Get(fields, "timeZone").
    14. If timeZone is not undefined, then
      1. Set timeZone to ? ToTemporalTimeZoneSlotValue(timeZone).
    15. If offsetString is undefined, then
      1. Set offsetBehaviour to wall.
  6. Else,
    1. If value is not a String, throw a TypeError exception.
    2. Let result be ? ParseTemporalRelativeToString(value).
    3. Let offsetString be result.[[TimeZone]].[[OffsetString]].
    4. Let annotation be result.[[TimeZone]].[[TimeZoneAnnotation]].
    5. If annotation is undefined, then
      1. Let timeZone be undefined.
    6. Else,
      1. Let timeZone be ? ToTemporalTimeZoneSlotValue(annotation).
      2. If result.[[TimeZone]].[[Z]] is true, then
        1. Set offsetBehaviour to exact.
      3. Else if offsetString is undefined, then
        1. Set offsetBehaviour to wall.
      4. Set matchBehaviour to match-minutes.
    7. Let calendar be result.[[Calendar]].
    8. If calendar is undefined, set calendar to "iso8601".
    9. If IsBuiltinCalendar(calendar) is false, throw a RangeError exception.
    10. Set calendar to the ASCII-lowercase of calendar.
  7. If timeZone is undefined, then
    1. Let plainDate be ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar).
    2. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: undefined, [[TimeZoneRec]]: undefined }.
  8. If offsetBehaviour is option, then
    1. Let offsetNs be ? ParseDateTimeUTCOffset(offsetString).
  9. Else,
    1. Let offsetNs be 0.
  10. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(timeZone, « get-offset-nanoseconds-for, get-possible-instants-for »).
  11. Let epochNanoseconds be ? InterpretISODateTimeOffset(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], offsetBehaviour, offsetNs, timeZoneRec, "compatible", "reject", matchBehaviour).
  12. Let zonedRelativeTo be ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
  13. Return the Record { [[PlainRelativeTo]]: undefined, [[ZonedRelativeTo]]: zonedRelativeTo, [[TimeZoneRec]]: timeZoneRec }.

13.21 LargerOfTwoTemporalUnits ( u1, u2 )

The abstract operation LargerOfTwoTemporalUnits takes arguments u1 (a String from the Singular column of Table 20) and u2 (a String from the Singular column of Table 20) and returns a String from the Singular column of Table 20. Given two strings representing Temporal units, it returns the string representing the larger of the two units. It performs the following steps when called:

  1. For each row of Table 20, except the header row, in table order, do
    1. Let unit be the value in the Singular column of the row.
    2. If SameValue(u1, unit) is true, return unit.
    3. If SameValue(u2, unit) is true, return unit.

13.22 IsCalendarUnit ( unit )

The abstract operation IsCalendarUnit takes argument unit (a String from the Singular column of Table 20) and returns a Boolean. It returns whether unit is a Temporal unit for which rounding would require calendar calculations. It performs the following steps when called:

  1. If unit is "year", return true.
  2. If unit is "month", return true.
  3. If unit is "week", return true.
  4. Return false.

13.23 MaximumTemporalDurationRoundingIncrement ( unit )

The abstract operation MaximumTemporalDurationRoundingIncrement takes argument unit (a String from the Singular column of Table 20) and returns 24, 60, 1000, or undefined. Given a string representing a Temporal.Duration unit, it returns the maximum rounding increment for that unit, or undefined if there is no maximum. It performs the following steps when called:

  1. If unit is "year", "month", "week", or "day", then
    1. Return undefined.
  2. If unit is "hour", then
    1. Return 24.
  3. If unit is "minute" or "second", then
    1. Return 60.
  4. Assert: unit is "millisecond", "microsecond", or "nanosecond".
  5. Return 1000.

13.24 IsPartialTemporalObject ( object )

The abstract operation IsPartialTemporalObject takes argument object (an ECMAScript language value) and returns either a normal completion containing a Boolean, or a throw completion. It determines whether value is a suitable input for one of the Temporal objects' with() methods: it must be an Object, it must not be an instance of one of the time-related or date-related Temporal types, and it must not have a calendar or timeZone property. It performs the following steps when called:

  1. If value is not an Object, return false.
  2. If value has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, return false.
  3. Let calendarProperty be ? Get(value, "calendar").
  4. If calendarProperty is not undefined, return false.
  5. Let timeZoneProperty be ? Get(value, "timeZone").
  6. If timeZoneProperty is not undefined, return false.
  7. Return true.

13.25 FormatFractionalSeconds ( subSecondNanoseconds, precision )

The abstract operation FormatFractionalSeconds takes arguments subSecondNanoseconds (an integer) and precision (either an integer in the inclusive range 0 to 9 or "auto") and returns a String. If precision is zero, or if precision is "auto" and subSecondNanoseconds is zero, then an empty String will be returned. Otherwise, the output will be a decimal point followed by a sequence of fractional seconds digits, truncated to precision digits or (if precision is "auto") to the last non-zero digit. It performs the following steps when called:

  1. If precision is "auto", then
    1. If subSecondNanoseconds is 0, return the empty String.
    2. Let fractionString be ToZeroPaddedDecimalString(subSecondNanoseconds, 9).
    3. Set fractionString to the longest prefix of fractionString ending with a code unit other than 0x0030 (DIGIT ZERO).
  2. Else,
    1. If precision is 0, return the empty String.
    2. Let fractionString be ToZeroPaddedDecimalString(subSecondNanoseconds, 9).
    3. Set fractionString to the substring of fractionString from 0 to precision.
  3. Return the string-concatenation of the code unit 0x002E (FULL STOP) and fractionString.

13.26 FormatTimeString ( hour, minute, second, subSecondNanoseconds, precision [ , style ] )

The abstract operation FormatTimeString takes arguments hour (a non-negative integer), minute (a non-negative integer), second (a non-negative integer), subSecondNanoseconds (a non-negative integer), and precision (an integer in the inclusive range 0 to 9, "minute", or "auto") and optional argument style (separated or unseparated) and returns a String. It formats a collection of unsigned time components into a string, truncating units as necessary, and separating hours, minutes, and seconds with colons unless style is unseparated. The output will be formatted like HH:MM or HHMM if precision is "minute". Otherwise, the output will be formatted like HH:MM:SS or HHMMSS if precision is zero, or if subSecondNanoseconds is zero and _precision is "auto". Otherwise, the output will be formatted like HH:MM:SS.fff or HHMMSS.fff where "fff" is a sequence of fractional seconds digits, truncated to precision digits or (if precision is "auto") to the last non-zero digit. It performs the following steps when called:

  1. If style is present and style is unseparated, let separator be the empty String; otherwise, let separator be ":".
  2. Let hh be ToZeroPaddedDecimalString(hour, 2).
  3. Let mm be ToZeroPaddedDecimalString(minute, 2).
  4. If precision is "minute", return the string-concatenation of hh, separator, and mm.
  5. Let ss be ToZeroPaddedDecimalString(second, 2).
  6. Let subSecondsPart be FormatFractionalSeconds(subSecondNanoseconds, precision).
  7. Return the string-concatenation of hh, separator, mm, separator, ss, and subSecondsPart.

13.27 GetUnsignedRoundingMode ( roundingMode, sign )

The abstract operation GetUnsignedRoundingMode takes arguments roundingMode (a String from the Identifier column of Table 19) and sign (negative or positive) and returns a specification type from the Unsigned Rounding Mode column of Table 21. It returns the rounding mode that should be applied to the absolute value of a number to produce the same result as if roundingMode, one of the String values in the Identifier column of Table 19, were applied to the signed value of the number (negative if sign is negative, or positive otherwise). It performs the following steps when called:

  1. Return the specification type in the Unsigned Rounding Mode column of Table 21 for the row where the value in the Identifier column is roundingMode and the value in the Sign column is sign.
Table 21: Conversion from rounding mode to unsigned rounding mode
Identifier Sign Unsigned Rounding Mode
"ceil" positive infinity
negative zero
"floor" positive zero
negative infinity
"expand" positive infinity
negative infinity
"trunc" positive zero
negative zero
"halfCeil" positive half-infinity
negative half-zero
"halfFloor" positive half-zero
negative half-infinity
"halfExpand" positive half-infinity
negative half-infinity
"halfTrunc" positive half-zero
negative half-zero
"halfEven" positive half-even
negative half-even

13.28 ApplyUnsignedRoundingMode ( x, r1, r2, unsignedRoundingMode )

The abstract operation ApplyUnsignedRoundingMode takes arguments x (a mathematical value), r1 (a mathematical value), r2 (a mathematical value), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 21, or undefined) and returns a mathematical value. It considers x, bracketed below by r1 and above by r2, and returns either r1 or r2 according to unsignedRoundingMode. It performs the following steps when called:

  1. If x is equal to r1, return r1.
  2. Assert: r1 < x < r2.
  3. Assert: unsignedRoundingMode is not undefined.
  4. If unsignedRoundingMode is zero, return r1.
  5. If unsignedRoundingMode is infinity, return r2.
  6. Let d1 be xr1.
  7. Let d2 be r2x.
  8. If d1 < d2, return r1.
  9. If d2 < d1, return r2.
  10. Assert: d1 is equal to d2.
  11. If unsignedRoundingMode is half-zero, return r1.
  12. If unsignedRoundingMode is half-infinity, return r2.
  13. Assert: unsignedRoundingMode is half-even.
  14. Let cardinality be (r1 / (r2r1)) modulo 2.
  15. If cardinality is 0, return r1.
  16. Return r2.

13.29 RoundNumberToIncrement ( x, increment, roundingMode )

The abstract operation RoundNumberToIncrement takes arguments x (a mathematical value), increment (an integer), and roundingMode (a String from the Identifier column of Table 19) and returns an integer. It rounds x to the nearest multiple of increment, up or down according to roundingMode. It performs the following steps when called:

  1. Let quotient be x / increment.
  2. If quotient < 0, then
    1. Let isNegative be true.
    2. Set quotient to -quotient.
  3. Else,
    1. Let isNegative be false.
  4. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, isNegative).
  5. Let r1 be the largest integer such that r1quotient.
  6. Let r2 be the smallest integer such that r2 > quotient.
  7. Let rounded be ApplyUnsignedRoundingMode(quotient, r1, r2, unsignedRoundingMode).
  8. If isNegative is true, set rounded to -rounded.
  9. Return rounded × increment.

13.30 RoundNumberToIncrementAsIfPositive ( x, increment, roundingMode )

The abstract operation RoundNumberToIncrementAsIfPositive takes arguments x (a mathematical value), increment (an integer), and roundingMode (a String from the Identifier column of Table 19) and returns an integer. It rounds x to the nearest multiple of increment, up or down according to roundingMode, but always as if x were positive. For example, "floor" and "trunc" behave identically. This is used when rounding exact times, where "rounding down" conceptually always means towards the beginning of time, even if the time is expressed as a negative amount of time relative to an epoch. It performs the following steps when called:

  1. Let quotient be x / increment.
  2. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, positive).
  3. Let r1 be the largest integer such that r1quotient.
  4. Let r2 be the smallest integer such that r2 > quotient.
  5. Let rounded be ApplyUnsignedRoundingMode(quotient, r1, r2, unsignedRoundingMode).
  6. Return rounded × increment.

13.31 ISO 8601 grammar

Several operations in this section are intended to parse ISO 8601 strings representing a date, a time, a duration, or a combined date and time. For the purposes of these operations, a valid ISO 8601 string is defined as a string that can be generated by one of the goal elements of the following grammar.

This grammar is adapted from the ABNF grammar of ISO 8601 that is given in appendix A of RFC 3339, augmented with the grammar of annotations in section 3.1 of Date and Time on the Internet: Timestamps with additional information

The grammar deviates from the standard given in ISO 8601 in the following ways:

  • Only the calendar date format is supported, not the weekdate or ordinal date format.
  • Two-digit years are disallowed.
  • Expanded Years of 6 digits are allowed.
  • Fractional parts may have 1 through 9 decimal places.
  • In time representations, only seconds are allowed to have a fractional part.
  • In duration representations, only hours, minutes, and seconds are allowed to have a fractional part.
  • Any number of conforming suffixes in square brackets are allowed. However, the only recognized suffixes are time zone and BCP 47 calendar. Others are ignored, unless they are prefixed with !, in which case they are rejected. Note that the suffix keys, although they look similar, are not the same as keys in RFC 6067. In particular, keys are lowercase-only.
  • A space may be used to separate the date and time in a combined date / time representation, but not in a duration (e.g., "1970-01-01 00:00Z" is valid but "P1D 1H" is not).
  • Alphabetic designators may be in lower or upper case (e.g., "1970-01-01t00:00Z" and "1970-01-01T00:00z" and "pT1m" are valid).
  • Period or comma may be used as the decimal separator (e.g., "PT1,00H" is a valid representation of a 1-hour duration).
  • UTC offsets of "-00:00" and "-0000" and "-00" are allowed, and all mean the same thing as "+00:00".
  • UTC offsets may have seconds and up to 9 sub-second fractional digits (e.g., "1970-01-01T00:00:00+00:00:00.123456789" is valid).
  • The constituent date, time, and UTC offset parts of a combined representation may each independently use basic format (with no separator symbols) or extended format (with mandatory - or : separators), as long as each such part is itself in either basic format or extended format (e.g., "1970-01-01T012345" and "19700101T01:23:45" are valid but "1970-0101T012345" and "1970-01-01T0123:45" are not).
  • When parsing a date representation for a Temporal.PlainMonthDay, the year may be omitted. The year may optionally be replaced by -- as in RFC 3339 Appendix A.
  • When parsing a date representation without a day for a Temporal.PlainYearMonth, the expression is allowed to be in basic format (with no separator symbols).
  • A duration specifier of "W" (weeks) can be combined with any of the other specifiers (e.g., "P1M1W1D" is valid).
  • Anything else described by the standard as requiring mutual agreement between communicating parties, is disallowed.
Alpha ::: one of A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z LowercaseAlpha ::: one of a b c d e f g h i j k l m n o p q r s t u v w x y z DaysDesignator ::: one of D d HoursDesignator ::: one of H h MinutesDesignator ::: one of M m MonthsDesignator ::: one of M m DurationDesignator ::: one of P p SecondsDesignator ::: one of S s DateTimeSeparator ::: <SP> T t TimeDesignator ::: one of T t WeeksDesignator ::: one of W w YearsDesignator ::: one of Y y UTCDesignator ::: one of Z z AnnotationCriticalFlag ::: ! DateYear ::: DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalSign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DateMonth ::: 0 NonZeroDigit 10 11 12 DateMonthWithThirtyOneDays ::: one of 01 03 05 07 08 10 12 DateDay ::: 0 NonZeroDigit 1 DecimalDigit 2 DecimalDigit 30 31 DateSpecYearMonth ::: DateYear -opt DateMonth DateSpecMonthDay ::: -- DateMonth -opt DateDay DateMonth -opt DateDay ValidMonthDay ::: DateMonth -opt 0 NonZeroDigit DateMonth -opt 1 DecimalDigit DateMonth -opt 2 DecimalDigit DateMonth -opt 30 but not one of 0230 or 02-30 DateMonthWithThirtyOneDays -opt 31 Date ::: DateYear - DateMonth - DateDay DateYear DateMonth DateDay TimeHour ::: Hour TimeMinute ::: MinuteSecond TimeSecond ::: MinuteSecond 60 TimeFraction ::: TemporalDecimalFraction UTCOffsetWithSubMinuteComponents[Extended] ::: TemporalSign Hour TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt NormalizedUTCOffset ::: ASCIISign Hour : MinuteSecond UTCOffsetMinutePrecision ::: TemporalSign Hour TemporalSign Hour TimeSeparator[+Extended] MinuteSecond TemporalSign Hour TimeSeparator[~Extended] MinuteSecond UTCOffsetSubMinutePrecision ::: UTCOffsetMinutePrecision UTCOffsetWithSubMinuteComponents[+Extended] UTCOffsetWithSubMinuteComponents[~Extended] DateTimeUTCOffset ::: UTCDesignator UTCOffsetSubMinutePrecision TimeZoneUTCOffsetName ::: UTCOffsetMinutePrecision TZLeadingChar ::: Alpha . _ TZChar ::: TZLeadingChar DecimalDigit - + TimeZoneIANANameComponent ::: TZLeadingChar TimeZoneIANANameComponent TZChar TimeZoneIANAName ::: TimeZoneIANANameComponent TimeZoneIANAName / TimeZoneIANANameComponent TimeZoneIdentifier ::: TimeZoneUTCOffsetName TimeZoneIANAName TimeZoneAnnotation ::: [ AnnotationCriticalFlagopt TimeZoneIdentifier ] AKeyLeadingChar ::: LowercaseAlpha _ AKeyChar ::: AKeyLeadingChar DecimalDigit - AnnotationKey ::: AKeyLeadingChar AnnotationKey AKeyChar AnnotationValueComponent ::: Alpha AnnotationValueComponentopt DecimalDigit AnnotationValueComponentopt AnnotationValue ::: AnnotationValueComponent AnnotationValueComponent - AnnotationValue Annotation ::: [ AnnotationCriticalFlagopt AnnotationKey = AnnotationValue ] Annotations ::: Annotation Annotationsopt TimeSpec ::: TimeHour TimeHour : TimeMinute TimeHour TimeMinute TimeHour : TimeMinute : TimeSecond TimeFractionopt TimeHour TimeMinute TimeSecond TimeFractionopt TimeSpecWithOptionalOffsetNotAmbiguous ::: TimeSpec DateTimeUTCOffsetopt but not one of ValidMonthDay or DateSpecYearMonth DateTime ::: Date Date DateTimeSeparator TimeSpec DateTimeUTCOffsetopt AnnotatedTime ::: TimeDesignator TimeSpec DateTimeUTCOffsetopt TimeZoneAnnotationopt Annotationsopt TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotationopt Annotationsopt AnnotatedDateTime[Zoned] ::: [~Zoned] DateTime TimeZoneAnnotationopt Annotationsopt [+Zoned] DateTime TimeZoneAnnotation Annotationsopt AnnotatedDateTimeTimeRequired ::: Date DateTimeSeparator TimeSpec DateTimeUTCOffsetopt TimeZoneAnnotationopt Annotationsopt AnnotatedYearMonth ::: DateSpecYearMonth TimeZoneAnnotationopt Annotationsopt AnnotatedMonthDay ::: DateSpecMonthDay TimeZoneAnnotationopt Annotationsopt DurationWholeSeconds ::: DecimalDigits[~Sep] DurationSecondsFraction ::: TimeFraction DurationSecondsPart ::: DurationWholeSeconds DurationSecondsFractionopt SecondsDesignator DurationWholeMinutes ::: DecimalDigits[~Sep] DurationMinutesFraction ::: TimeFraction DurationMinutesPart ::: DurationWholeMinutes DurationMinutesFraction MinutesDesignator DurationWholeMinutes MinutesDesignator DurationSecondsPartopt DurationWholeHours ::: DecimalDigits[~Sep] DurationHoursFraction ::: TimeFraction DurationHoursPart ::: DurationWholeHours DurationHoursFraction HoursDesignator DurationWholeHours HoursDesignator DurationMinutesPart DurationWholeHours HoursDesignator DurationSecondsPartopt DurationTime ::: TimeDesignator DurationHoursPart TimeDesignator DurationMinutesPart TimeDesignator DurationSecondsPart DurationDays ::: DecimalDigits[~Sep] DurationDaysPart ::: DurationDays DaysDesignator DurationWeeks ::: DecimalDigits[~Sep] DurationWeeksPart ::: DurationWeeks WeeksDesignator DurationDaysPartopt DurationMonths ::: DecimalDigits[~Sep] DurationMonthsPart ::: DurationMonths MonthsDesignator DurationWeeksPart DurationMonths MonthsDesignator DurationDaysPartopt DurationYears ::: DecimalDigits[~Sep] DurationYearsPart ::: DurationYears YearsDesignator DurationMonthsPart DurationYears YearsDesignator DurationWeeksPart DurationYears YearsDesignator DurationDaysPartopt DurationDate ::: DurationYearsPart DurationTimeopt DurationMonthsPart DurationTimeopt DurationWeeksPart DurationTimeopt DurationDaysPart DurationTimeopt Duration ::: TemporalSignopt DurationDesignator DurationDate TemporalSignopt DurationDesignator DurationTime TemporalInstantString ::: Date DateTimeSeparator TimeSpec DateTimeUTCOffset TimeZoneAnnotationopt Annotationsopt TemporalDateTimeString[Zoned] ::: AnnotatedDateTime[?Zoned] TemporalDurationString ::: Duration TemporalMonthDayString ::: AnnotatedMonthDay AnnotatedDateTime[~Zoned] TemporalTimeString ::: AnnotatedTime AnnotatedDateTimeTimeRequired TemporalYearMonthString ::: AnnotatedYearMonth AnnotatedDateTime[~Zoned]

13.31.1 Static Semantics: Early Errors

DateYear ::: TemporalSign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit
  • It is a Syntax Error if DateYear is "-000000" or "−000000" (U+2212 MINUS SIGN followed by 000000).

13.32 ParseISODateTime ( isoString )

The abstract operation ParseISODateTime takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns a Record representing each date and time component as a distinct field.

Note
The value of ! ToIntegerOrInfinity(undefined) is 0.

It performs the following steps when called:

  1. Let parseResult be empty.
  2. For each nonterminal goal of « TemporalDateTimeString, TemporalInstantString, TemporalTimeString », do
    1. If parseResult is not a Parse Node, set parseResult to ParseText(StringToCodePoints(isoString), goal).
  3. For each nonterminal goal of « TemporalMonthDayString, TemporalYearMonthString », do
    1. If parseResult is not a Parse Node, then
      1. Set parseResult to ParseText(StringToCodePoints(isoString), goal).
      2. If parseResult is a Parse Node, then
        1. Let foundCalendar be undefined.
        2. For each Annotation Parse Node annotation contained within parseResult, do
          1. Let key be the source text matched by the AnnotationKey Parse Node contained within annotation.
          2. Let value be the source text matched by the AnnotationValue Parse Node contained within annotation.
          3. If CodePointsToString(key) is "u-ca", and foundCalendar is undefined, then
            1. Set foundCalendar to CodePointsToString(value).
        3. If foundCalendar is not undefined and the ASCII-lowercase of foundCalendar is not "iso8601", throw a RangeError exception.
  4. If parseResult is not a Parse Node, throw a RangeError exception.
  5. Let each of year, month, day, hour, minute, second, and fSeconds be the source text matched by the respective DateYear, DateMonth, DateDay, TimeHour, TimeMinute, TimeSecond, and TimeFraction Parse Node contained within parseResult, or an empty sequence of code points if not present.
  6. If the first code point of year is U+2212 (MINUS SIGN), replace the first code point with U+002D (HYPHEN-MINUS).
  7. Let yearMV be ! ToIntegerOrInfinity(CodePointsToString(year)).
  8. If month is empty, then
    1. Let monthMV be 1.
  9. Else,
    1. Let monthMV be ! ToIntegerOrInfinity(CodePointsToString(month)).
  10. If day is empty, then
    1. Let dayMV be 1.
  11. Else,
    1. Let dayMV be ! ToIntegerOrInfinity(CodePointsToString(day)).
  12. Let hourMV be ! ToIntegerOrInfinity(CodePointsToString(hour)).
  13. Let minuteMV be ! ToIntegerOrInfinity(CodePointsToString(minute)).
  14. Let secondMV be ! ToIntegerOrInfinity(CodePointsToString(second)).
  15. If secondMV is 60, then
    1. Set secondMV to 59.
  16. If fSeconds is not empty, then
    1. Let fSecondsDigits be the substring of CodePointsToString(fSeconds) from 1.
    2. Let fSecondsDigitsExtended be the string-concatenation of fSecondsDigits and "000000000".
    3. Let millisecond be the substring of fSecondsDigitsExtended from 0 to 3.
    4. Let microsecond be the substring of fSecondsDigitsExtended from 3 to 6.
    5. Let nanosecond be the substring of fSecondsDigitsExtended from 6 to 9.
    6. Let millisecondMV be ! ToIntegerOrInfinity(millisecond).
    7. Let microsecondMV be ! ToIntegerOrInfinity(microsecond).
    8. Let nanosecondMV be ! ToIntegerOrInfinity(nanosecond).
  17. Else,
    1. Let millisecondMV be 0.
    2. Let microsecondMV be 0.
    3. Let nanosecondMV be 0.
  18. If IsValidISODate(yearMV, monthMV, dayMV) is false, throw a RangeError exception.
  19. If IsValidTime(hourMV, minuteMV, secondMV, millisecondMV, microsecondMV, nanosecondMV) is false, throw a RangeError exception.
  20. Let timeZoneResult be the Record { [[Z]]: false, [[OffsetString]]: undefined, [[TimeZoneAnnotation]]: undefined }.
  21. If parseResult contains a TimeZoneIdentifier Parse Node, then
    1. Let identifier be the source text matched by the TimeZoneIdentifier Parse Node contained within parseResult.
    2. Set timeZoneResult.[[TimeZoneAnnotation]] to CodePointsToString(identifier).
  22. If parseResult contains a UTCDesignator Parse Node, then
    1. Set timeZoneResult.[[Z]] to true.
  23. Else if parseResult contains a UTCOffsetSubMinutePrecision Parse Node, then
    1. Let offset be the source text matched by the UTCOffsetSubMinutePrecision Parse Node contained within parseResult.
    2. Set timeZoneResult.[[OffsetString]] to CodePointsToString(offset).
  24. Let calendar be undefined.
  25. Let calendarWasCritical be false.
  26. For each Annotation Parse Node annotation contained within parseResult, do
    1. Let key be the source text matched by the AnnotationKey Parse Node contained within annotation.
    2. If CodePointsToString(key) is "u-ca", then
      1. If calendar is undefined, then
        1. Let value be the source text matched by the AnnotationValue Parse Node contained within annotation.
        2. Set calendar to CodePointsToString(value).
        3. If annotation contains an AnnotationCriticalFlag Parse Node, set calendarWasCritical to true.
      2. Else,
        1. If annotation contains an AnnotationCriticalFlag Parse Node, or calendarWasCritical is true, throw a RangeError exception.
    3. Else,
      1. If annotation contains an AnnotationCriticalFlag Parse Node, throw a RangeError exception.
  27. Return the Record { [[Year]]: yearMV, [[Month]]: monthMV, [[Day]]: dayMV, [[Hour]]: hourMV, [[Minute]]: minuteMV, [[Second]]: secondMV, [[Millisecond]]: millisecondMV, [[Microsecond]]: microsecondMV, [[Nanosecond]]: nanosecondMV, [[TimeZone]]: timeZoneResult, [[Calendar]]: calendar  }.

13.33 ParseTemporalInstantString ( isoString )

The abstract operation ParseTemporalInstantString takes argument isoString (a String) and returns either a normal completion containing a Record, or a throw completion. It parses the argument as an ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.Instant instance as a distinct field. It performs the following steps when called:

  1. If ParseText(StringToCodePoints(isoString), TemporalInstantString) is a List of errors, throw a RangeError exception.
  2. Let result be ? ParseISODateTime(isoString).
  3. Assert: Either result.[[TimeZone]].[[OffsetString]] is a String or result.[[TimeZone]].[[Z]] is true, but not both.
  4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]], [[OffsetString]]: result.[[TimeZone]].[[OffsetString]], [[Z]]: result.[[TimeZone]].[[Z]]  }.

13.34 ParseTemporalZonedDateTimeString ( isoString )

The abstract operation ParseTemporalZonedDateTimeString takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.ZonedDateTime instance as a distinct field. It performs the following steps when called:

  1. If ParseText(StringToCodePoints(isoString), TemporalDateTimeString[+Zoned]) is a List of errors, throw a RangeError exception.
  2. Return ? ParseISODateTime(isoString).

13.35 ParseTemporalCalendarString ( isoString )

The abstract operation ParseTemporalCalendarString takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns the calendar identifier, or undefined if there is none. It performs the following steps when called:

  1. Let parseResult be Completion(ParseISODateTime(isoString)).
  2. If parseResult is a normal completion, then
    1. Let calendar be parseResult.[[Value]].[[Calendar]].
    2. If calendar is undefined, return "iso8601".
    3. Else, return calendar.
  3. Else,
    1. Set parseResult to ParseText(StringToCodePoints(isoString), AnnotationValue).
    2. If parseResult is a List of errors, throw a RangeError exception.
    3. Else, return isoString.

13.36 ParseTemporalDateString ( isoString )

The abstract operation ParseTemporalDateString takes argument isoString (a String). It parses the argument as a full or partial ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.PlainDate instance as a distinct field. It performs the following steps when called:

  1. Let parts be ? ParseTemporalDateTimeString(isoString).
  2. Return the Record { [[Year]]: parts.[[Year]], [[Month]]: parts.[[Month]], [[Day]]: parts.[[Day]], [[Calendar]]: parts.[[Calendar]]  }.

13.37 ParseTemporalDateTimeString ( isoString )

The abstract operation ParseTemporalDateTimeString takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.PlainDateTime instance as a distinct field. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalDateTimeString).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception.
  4. Return ? ParseISODateTime(isoString).

13.38 ParseTemporalDurationString ( isoString )

The abstract operation ParseTemporalDurationString takes argument isoString (a String) and returns either a normal completion containing a Duration Record, or a throw completion. It parses the argument as an ISO 8601 duration string.

Note 1
The value of ToIntegerWithTruncation("") is 0.
Note 2
Use of mathematical values rather than approximations is important to avoid off-by-one errors with input like "PT46H66M71.50040904S".

It performs the following steps when called:

  1. Let duration be ParseText(StringToCodePoints(isoString), TemporalDurationString).
  2. If duration is a List of errors, throw a RangeError exception.
  3. Let each of sign, years, months, weeks, days, hours, fHours, minutes, fMinutes, seconds, and fSeconds be the source text matched by the respective TemporalSign, DurationYears, DurationMonths, DurationWeeks, DurationDays, DurationWholeHours, DurationHoursFraction, DurationWholeMinutes, DurationMinutesFraction, DurationWholeSeconds, and DurationSecondsFraction Parse Node contained within duration, or an empty sequence of code points if not present.
  4. Let yearsMV be ? ToIntegerWithTruncation(CodePointsToString(years)).
  5. Let monthsMV be ? ToIntegerWithTruncation(CodePointsToString(months)).
  6. Let weeksMV be ? ToIntegerWithTruncation(CodePointsToString(weeks)).
  7. Let daysMV be ? ToIntegerWithTruncation(CodePointsToString(days)).
  8. Let hoursMV be ? ToIntegerWithTruncation(CodePointsToString(hours)).
  9. If fHours is not empty, then
    1. Assert: minutes, fMinutes, seconds, and fSeconds are empty.
    2. Let fHoursDigits be the substring of CodePointsToString(fHours) from 1.
    3. Let fHoursScale be the length of fHoursDigits.
    4. Let minutesMV be ? ToIntegerWithTruncation(fHoursDigits) / 10fHoursScale × 60.
  10. Else,
    1. Let minutesMV be ? ToIntegerWithTruncation(CodePointsToString(minutes)).
  11. If fMinutes is not empty, then
    1. Assert: seconds and fSeconds are empty.
    2. Let fMinutesDigits be the substring of CodePointsToString(fMinutes) from 1.
    3. Let fMinutesScale be the length of fMinutesDigits.
    4. Let secondsMV be ? ToIntegerWithTruncation(fMinutesDigits) / 10fMinutesScale × 60.
  12. Else if seconds is not empty, then
    1. Let secondsMV be ? ToIntegerWithTruncation(CodePointsToString(seconds)).
  13. Else,
    1. Let secondsMV be remainder(minutesMV, 1) × 60.
  14. If fSeconds is not empty, then
    1. Let fSecondsDigits be the substring of CodePointsToString(fSeconds) from 1.
    2. Let fSecondsScale be the length of fSecondsDigits.
    3. Let millisecondsMV be ? ToIntegerWithTruncation(fSecondsDigits) / 10fSecondsScale × 1000.
  15. Else,
    1. Let millisecondsMV be remainder(secondsMV, 1) × 1000.
  16. Let microsecondsMV be remainder(millisecondsMV, 1) × 1000.
  17. Let nanosecondsMV be remainder(microsecondsMV, 1) × 1000.
  18. If sign contains the code point U+002D (HYPHEN-MINUS) or U+2212 (MINUS SIGN), then
    1. Let factor be -1.
  19. Else,
    1. Let factor be 1.
  20. Set yearsMV to yearsMV × factor.
  21. Set monthsMV to monthsMV × factor.
  22. Set weeksMV to weeksMV × factor.
  23. Set daysMV to daysMV × factor.
  24. Set hoursMV to hoursMV × factor.
  25. Set minutesMV to floor(minutesMV) × factor.
  26. Set secondsMV to floor(secondsMV) × factor.
  27. Set millisecondsMV to floor(millisecondsMV) × factor.
  28. Set microsecondsMV to floor(microsecondsMV) × factor.
  29. Set nanosecondsMV to floor(nanosecondsMV) × factor.
  30. If IsValidDuration(yearsMV, monthsMV, weeksMV, daysMV, hoursMV, minutesMV, secondsMV, millisecondsMV, microsecondsMV, nanosecondsMV) is false, throw a RangeError exception.
  31. Return CreateDurationRecord(yearsMV, monthsMV, weeksMV, daysMV, hoursMV, minutesMV, secondsMV, millisecondsMV, microsecondsMV, nanosecondsMV).

13.39 ParseTemporalMonthDayString ( isoString )

The abstract operation ParseTemporalMonthDayString takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.PlainMonthDay instance as a distinct field. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalMonthDayString).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception.
  4. Let result be ? ParseISODateTime(isoString).
  5. Let year be result.[[Year]].
  6. If parseResult does not contain a DateYear Parse Node, then
    1. Set year to undefined.
  7. Return the Record { [[Year]]: year, [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]]  }.

13.40 ParseTemporalRelativeToString ( isoString )

The abstract operation ParseTemporalRelativeToString takes argument isoString (a String). It parses the argument as an ISO 8601 string and returns the information needed to construct either a Temporal.ZonedDateTime or a Temporal.PlainDate instance, e.g. as the value of a relativeTo option. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalDateTimeString).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a UTCDesignator ParseNode but no TimeZoneAnnotation Parse Node, throw a RangeError exception.
  4. Return ? ParseISODateTime(isoString).

13.41 ParseTemporalTimeString ( isoString )

The abstract operation ParseTemporalTimeString takes argument isoString (a String). It parses the argument as an ISO 8601 time of day and returns the information needed to construct a Temporal.PlainTime instance. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalTimeString).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception.
  4. Let result be ? ParseISODateTime(isoString).
  5. Return the Record { [[Hour]]: result.[[Hour]], [[Minute]]: result.[[Minute]], [[Second]]: result.[[Second]], [[Millisecond]]: result.[[Millisecond]], [[Microsecond]]: result.[[Microsecond]], [[Nanosecond]]: result.[[Nanosecond]],  }.
Note

A successful parse using TemporalTimeString guarantees absence of ambiguity with respect to any ISO 8601 date-only, year-month, or month-day representation.

13.42 ParseTemporalTimeZoneString ( timeZoneString )

The abstract operation ParseTemporalTimeZoneString takes argument timeZoneString (a String) and returns either a normal completion containing a Record containing information about the time zone, or a throw completion. It parses the argument as either a time zone identifier or an ISO 8601 string. The returned Record's fields are set as follows:

  • If timeZoneString is a named time zone identifier, then [[Name]] is timeZoneString and [[OffsetMinutes]] is empty.
  • Otherwise, if timeZoneString is an offset time zone identifier, then [[OffsetMinutes]] is a signed integer and [[Name]] is empty.
  • Otherwise, if timeZoneString is an ISO 8601 string with a time zone annotation containing a named time zone identifier, then [[Name]] is the time zone identifier contained in the annotation and [[OffsetMinutes]] is empty.
  • Otherwise, if timeZoneString is an ISO 8601 string with a time zone annotation containing an offset time zone identifier, then [[OffsetMinutes]] is a signed integer and [[Name]] is empty.
  • Otherwise, if timeZoneString is an ISO 8601 string using a Z offset designator, then [[Name]] is "UTC" and [[OffsetMinutes]] is empty.
  • Otherwise, if timeZoneString is an ISO 8601 string using a numeric UTC offset, then [[OffsetMinutes]] is a signed integer and [[Name]] is empty.
  • Otherwise, a RangeError is thrown.
It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(timeZoneString), TimeZoneIdentifier).
  2. If parseResult is a Parse Node, then
    1. Return ! ParseTimeZoneIdentifier(timeZoneString).
  3. Let result be ? ParseISODateTime(timeZoneString).
  4. Let timeZoneResult be result.[[TimeZone]].
  5. If timeZoneResult.[[TimeZoneAnnotation]] is not undefined, then
    1. Return ! ParseTimeZoneIdentifier(timeZoneResult.[[TimeZoneAnnotation]]).
  6. If timeZoneResult.[[Z]] is true, then
    1. Return ! ParseTimeZoneIdentifier("UTC").
  7. If timeZoneResult.[[OffsetString]] is not undefined, then
    1. Return ? ParseTimeZoneIdentifier(timeZoneResult.[[OffsetString]]).
  8. Throw a RangeError exception.

13.43 ParseTemporalYearMonthString ( isoString )

The abstract operation ParseTemporalYearMonthString takes argument isoString (a String). It parses the argument as a full or partial ISO 8601 string and returns a Record representing each date and time component needed to construct a Temporal.PlainYearMonth instance as a distinct field. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(isoString), TemporalYearMonthString).
  2. If parseResult is a List of errors, throw a RangeError exception.
  3. If parseResult contains a UTCDesignator Parse Node, throw a RangeError exception.
  4. Let result be ? ParseISODateTime(isoString).
  5. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]]  }.

13.44 ToPositiveIntegerWithTruncation ( argument )

The abstract operation ToPositiveIntegerWithTruncation takes argument argument (an ECMAScript language value) and returns either a normal completion containing a positive integer, or an abrupt completion. It converts argument to an integer representing its Number value with fractional part truncated, or throws a RangeError when that value is not finite or not positive. It performs the following steps when called:

  1. Let integer be ? ToIntegerWithTruncation(argument).
  2. If integer ≤ 0, throw a RangeError exception.
  3. Return integer.

13.45 ToIntegerWithTruncation ( argument )

The abstract operation ToIntegerWithTruncation takes argument argument (an ECMAScript language value) and returns either a normal completion containing an integer, or an abrupt completion. It converts argument to an integer representing its Number value with fractional part truncated, or throws a RangeError when that value is not finite. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
  3. Return truncate((number)).

13.46 ToIntegerIfIntegral ( argument )

The abstract operation ToIntegerIfIntegral takes argument argument (an ECMAScript language value) and returns either a normal completion containing an integer, or an abrupt completion. It converts argument to an integer representing its Number value, or throws a RangeError when that value is not integral. It performs the following steps when called:

  1. Let number be ? ToNumber(argument).
  2. If IsIntegralNumber(number) is false, throw a RangeError exception.
  3. Return (number).

13.47 PrepareTemporalFields ( fields, fieldNames, requiredFields [ , extraFieldDescriptors [ , duplicateBehaviour ] ] )

The abstract operation PrepareTemporalFields takes arguments fields (an Object), fieldNames (a List of property names), and requiredFields (partial or a List of property names) and optional arguments extraFieldDescriptors (a List of Calendar Field Descriptor Records) and duplicateBehaviour (throw or ignore) and returns either a normal completion containing an Object, or an abrupt completion. The returned Object has a null prototype, and an own data property for each element of fieldNames that corresponds with a non-undefined property of the same name on fields used as the input for relevant conversion. When requiredFields is partial, this operation throws if none of the properties are present with a non-undefined value. When requiredFields is a List, this operation throws if any of the properties named by it are absent or undefined, and otherwise substitutes a relevant default for any absent or undefined non-required property (ensuring that the returned object has a property for each element of fieldNames). When extraFieldDescriptors is present, its contents are treated as an extension of Table 22. It performs the following steps when called:

  1. If duplicateBehaviour is not present, set duplicateBehaviour to throw.
  2. Let result be OrdinaryObjectCreate(null).
  3. Let any be false.
  4. If extraFieldDescriptors is present, then
    1. For each Calendar Field Descriptor Record desc of extraFieldDescriptors, do
      1. Assert: fieldNames does not contain desc.[[Property]].
      2. Append desc.[[Property]] to fieldNames.
      3. If desc.[[Required]] is true and requiredFields is a List, then
        1. Append desc.[[Property]] to requiredFields.
  5. Let sortedFieldNames be SortStringListByCodeUnit(fieldNames).
  6. Let previousProperty be undefined.
  7. For each property name property of sortedFieldNames, do
    1. If property is one of "constructor" or "__proto__", then
      1. Throw a RangeError exception.
    2. If property is not equal to previousProperty, then
      1. Let value be ? Get(fields, property).
      2. If value is not undefined, then
        1. Set any to true.
        2. If property is in the Property column of Table 22 and there is a Conversion value in the same row, then
          1. Let Conversion be the Conversion value of the same row.
          2. If Conversion is to-integer-with-truncation, then
            1. Set value to ? ToIntegerWithTruncation(value).
            2. Set value to 𝔽(value).
          3. Else if Conversion is to-positive-integer-with-truncation, then
            1. Set value to ? ToPositiveIntegerWithTruncation(value).
            2. Set value to 𝔽(value).
          4. Else,
            1. Assert: Conversion is to-primitive-and-require-string.
            2. NOTE: Non-primitive values are supported here for consistency with other fields, but such values must coerce to Strings.
            3. Set value to ? ToPrimitive(value, string).
            4. If value is not a String, throw a TypeError exception.
        3. Else if extraFieldDescriptors is present and extraFieldDescriptors contains a Calendar Field Descriptor Record desc such that desc.[[Property]] is property, then
          1. Let converter be desc.[[Conversion]].
          2. Set value to ? converter(value).
        4. Perform ! CreateDataPropertyOrThrow(result, property, value).
      3. Else if requiredFields is a List, then
        1. If requiredFields contains property, then
          1. Throw a TypeError exception.
        2. If property is in the Property column of Table 22, then
          1. Set value to the corresponding Default value of the same row.
        3. Perform ! CreateDataPropertyOrThrow(result, property, value).
    3. Else if duplicateBehaviour is throw, then
      1. Throw a RangeError exception.
    4. Set previousProperty to property.
  8. If requiredFields is partial and any is false, then
    1. Throw a TypeError exception.
  9. Return result.
Table 22: Temporal field requirements
Property Conversion Default
"year" to-integer-with-truncation undefined
"month" to-positive-integer-with-truncation undefined
"monthCode" to-primitive-and-require-string undefined
"day" to-positive-integer-with-truncation undefined
"hour" to-integer-with-truncation +0𝔽
"minute" to-integer-with-truncation +0𝔽
"second" to-integer-with-truncation +0𝔽
"millisecond" to-integer-with-truncation +0𝔽
"microsecond" to-integer-with-truncation +0𝔽
"nanosecond" to-integer-with-truncation +0𝔽
"offset" to-primitive-and-require-string undefined
"timeZone" undefined

13.47.1 Calendar Field Descriptor Record

A Calendar Field Descriptor Record is a Record value used to describe a calendar-specific field for use in creating and interacting with instances of Temporal types.

Calendar Field Descriptor Records have the fields listed in Table 23.

Table 23: Calendar Field Descriptor Record Fields
Field Name Value Meaning
[[Property]] a String The property name associated with the field, analogous to the Property column of Table 22.
[[Conversion]] an Abstract Closure accepting a single ECMAScript language value and returning either a normal completion containing an ECMAScript language value representing purely static data or a throw completion. The means by which purported values are coerced to a static representation of the correct type (or rejected if that fails), analogous to steps indicated by the Conversion column of Table 22.
[[Required]] a Boolean Whether PrepareTemporalFields should consider the field as required when not accepting partial data.

13.48 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit )

The abstract operation GetDifferenceSettings takes arguments operation (since or until), options (an Object), unitGroup (date, time, or datetime), disallowedUnits (a List of Strings), fallbackSmallestUnit (a String), and smallestLargestDefaultUnit (a String) and returns either a normal completion containing a Record or an abrupt completion. It reads unit and rounding options needed by difference operations. It performs the following steps when called:

  1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToTemporalRoundingIncrement reads "roundingIncrement" and ToTemporalRoundingMode reads "roundingMode").
  2. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", unitGroup, "auto").
  3. If disallowedUnits contains largestUnit, throw a RangeError exception.
  4. Let roundingIncrement be ? ToTemporalRoundingIncrement(options).
  5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
  6. If operation is since, then
    1. Set roundingMode to NegateTemporalRoundingMode(roundingMode).
  7. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", unitGroup, fallbackSmallestUnit).
  8. If disallowedUnits contains smallestUnit, throw a RangeError exception.
  9. Let defaultLargestUnit be LargerOfTwoTemporalUnits(smallestLargestDefaultUnit, smallestUnit).
  10. If largestUnit is "auto", set largestUnit to defaultLargestUnit.
  11. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
  12. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  13. If maximum is not undefined, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  14. Return the Record { [[SmallestUnit]]: smallestUnit, [[LargestUnit]]: largestUnit, [[RoundingMode]]: roundingMode, [[RoundingIncrement]]: roundingIncrement,  }.

14 Amendments to the ECMAScript® 2023 Language Specification

Editor's Note

This section lists amendments which must be made to ECMA-262, the ECMAScript® 2023 Language Specification, other than the addition of the new sections specifying the Temporal object and everything related to it. Text to be added is marked like this, and text to be deleted is marked like this. Blocks of unmodified text between modified sections are marked by [...].

14.1 The String Type

Editor's Note

This section intends to move the definitions of ASCII-uppercase, ASCII-lowercase, and ASCII-case-insensitive match from ECMA-402 into ECMA-262, after the definition of the ASCII word characters.

[...]

The ASCII-uppercase of a String S is the String derived from S by replacing each occurrence of an ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) with the corresponding ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) while preserving all other code units.

The ASCII-lowercase of a String S is the String derived from S by replacing each occurrence of an ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) with the corresponding ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) while preserving all other code units.

A String A is an ASCII-case-insensitive match for a String B if the ASCII-lowercase of A is the ASCII-lowercase of B.

14.2 The Year-Week Record Specification Type

The Year-Week Record specification type is returned by the week number calculation in ToISOWeekOfYear, and the corresponding calculations for other calendars if applicable. It comprises a calendar week of year with the corresponding week calendar year.

Year-Week Records have the fields listed in table Table 24.

Table 24: Year-Week Record Fields
Field Name Value Meaning
[[Week]] a positive integer or undefined The calendar week of year.
[[Year]] an integer or undefined The week calendar year.

14.3 SortStringListByCodeUnit ( strings )

The abstract operation SortStringListByCodeUnit takes argument strings (a List of Strings) and returns a List of Strings. The returned List contains the same Strings as strings, but sorted lexicographically by UTF-16 code unit in ascending order. It performs the following steps when called:

  1. Let result be a copy of strings.
  2. Sort result into the same order as if an Array of the same values had been sorted using %Array.prototype.sort% with undefined as comparefn.
  3. Return result.

14.4 Mathematical Operations

[...]

The notation “x modulo y” (y must be finite and non-zero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x - k = q × y for some integer q.

The mathematical function remainder(x, y) produces the mathematical value whose sign is the sign of x and whose magnitude is abs(x) modulo y.

[...]

Mathematical functions min, max, abs, remainder, floor, and truncate are not defined for Numbers and BigInts, and any usage of those methods that have non-mathematical value arguments would be an editorial error in this specification.

[...]

14.5 CopyDataProperties ( target, source, excludedItems, excludedKeys [ , excludedValues ] )

The abstract operation CopyDataProperties takes arguments target (an Object), source (an ECMAScript language value), excludedItems (a List of property keys), and excludedKeys (a List of property keys) and optional argument excludedValues (a List of ECMAScript language values) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. If source is undefined or null, return unused.
  2. Let from be ! ToObject(source).
  3. Let keys be ? from.[[OwnPropertyKeys]]().
  4. For each element nextKey of keys, do
    1. Let excluded be false.
    2. For each element e of excludedItemsexcludedKeys, do
      1. If SameValue(e, nextKey) is true, then
        1. Set excluded to true.
    3. If excluded is false, then
      1. Let desc be ? from.[[GetOwnProperty]](nextKey).
      2. If desc is not undefined and desc.[[Enumerable]] is true, then
        1. Let propValue be ? Get(from, nextKey).
        2. If excludedValues is present, then
          1. For each element e of excludedValues, do
            1. If SameValue(e, propValue) is true, then
              1. Set excluded to true.
        3. PerformIf excluded is false, performCreateDataPropertyOrThrow(target, nextKey, propValue).
  5. Return unused.
Note

The target passed in here is always a newly created object which is not directly accessible in case of an error being thrown.

14.6 SnapshotOwnProperties ( source, proto [ , excludedKeys [ , excludedValues ] ] )

The abstract operation SnapshotOwnProperties takes arguments source (an Object) and proto (an Object or null) and optional arguments excludedKeys (a List of property keys) and excludedValues (a List of ECMAScript language values) and returns either a normal completion containing an Object, or a throw completion. It enumerates the own properties of source and copies them into data properties on a new object with the specified prototype, subject to the specified exclusions. It performs the following steps when called:

  1. Let copy be OrdinaryObjectCreate(proto).
  2. If excludedKeys is not present, set excludedKeys to « ».
  3. If excludedValues is not present, set excludedValues to « ».
  4. Perform ? CopyDataProperties(copy, source, excludedKeys, excludedValues).
  5. Return copy.

14.7 Overview of Date Objects and Definitions of Abstract Operations

[...]

14.7.1 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond [ , offsetNanoseconds ] )

The abstract operation GetUTCEpochNanoseconds takes arguments year (an integer), month (an integer in the inclusive interval from 1 to 12), day (an integer in the inclusive interval from 1 to 31), hour (an integer in the inclusive interval from 0 to 23), minute (an integer in the inclusive interval from 0 to 59), second (an integer in the inclusive interval from 0 to 59), millisecond (an integer in the inclusive interval from 0 to 999), microsecond (an integer in the inclusive interval from 0 to 999), and nanosecond (an integer in the inclusive interval from 0 to 999) and optional argument offsetNanoseconds (an integer in the interval from -nsPerDay (exclusive) to nsPerDay (exclusive)) and returns a BigInt. The returned value represents a number of nanoseconds since the epoch that corresponds to the given ISO 8601 calendar date and wall-clock time in UTC. If a UTC offset is provided, the returned value will be adjusted by that offset. It performs the following steps when called:

  1. Let date be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)).
  2. Let time be MakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond)).
  3. Let ms be MakeDate(date, time).
  4. Assert: ms is an integral Number.
  5. Return ((ms) × 106 + microsecond × 103 + nanosecond).
  6. Let epochNanoseconds be (ms) × 106 + microsecond × 103 + nanosecond.
  7. If offsetNanoseconds is present and offsetNanoseconds ≠ 0, set epochNanoseconds to epochNanoseconds - offsetNanoseconds.
  8. Return (epochNanoseconds).

14.7.2 Time Zone Identifiers

Time zones in ECMAScript are represented by time zone identifiers, which are Strings composed entirely of code units in the inclusive interval from 0x0000 to 0x007F0x0021 to 0x007E. Time zones supported by an ECMAScript implementation may be available named time zones, represented by the [[Identifier]] field of the Time Zone Identifier Records returned by AvailableNamedTimeZoneIdentifiers, or offset time zones, represented by Strings for which IsTimeZoneOffsetStringIsOffsetTimeZoneIdentifier returns true.

A primary time zone identifier is the preferred identifier for an available named time zone. A non-primary time zone identifier is an identifier for an available named time zone that is not a primary time zone identifier. An available named time zone identifier is either a primary time zone identifier or a non-primary time zone identifier. Each available named time zone identifier is associated with exactly one available named time zone. Each available named time zone is associated with exactly one primary time zone identifier and zero or more non-primary time zone identifiers.

Time zone identifiers are compared using ASCII-case-insensitive comparisons, and are accepted as input in any variation of letter case. Offset time zone identifiers are compared using the number of minutes represented (not as a String), and are accepted as input in any the formats specified by TimeZoneUTCOffsetName. However, ECMAScript built-in objects will only output the normalized format of a time zone identifier. The normalized format of an available named time zone identifier is the preferred letter case for that identifier. The normalized format of an offset time zone identifier is specified by NormalizedUTCOffset and produced by FormatOffsetTimeZoneIdentifier with style either not present or set to separated.

ECMAScript implementations must support an available named time zone with the identifier "UTC", which must be the primary time zone identifier for the UTC time zone. In addition, implementations may support any number of other available named time zones.

Implementations that follow the requirements for time zones as described in the ECMA-402 Internationalization API specification are called time zone aware. Time zone aware implementations must support available named time zones corresponding to the Zone and Link names of the IANA Time Zone Database, and only such names. In time zone aware implementations, a primary time zone identifier is a Zone name, and a non-primary time zone identifier is a Link name, respectively, in the IANA Time Zone Database except as specifically overridden by AvailableNamedTimeZoneIdentifiers as specified in the ECMA-402 specification. Implementations that do not support the entire IANA Time Zone Database are still recommended to use IANA Time Zone Database names as identifiers to represent time zones.

14.7.3 AvailableNamedTimeZoneIdentifiers ( )

The implementation-defined abstract operation AvailableNamedTimeZoneIdentifiers takes no arguments and returns a List of Time Zone Identifier Records. Its result describes all available named time zone identifiers in this implementation, as well as the primary time zone identifier corresponding to each available named time zone identifier. The List is ordered according to the [[Identifier]] field of each Time Zone Identifier Record.

Time zone aware implementations, including all implementations that implement the ECMA-402 Internationalization API, must implement the AvailableNamedTimeZoneIdentifiers abstract operation as specified in the ECMA-402 specification. For implementations that are not time zone aware, AvailableNamedTimeZoneIdentifiers performs the following steps when called:

  1. If the implementation does not include local political rules for any time zones, then
    1. Return « the Time Zone Identifier Record { [[Identifier]]: "UTC", [[PrimaryIdentifier]]: "UTC" } ».
  2. Let identifiers be the List of unique available named time zone identifiers.
  3. Sort identifiers into the same order as if an Array of the same values had been sorted using %Array.prototype.sort% with undefined as the argument.
  4. Set identifiers to SortStringListByCodeUnit(identifiers).
  5. Let result be a new empty List.
  6. For each element identifier of identifiers, do
    1. Let primary be identifier.
    2. If identifier is a non-primary time zone identifier in this implementation and identifier is not "UTC", then
      1. Set primary to the primary time zone identifier associated with identifier.
      2. NOTE: An implementation may need to resolve identifier iteratively to obtain the primary time zone identifier.
    3. Let record be the Time Zone Identifier Record { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }.
    4. Append record to result.
  7. Assert: result contains a Time Zone Identifier Record r such that r.[[Identifier]] is "UTC" and r.[[PrimaryIdentifier]] is "UTC".
  8. Return result.
Note
Time zone identifiers in the IANA Time Zone Database can change over time. At a minimum, implementations must limit changes to the result of AvailableNamedTimeZoneIdentifiers to the changes allowed by GetAvailableNamedTimeZoneIdentifier, for the lifetime of the surrounding agent. That is, implementations must not remove support for or change the primary vs. non-primary status of an identifier that was already reported as available, and they must not add support for an identifier that was already reported as not available. Due to the complexity of supporting these recommendations, it is recommended that the result of AvailableNamedTimeZoneIdentifiers remains the same for the lifetime of the surrounding agent.

14.7.4 SystemTimeZoneIdentifier ( )

The implementation-defined abstract operation SystemTimeZoneIdentifier takes no arguments and returns a String. It returns a String representing the host environment's current time zone, which is either a String representing a UTC offset for which IsTimeZoneOffsetString returns true, or a primary time zone identifiera primary time zone identifier or an offset time zone identifier. It performs the following steps when called:

  1. If the implementation only supports the UTC time zone, return "UTC".
  2. Let systemTimeZoneString be the String representing the host environment's current time zone as a time zone identifier in normalized format, either a primary time zone identifier or an offset time zone identifier.
  3. Return systemTimeZoneString.
Note

To ensure the level of functionality that implementations commonly provide in the methods of the Date object, it is recommended that SystemTimeZoneIdentifier return an IANA time zone name corresponding to the host environment's time zone setting, if such a thing exists. GetNamedTimeZoneEpochNanoseconds and GetNamedTimeZoneOffsetNanoseconds must reflect the local political rules for standard time and daylight saving time in that time zone, if such rules exist.

For example, if the host environment is a browser on a system where the user has chosen US Eastern Time as their time zone, SystemTimeZoneIdentifier returns "America/New_York".

14.7.5 Time Zone Offset String FormatFormats

ECMAScript defines a string interchange format for UTC offsets, derived from ISO 8601. The format is described by the following grammar. The usage of Unicode code points in this grammar is listed in Table 62.

ECMAScript defines string interchange formats for UTC offsets, derived from ISO 8601. UTC offsets that represent offset time zone identifiers, or that are intended for interoperability with ISO 8601, use only hours and minutes and are specified by UTCOffsetMinutePrecision. UTC offsets that represent the offset of a named or custom time zone can be more precise, and are specified by UTCOffsetSubMinutePrecision.

These formats are described by the ISO String grammar in 13.31. The usage of Unicode code points in this grammar is listed in Table 62.

[...]

Editor's Note
The grammar in this section should be deleted; it is replaced by the ISO 8601 String grammar in 13.31.

14.7.6 LocalTime ( t )

The abstract operation LocalTime takes argument t (a finite time value) and returns an integral Number. It converts t from UTC to local time. The local political rules for standard time and daylight saving time in effect at t should be used to determine the result in the way specified in this section. It performs the following steps when called:

  1. Let systemTimeZoneIdentifier be SystemTimeZoneIdentifier().
  2. Let parseResult be ! ParseTimeZoneIdentifier(systemTimeZoneIdentifier).
  3. If IsTimeZoneOffsetString(systemTimeZoneIdentifier) is trueparseResult.[[OffsetMinutes]] is not empty, then
    1. Let offsetNs be ParseTimeZoneOffsetString(systemTimeZoneIdentifier)parseResult.[[OffsetMinutes]] × (60 × 109).
  4. Else,
    1. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((t) × 106)).
  5. Let offsetMs be truncate(offsetNs / 106).
  6. Return t + 𝔽(offsetMs).
Note 1

If political rules for the local time t are not available within the implementation, the result is t because SystemTimeZoneIdentifier returns "UTC" and GetNamedTimeZoneOffsetNanoseconds returns 0.

Note 2

It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.

Note 3

Two different input time values tUTC are converted to the same local time tlocal at a negative time zone transition when there are repeated times (e.g. the daylight saving time ends or the time zone adjustment is decreased.).

LocalTime(UTC(tlocal)) is not necessarily always equal to tlocal. Correspondingly, UTC(LocalTime(tUTC)) is not necessarily always equal to tUTC.

14.7.7 UTC ( t )

The abstract operation UTC takes argument t (a Number) and returns a time value. It converts t from local time to a UTC time value. The local political rules for standard time and daylight saving time in effect at t should be used to determine the result in the way specified in this section. It performs the following steps when called:

  1. If t is not finite, return NaN.
  2. Let systemTimeZoneIdentifier be SystemTimeZoneIdentifier().
  3. Let parseResult be ! ParseTimeZoneIdentifier(systemTimeZoneIdentifier).
  4. If IsTimeZoneOffsetString(systemTimeZoneIdentifier) is trueparseResult.[[OffsetMinutes]] is not empty, then
    1. Let offsetNs be ParseTimeZoneOffsetString(systemTimeZoneIdentifier)parseResult.[[OffsetMinutes]] × (60 × 109).
  5. Else,
    1. Let possibleInstants be GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(t)), (MonthFromTime(t)) + 1, (DateFromTime(t)), (HourFromTime(t)), (MinFromTime(t)), (SecFromTime(t)), (msFromTime(t)), 0, 0).
    2. NOTE: The following steps ensure that when t represents local time repeating multiple times at a negative time zone transition (e.g. when the daylight saving time ends or the time zone offset is decreased due to a time zone rule change) or skipped local time at a positive time zone transition (e.g. when the daylight saving time starts or the time zone offset is increased due to a time zone rule change), t is interpreted using the time zone offset before the transition.
    3. If possibleInstants is not empty, then
      1. Let disambiguatedInstant be possibleInstants[0].
    4. Else,
      1. NOTE: t represents a local time skipped at a positive time zone transition (e.g. due to daylight saving time starting or a time zone rule change increasing the UTC offset).
      2. Let possibleInstantsBefore be GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(tBefore)), (MonthFromTime(tBefore)) + 1, (DateFromTime(tBefore)), (HourFromTime(tBefore)), (MinFromTime(tBefore)), (SecFromTime(tBefore)), (msFromTime(tBefore)), 0, 0), where tBefore is the largest integral Number < t for which possibleInstantsBefore is not empty (i.e., tBefore represents the last local time before the transition).
      3. Let disambiguatedInstant be the last element of possibleInstantsBefore.
    5. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant).
  6. Let offsetMs be truncate(offsetNs / 106).
  7. Return t - 𝔽(offsetMs).

Input t is nominally a time value but may be any Number value. The algorithm must not limit t to the time value range, so that inputs corresponding with a boundary of the time value range can be supported regardless of local UTC offset. For example, the maximum time value is 8.64 × 1015, corresponding with "+275760-09-13T00:00:00Z". In an environment where the local time zone offset is ahead of UTC by 1 hour at that instant, it is represented by the larger input of 8.64 × 1015 + 3.6 × 106, corresponding with "+275760-09-13T01:00:00+01:00".

If political rules for the local time t are not available within the implementation, the result is t because SystemTimeZoneIdentifier returns "UTC" and GetNamedTimeZoneOffsetNanoseconds returns 0.

Note 1

It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.

1:30 AM on 5 November 2017 in America/New_York is repeated twice (fall backward), but it must be interpreted as 1:30 AM UTC-04 instead of 1:30 AM UTC-05. In UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))), the value of offsetMs is -4 × msPerHour.

2:30 AM on 12 March 2017 in America/New_York does not exist, but it must be interpreted as 2:30 AM UTC-05 (equivalent to 3:30 AM UTC-04). In UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))), the value of offsetMs is -5 × msPerHour.

Note 2

UTC(LocalTime(tUTC)) is not necessarily always equal to tUTC. Correspondingly, LocalTime(UTC(tlocal)) is not necessarily always equal to tlocal.

[...]

14.7.8 TimeString ( tv )

The abstract operation TimeString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. Let hour be ToZeroPaddedDecimalString((HourFromTime(tv)), 2).
  2. Let minute be ToZeroPaddedDecimalString((MinFromTime(tv)), 2).
  3. Let second be ToZeroPaddedDecimalString((SecFromTime(tv)), 2).
  4. Let timeString be FormatTimeString((HourFromTime(tv)), (MinFromTime(tv)), (SecFromTime(tv)), 0, 0).
  5. Return the string-concatenation of hour, ":", minute, ":", secondtimeString, the code unit 0x0020 (SPACE), and "GMT".

[...]

14.7.9 TimeZoneString ( tv )

The abstract operation TimeZoneString takes argument tv (an integral Number) and returns a String. It performs the following steps when called:

  1. Let systemTimeZoneIdentifier be SystemTimeZoneIdentifier().
  2. If IsTimeZoneOffsetString(systemTimeZoneIdentifier) is true, then
    1. Let offsetNs be ParseTimeZoneOffsetString(systemTimeZoneIdentifier).
  3. Else,
  4. Let offsetMinutes be ! ParseTimeZoneIdentifier(systemTimeZoneIdentifier).[[OffsetMinutes]].
  5. If offsetMinutes is empty, then
    1. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((tv) × 106)).
    2. Set offsetMinutes to truncate(offsetNs / (60 × 109)).
  6. Let offset be 𝔽(truncate(offsetNs / 106)).
  7. If offset is +0𝔽 or offset > +0𝔽, then
    1. Let offsetSign be "+".
    2. Let absOffset be offset.
  8. Else,
    1. Let offsetSign be "-".
    2. Let absOffset be -offset.
  9. Let offsetMin be ToZeroPaddedDecimalString((MinFromTime(absOffset)), 2).
  10. Let offsetHour be ToZeroPaddedDecimalString((HourFromTime(absOffset)), 2).
  11. Let offsetString be FormatOffsetTimeZoneIdentifier(offsetMinutes, unseparated).
  12. Let tzName be an implementation-defined string that is either the empty String or the string-concatenation of the code unit 0x0020 (SPACE), the code unit 0x0028 (LEFT PARENTHESIS), an implementation-defined timezone name, and the code unit 0x0029 (RIGHT PARENTHESIS).
  13. Return the string-concatenation of offsetSign, offsetHour, offsetMin, and tzName.
  14. Return the string-concatenation of offsetString and tzName.

IsTimeZoneOffsetString ( offsetString: a String, ): a Boolean

14.7.10 IsOffsetTimeZoneIdentifier ( offsetString )

The abstract operation IsOffsetTimeZoneIdentifier takes argument offsetString (a String) and returns a Boolean. The return value indicates whether offsetString conforms to the grammar given by UTCOffsetTimeZoneUTCOffsetName. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(offsetString), UTCOffsetTimeZoneUTCOffsetName).
  2. If parseResult is a List of errors, return false.
  3. Return true.

ParseTimeZoneOffsetString ( offsetString: a String, ): an integer

14.7.11 ParseDateTimeUTCOffset ( offsetString )

The abstract operation ParseDateTimeUTCOffset takes argument offsetString (a String) and returns either a normal completion containing an integer, or a throw completion. The return value is the UTC offset, as a number of nanoseconds, that corresponds to the String offsetString. If offsetString is invalid, a RangeError is thrown. It performs the following steps when called:

  1. Let parseResult be ParseText(StringToCodePoints(offsetString), UTCOffsetUTCOffsetSubMinutePrecision).
  2. Assert: parseResult is not a List of errors.
  3. If parseResult is a List of errors, throw a RangeError exception.
  4. Assert: parseResult contains a TemporalSign Parse Node.
  5. Let parsedSign be the source text matched by the TemporalSign Parse Node contained within parseResult.
  6. If parsedSign is the single code point U+002D (HYPHEN-MINUS) or U+2212 (MINUS SIGN), then
    1. Let sign be -1.
  7. Else,
    1. Let sign be 1.
  8. NOTE: Applications of StringToNumber below do not lose precision, since each of the parsed values is guaranteed to be a sufficiently short string of decimal digits.
  9. Assert: parseResult contains an Hour Parse Node.
  10. Let parsedHours be the source text matched by the Hour Parse Node contained within parseResult.
  11. Let hours be (StringToNumber(CodePointsToString(parsedHours))).
  12. If parseResult does not contain a MinuteSecond Parse Node, then
    1. Let minutes be 0.
  13. Else,
    1. Let parsedMinutes be the source text matched by the first MinuteSecond Parse Node contained within parseResult.
    2. Let minutes be (StringToNumber(CodePointsToString(parsedMinutes))).
  14. If parseResult does not contain two MinuteSecond Parse Nodes, then
    1. Let seconds be 0.
  15. Else,
    1. Let parsedSeconds be the source text matched by the second MinuteSecond Parse Node contained within parseResult.
    2. Let seconds be (StringToNumber(CodePointsToString(parsedSeconds))).
  16. If parseResult does not contain a TemporalDecimalFraction Parse Node, then
    1. Let nanoseconds be 0.
  17. Else,
    1. Let parsedFraction be the source text matched by the TemporalDecimalFraction Parse Node contained within parseResult.
    2. Let fraction be the string-concatenation of CodePointsToString(parsedFraction) and "000000000".
    3. Let nanosecondsString be the substring of fraction from 1 to 10.
    4. Let nanoseconds be (StringToNumber(nanosecondsString)).
  18. Return sign × (((hours × 60 + minutes) × 60 + seconds) × 109 + nanoseconds).

14.8 The Date Constructor

14.8.1 Date ( ...values )

This function performs the following steps when called:

  1. If NewTarget is undefined, then
    1. Let now be the time value (UTC) identifying the current time.
    2. Return ToDateString(now).
  2. If NewTarget is undefined, return ToDateString(SystemUTCEpochMilliseconds()).
  3. Let numberOfArgs be the number of elements in values.
  4. If numberOfArgs = 0, then
    1. Let dv be the time value (UTC) identifying the current time SystemUTCEpochMilliseconds().
  5. Else if numberOfArgs = 1, then
    1. Let value be values[0].
    2. If value is an Object and value has a [[DateValue]] internal slot, then
      1. Let tv be value.[[DateValue]].
    3. Else,
      1. Let v be ? ToPrimitive(value).
      2. If v is a String, then
        1. Assert: The next step never returns an abrupt completion because v is a String.
        2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
      3. Else,
        1. Let tv be ? ToNumber(v).
    4. Let dv be TimeClip(tv).
  6. Else,
    1. Assert: numberOfArgs ≥ 2.
    2. Let y be ? ToNumber(values[0]).
    3. Let m be ? ToNumber(values[1]).
    4. If numberOfArgs > 2, let dt be ? ToNumber(values[2]); else let dt be 1𝔽.
    5. If numberOfArgs > 3, let h be ? ToNumber(values[3]); else let h be +0𝔽.
    6. If numberOfArgs > 4, let min be ? ToNumber(values[4]); else let min be +0𝔽.
    7. If numberOfArgs > 5, let s be ? ToNumber(values[5]); else let s be +0𝔽.
    8. If numberOfArgs > 6, let milli be ? ToNumber(values[6]); else let milli be +0𝔽.
    9. Let yr be MakeFullYear(y).
    10. Let finalDate be MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)).
    11. Let dv be TimeClip(UTC(finalDate)).
  7. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »).
  8. Set O.[[DateValue]] to dv.
  9. Return O.

14.9 Properties of the Date Constructor

14.9.1 Date.now ( )

This function returns the time value designating the UTC date and time of the occurrence of the call to it.

This function performs the following steps when called:

  1. Return SystemUTCEpochMilliseconds().

14.10 Properties of the Date Prototype Object

14.10.1 Date.prototype.toTemporalInstant ( )

This method performs the following steps when called:

  1. Let dateObject be the this value.
  2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
  3. Let t be dateObject.[[DateValue]].
  4. Let ns be ? NumberToBigInt(t) × (106).
  5. Return ! CreateTemporalInstant(ns).

15 Amendments to the ECMAScript® 2023 Internationalization API Specification

Editor's Note

This section lists amendments which must be made to ECMA-402, the ECMAScript® 2023 Internationalization API Specification. Text to be added is marked like this, and text to be deleted is marked like this. Blocks of unmodified text between modified sections are marked by [...].

This text is based on top of the ECMA-402 spec text from commit 537afda7be28a443b79b3fd7e6c836a16ce4f75f.

15.1 Case Sensitivity and Case Mapping

Editor's Note

These definitions are moved into ECMA-262.

The String values used to identify locales, currencies, scripts, and time zones are interpreted in an ASCII-case-insensitive manner, treating the code units 0x0041 through 0x005A (corresponding to Unicode characters LATIN CAPITAL LETTER A through LATIN CAPITAL LETTER Z) as equivalent to the corresponding code units 0x0061 through 0x007A (corresponding to Unicode characters LATIN SMALL LETTER A through LATIN SMALL LETTER Z), both inclusive. No other case folding equivalences are applied.

Note
For example, "ß" (U+00DF) must not match or be mapped to "SS" (U+0053, U+0053). "ı" (U+0131) must not match or be mapped to "I" (U+0049).

The ASCII-uppercase of a String value S is the String value derived from S by replacing each occurrence of an ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) with the corresponding ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) while preserving all other code units.

The ASCII-lowercase of a String value S is the String value derived from S by replacing each occurrence of an ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) with the corresponding ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) while preserving all other code units.

A String value A is an ASCII-case-insensitive match for String value B if the ASCII-uppercase of A is exactly the same sequence of code units as the ASCII-uppercase of B. A sequence of Unicode code points A is an ASCII-case-insensitive match for B if B is an ASCII-case-insensitive match for ! CodePointsToString(A).

15.2 Use of the IANA Time Zone Database

Editor's Note
This section replaces the Time Zone Names section in ECMA-402.

Implementations that adopt this specification are time zone aware: they use the IANA Time Zone Database https://www.iana.org/time-zones/ to supply time zone identifiers and data used in ECMAScript calculations and formatting. This section defines how the IANA Time Zone Database should be used by time zone aware implementations.

Except as overridden by AvailableNamedTimeZoneIdentifiers, each Zone in the IANA Time Zone Database must be a primary time zone identifier and each Link name in the IANA Time Zone Database must be a non-primary time zone identifier. No String may be an available named time zone identifier unless it is a Zone name or a Link name in the IANA Time Zone Database. Available named time zone identifiers returned by ECMAScript built-in objects must use the casing found in the IANA Time Zone Database.

In the IANA Time Zone Database, the UTC time zone is represented by the Zone "Etc/UTC" which is distinct from the Zone "Etc/GMT". For historical reasons, ECMAScript uses "UTC" as the primary identifier for the former Zone and does not recognize the latter Zone as distinct, instead requiring "Etc/UTC", "Etc/GMT", and "GMT" (if available) to be non-primary identifiers that resolve to "UTC". This is the only deviation from the IANA Time Zone Database that is required of a time zone aware ECMAScript implementation.

The IANA Time Zone Database is typically updated between five and ten times per year. These updates may add new Zone or Link names, may change Zones to Links, and may change the UTC offsets and transitions associated with any Zone. ECMAScript implementations are recommended to include updates to the IANA Time Zone Database as soon as possible. Such prompt action ensures that ECMAScript programs can accurately perform time-zone-sensitive calculations and can use newly-added available named time zone identifiers supplied by external input or the host environment.

Note 1

Although the IANA Time Zone Database maintainers strive for stability, in rare cases (averaging less than once per year) a Zone may be replaced by a new Zone. For example, in 2022 "Europe/Kiev" was deprecated to a Link resolving to a new "Europe/Kyiv" Zone.

To reduce disruption from renaming changes, ECMAScript implementations are encouraged to initially add the new Zone as a non-primary time zone identifier that resolves to the current primary identifier. Then, after a waiting period, implementations are recommended to promote the new Zone to a primary time zone identifier while simultaneously demoting the deprecated name to non-primary. The recommended waiting period is two years after the IANA Time Zone Database release containing the changes. This delay allows other systems, that ECMAScript programs may interact with, to be updated to recognize the new Zone.

A waiting period should only apply when a new Zone is added to replace an existing Zone. If an existing Zone and Link are swapped, then no waiting period is necessary.

If implementations revise time zone information during the lifetime of an agent, then which identifiers are supported, the primary time zone identifier associated with any identifier, and the UTC offsets and transitions associated with any Zone, must be consistent with results previously observed by that agent. Due to the complexity of supporting this requirement, it is recommended that implementations maintain a fully consistent copy of the IANA Time Zone Database for the lifetime of each agent.

This section complements but does not supersede 14.7.2.

Note 2

The IANA Time Zone Database offers build options that affect which time zone identifiers are primary. The default build options merge different countries' time zones, for example "Atlantic/Reykjavik" being a Link to the Zone "Africa/Abidjan". Geographically and politically distinct locations are likely to introduce divergent time zone rules in a future version of the IANA Time Zone Database. Therefore, it is recommended that ECMAScript implementations instead use build options such as PACKRATDATA=backzone PACKRATLIST=zone.tab or a similar alternative that ensures at least one primary identifier for each ISO 3166-1 Alpha-2 country code.

15.2.1 AvailableNamedTimeZoneIdentifiers ( )

The implementation-defined abstract operation AvailableNamedTimeZoneIdentifiers takes no arguments and returns a List of Time Zone Identifier Records. Its result describes all available named time zone identifiers in this implementation, as well as the primary time zone identifier corresponding to each available named time zone identifier. The List is ordered according to the [[Identifier]] field of each Time Zone Identifier Record.

This definition supersedes the definition provided in 14.7.3.

  1. Let identifiers be a List containing the String value of each Zone or Link name in the IANA Time Zone Database.
  2. Assert: No element of identifiers is an ASCII-case-insensitive match for any other element.
  3. Assert: Every element of identifiers identifies a Zone or Link name in the IANA Time Zone Database.
  4. Set identifiers to SortStringListByCodeUnit(identifiers).
  5. Let result be a new empty List.
  6. For each element identifier of identifiers, do
    1. Let primary be identifier.
    2. If identifier is a non-primary time zone identifier and identifier is not "UTC", then
      1. Set primary to the name of the primary time zone identifier that identifier resolves to, according to the rules for resolving Link names in the IANA Time Zone Database.
      2. NOTE: An implementation may need to resolve identifier iteratively to obtain the primary time zone identifier.
    3. If primary is one of "Etc/UTC", "Etc/GMT", or "GMT", set primary to "UTC".
    4. Let record be the Time Zone Identifier Record { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }.
    5. Append record to result.
  7. Assert: result contains a Time Zone Identifier Record r such that r.[[Identifier]] is "UTC" and r.[[PrimaryIdentifier]] is "UTC".
  8. Return result.
Note
Time zone identifiers in the IANA Time Zone Database can change over time. At a minimum, implementations must limit changes to the result of AvailableNamedTimeZoneIdentifiers to the changes allowed by GetAvailableNamedTimeZoneIdentifier, for the lifetime of the surrounding agent. That is, implementations must not remove support for or change the primary vs. non-primary status of an identifier that was already reported as available, and they must not add support for an identifier that was already reported as not available. Due to the complexity of supporting these recommendations, it is recommended that the result of AvailableNamedTimeZoneIdentifiers remains the same for the lifetime of the surrounding agent.

15.3 Time Zone Names

This specification identifies time zones using the Zone and Link names of the IANA Time Zone Database. Their canonical form is the corresponding Zone name in the casing used in the IANA Time Zone Database except as specifically overridden by CanonicalizeTimeZoneName.

A conforming implementation must recognize "UTC" and all other Zone and Link names (and only such names), and use best available current and historical information about their offsets from UTC and their daylight saving time rules in calculations. However, the set of combinations of time zone name and language tag for which localized time zone names are available is implementation dependent.

15.3.1 IsValidTimeZoneName ( timeZone )

The abstract operation IsValidTimeZoneName takes argument timeZone (a String) and returns a Boolean. It verifies that the timeZone argument represents a valid Zone or Link name of the IANA Time Zone Database. It performs the following steps when called:

  1. If one of the Zone or Link names of the IANA Time Zone Database is an ASCII-case-insensitive match for timeZone, return true.
  2. If timeZone is an ASCII-case-insensitive match for "UTC", return true.
  3. Return false.
Note
Any value returned from SystemTimeZoneIdentifier that is not recognized as valid by IsTimeZoneOffsetString must be recognized as valid by IsValidTimeZoneName.

15.3.2 CanonicalizeTimeZoneName ( timeZone )

The abstract operation CanonicalizeTimeZoneName takes argument timeZone (a String value that is a valid time zone name as verified by IsValidTimeZoneName). It returns the canonical and case-regularized form of timeZone. It performs the following steps when called:

  1. Let ianaTimeZone be the String value of the Zone or Link name of the IANA Time Zone Database that is an ASCII-case-insensitive match of timeZone.
  2. If ianaTimeZone is a Link name, set ianaTimeZone to the String value of the corresponding Zone name as specified in the file backward of the IANA Time Zone Database.
  3. If ianaTimeZone is "Etc/UTC" or "Etc/GMT", or "GMT", return "UTC".
  4. Return ianaTimeZone.

15.3.3 AvailableCanonicalTimeZones ( )

The implementation-defined abstract operation AvailableCanonicalTimeZones takes no arguments and returns a List of Strings. The returned List is a sorted List of supported Zone and Link names in the IANA Time Zone Database. It performs the following steps when called:

  1. Let names be a List of all Zone and Link names in the IANA Time Zone Database that are supported by the implementation.
  2. Let result be a new empty List.
  3. For each element name of names, do
    1. Assert: IsValidTimeZoneName( name ) is true.
    2. Let canonical be CanonicalizeTimeZoneName( name ).
    3. If result does not contain canonical, then
      1. Append canonical to result.
  4. Sort result in order as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn.
  5. Return result.

15.4 The Intl Object

[...]

15.4.1 Function Properties of the Intl Object

[...]

15.4.1.1 Intl.supportedValuesOf ( key )

When the supportedValuesOf method is called with argument key , the following steps are taken:

  1. Let key be ? ToString(key).
  2. If key is "calendar", then
    1. Let list be AvailableCanonicalCalendars( ).
  3. Else if key is "collation", then
    1. Let list be AvailableCanonicalCollations( ).
  4. Else if key is "currency", then
    1. Let list be AvailableCanonicalCurrencies( ).
  5. Else if key is "numberingSystem", then
    1. Let list be AvailableCanonicalNumberingSystems( ).
  6. Else if key is "timeZone", then
    1. Let list be AvailableCanonicalTimeZones( ).
    2. Let timeZones be AvailableNamedTimeZoneIdentifiers().
    3. Let list be a List consisting of every element record of timeZones for which record.[[Identifier]] = record.[[PrimaryIdentifier]].
  7. Else if key is "unit", then
    1. Let list be AvailableCanonicalUnits( ).
  8. Else,
    1. Throw a RangeError exception.
  9. Return CreateArrayFromList( list ).

15.5 Abstract Operations

Editor's Note

In this section, some abstract operations that manipulate options objects are to be moved from ECMA-402 into ECMA-262.

15.5.1 GetOptionsObject ( options )

The abstract operation GetOptionsObject takes argument options (an ECMAScript language value) and returns either a normal completion containing an Object or a throw completion. It returns an Object suitable for use with GetOption, either options itself or a default empty Object. It throws a TypeError if options is not undefined and not an Object. It performs the following steps when called:

  1. If options is undefined, then
    1. Return OrdinaryObjectCreate(null).
  2. If Type(options) is Object, then
    1. Return options.
  3. Throw a TypeError exception.

[...]

15.5.2 GetOption ( options, property, type, values, default )

The abstract operation GetOption takes arguments options (an Object), property (a property key), type (boolean or string), values (empty or a List of ECMAScript language values), and default (required or an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It extracts the value of the specified property of options, converts it to the required type, checks whether it is allowed by values if values is not empty, and substitutes default if the value is undefined. It performs the following steps when called:

  1. Let value be ? Get(options, property).
  2. If value is undefined, then
    1. If default is required, throw a RangeError exception.
    2. Return default.
  3. If type is boolean, then
    1. Set value to ToBoolean(value).
  4. Else,
    1. Assert: type is string.
    2. Set value to ? ToString(value).
  5. If values is not empty and values does not contain value, throw a RangeError exception.
  6. Return value.

[...]

Table 25: Rounding modes in Intl.NumberFormat
Identifier Description Examples: Round to 0 fraction digits
-1.5 0.4 0.5 0.6 1.5
"ceil" Toward positive infinity ⬆️ [-1] ⬆️ [1] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"floor" Toward negative infinity ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬇️ [0] ⬇️ [1]
"expand" Away from zero ⬇️ [-2] ⬆️ [1] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"trunc" Toward zero ⬆️ [-1] ⬇️ [0] ⬇️ [0] ⬇️ [0] ⬇️ [1]
"halfCeil" Ties toward positive infinity ⬆️ [-1] ⬇️ [0] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"halfFloor" Ties toward negative infinity ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬇️ [1]
"halfExpand" Ties away from zero ⬇️ [-2] ⬇️ [0] ⬆️ [1] ⬆️ [1] ⬆️ [2]
"halfTrunc" Ties toward zero ⬆️ [-1] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬇️ [1]
"halfEven" Ties toward an even rounding increment multiple ⬇️ [-2] ⬇️ [0] ⬇️ [0] ⬆️ [1] ⬆️ [2]
Note
The examples are illustrative of the unique behaviour of each option. ⬆️ means "resolves toward positive infinity"; ⬇️ means "resolves toward negative infinity".

15.5.3 GetUnsignedRoundingMode ( roundingMode, sign )

The abstract operation GetUnsignedRoundingMode takes arguments roundingMode (a String) and sign (negative or positive) and returns a specification type from the Unsigned Rounding Mode column of Table 26. It returns the rounding mode that should be applied to the absolute value of a number to produce the same result as if roundingMode, one of the String values in the Identifier column of Table 25, were applied to the signed value of the number (negative if sign is negative, or positive otherwise). It performs the following steps when called:

  1. Return the specification type in the Unsigned Rounding Mode column of Table 26 for the row where the value in the Identifier column is roundingMode and the value in the Sign column is sign.
Table 26: Conversion from rounding mode to unsigned rounding mode
Identifier Sign Unsigned Rounding Mode
"ceil" positive infinity
negative zero
"floor" positive zero
negative infinity
"expand" positive infinity
negative infinity
"trunc" positive zero
negative zero
"halfCeil" positive half-infinity
negative half-zero
"halfFloor" positive half-zero
negative half-infinity
"halfExpand" positive half-infinity
negative half-infinity
"halfTrunc" positive half-zero
negative half-zero
"halfEven" positive half-even
negative half-even

15.5.4 ApplyUnsignedRoundingMode ( x, r1, r2, unsignedRoundingMode )

The abstract operation ApplyUnsignedRoundingMode takes arguments x (a mathematical value), r1 (a mathematical value), r2 (a mathematical value), and unsignedRoundingMode (a specification type from the Unsigned Rounding Mode column of Table 26, or undefined) and returns a mathematical value. It considers x, bracketed below by r1 and above by r2, and returns either r1 or r2 according to unsignedRoundingMode. It performs the following steps when called:

  1. If x is equal to r1, return r1.
  2. Assert: r1 < x < r2.
  3. Assert: unsignedRoundingMode is not undefined.
  4. If unsignedRoundingMode is zero, return r1.
  5. If unsignedRoundingMode is infinity, return r2.
  6. Let d1 be xr1.
  7. Let d2 be r2x.
  8. If d1 < d2, return r1.
  9. If d2 < d1, return r2.
  10. Assert: d1 is equal to d2.
  11. If unsignedRoundingMode is half-zero, return r1.
  12. If unsignedRoundingMode is half-infinity, return r2.
  13. Assert: unsignedRoundingMode is half-even.
  14. Let cardinality be (r1 / (r2r1)) modulo 2.
  15. If cardinality is 0, return r1.
  16. Return r2.

15.6 The Intl.DateTimeFormat Constructor

[...]

15.6.1 CreateDateTimeFormat ( newTarget, locales, options, required, defaults [ , toLocaleStringTimeZone ] )

The abstract operation CreateDateTimeFormat takes arguments newTarget (a constructor), locales (an ECMAScript language value), options (an ECMAScript language value), required (date, time, or any), and defaults (date, time, or all) and optional argument toLocaleStringTimeZone (a primary time zone identifier) and returns either a normal completion containing a DateTimeFormat object or a throw completion.

If the additional toLocaleStringTimeZone argument is provided, the time zone will be overridden and some adjustments will be made to the defaults in order to implement the behaviour of Temporal.ZonedDateTime.prototype.toLocaleString.

It performs the following steps when called:

  1. Let dateTimeFormat be ? OrdinaryCreateFromConstructor(newTarget, "%Intl.DateTimeFormat.prototype%", « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[DayPeriod]], [[Hour]], [[Minute]], [[Second]], [[FractionalSecondDigits]], [[TimeZoneName]], [[HourCycle]], [[DateStyle]], [[TimeStyle]], [[Pattern]], [[RangePatterns]], [[BoundFormat]] »).
  2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
  3. Set options to ? CoerceOptionsToObject(options).
  4. Let opt be a new Record.
  5. Let matcher be ? GetOption(options, "localeMatcher", string, « "lookup", "best fit" », "best fit").
  6. Set opt.[[localeMatcher]] to matcher.
  7. Let calendar be ? GetOption(options, "calendar", string, empty, undefined).
  8. If calendar is not undefined, then
    1. If calendar cannot be matched by the type Unicode locale nonterminal, throw a RangeError exception.
  9. Set opt.[[ca]] to calendar.
  10. Let numberingSystem be ? GetOption(options, "numberingSystem", string, empty, undefined).
  11. If numberingSystem is not undefined, then
    1. If numberingSystem cannot be matched by the type Unicode locale nonterminal, throw a RangeError exception.
  12. Set opt.[[nu]] to numberingSystem.
  13. Let hour12 be ? GetOption(options, "hour12", boolean, empty, undefined).
  14. Let hourCycle be ? GetOption(options, "hourCycle", string, « "h11", "h12", "h23", "h24" », undefined).
  15. If hour12 is not undefined, then
    1. Set hourCycle to null.
  16. Set opt.[[hc]] to hourCycle.
  17. Let localeData be %Intl.DateTimeFormat%.[[LocaleData]].
  18. Let r be ResolveLocale(%Intl.DateTimeFormat%.[[AvailableLocales]], requestedLocales, opt, %Intl.DateTimeFormat%.[[RelevantExtensionKeys]], localeData).
  19. Set dateTimeFormat.[[Locale]] to r.[[locale]].
  20. Let resolvedCalendar be r.[[ca]].
  21. Set dateTimeFormat.[[Calendar]] to resolvedCalendar.
  22. Set dateTimeFormat.[[NumberingSystem]] to r.[[nu]].
  23. Let dataLocale be r.[[dataLocale]].
  24. Let dataLocaleData be localeData.[[<dataLocale>]].
  25. If hour12 is true, then
    1. Let hc be dataLocaleData.[[hourCycle12]].
  26. Else if hour12 is false, then
    1. Let hc be dataLocaleData.[[hourCycle24]].
  27. Else,
    1. Assert: hour12 is undefined.
    2. Let hc be r.[[hc]].
    3. If hc is null, set hc to dataLocaleData.[[hourCycle]].
  28. Set dateTimeFormat.[[HourCycle]] to hc.
  29. Let timeZone be ? Get(options, "timeZone").
  30. If timeZone is undefined, then
    1. If toLocaleStringTimeZone is present, then
      1. Set timeZone to toLocaleStringTimeZone.
    2. Else,
      1. Set timeZone to SystemTimeZoneIdentifier().
  31. Else,
    1. If toLocaleStringTimeZone is present, throw a TypeError exception.
    2. Set timeZone to ? ToString(timeZone).
  32. If IsTimeZoneOffsetString(timeZone) is true, then
    1. Let parseResult be ParseText(StringToCodePoints(timeZone), UTCOffsetUTCOffsetMinutePrecision).
    2. Assert: parseResult is a Parse Node.
    3. If parseResult contains more than one MinuteSecond Parse Node, throw a RangeError exception.
    4. Let offsetNanoseconds be ParseTimeZoneOffsetStringParseDateTimeUTCOffset(timeZone).
    5. Let offsetMinutes be offsetNanoseconds / (6 × 1010).
    6. Assert: offsetMinutes is an integer.
    7. Set timeZone to FormatOffsetTimeZoneIdentifier(offsetMinutes).
  33. Else if IsValidTimeZoneName(timeZone) is true, then
  34. Else,
    1. Let timeZoneIdentifierRecord be GetAvailableNamedTimeZoneIdentifier(timeZone).
    2. If timeZoneIdentifierRecord is empty, then
      1. Throw a RangeError exception.
    3. Set timeZone to CanonicalizeTimeZoneName(timeZone)timeZoneIdentifierRecord.[[Identifier]].
  35. Else,
    1. Throw a RangeError exception.
  36. Set dateTimeFormat.[[TimeZone]] to timeZone.
  37. Let formatOptions be a new Record.
  38. Set formatOptions.[[hourCycle]] to hc.
  39. Let hasExplicitFormatComponents be false.
  40. For each row of Table 7, except the header row, in table order, do
    1. Let prop be the name given in the Property column of the row.
    2. If prop is "fractionalSecondDigits", then
      1. Let value be ? GetNumberOption(options, "fractionalSecondDigits", 1, 3, undefined).
    3. Else,
      1. Let values be a List whose elements are the strings given in the Values column of the row.
      2. Let value be ? GetOption(options, prop, string, values, undefined).
    4. Set formatOptions.[[<prop>]] to value.
    5. If value is not undefined, then
      1. Set hasExplicitFormatComponents to true.
  41. Let formatMatcher be ? GetOption(options, "formatMatcher", string, « "basic", "best fit" », "best fit").
  42. Let dateStyle be ? GetOption(options, "dateStyle", string, « "full", "long", "medium", "short" », undefined).
  43. Set dateTimeFormat.[[DateStyle]] to dateStyle.
  44. Let timeStyle be ? GetOption(options, "timeStyle", string, « "full", "long", "medium", "short" », undefined).
  45. Set dateTimeFormat.[[TimeStyle]] to timeStyle.
  46. Let expandedOptions be a copy of formatOptions.
  47. If dateStyle is not undefined or timeStyle is not undefined, then
    1. If hasExplicitFormatComponents is true, then
      1. Throw a TypeError exception.
    2. If required is date and timeStyle is not undefined, then
      1. Throw a TypeError exception.
    3. If required is time and dateStyle is not undefined, then
      1. Throw a TypeError exception.
    4. Let styles be dataLocaleData.[[styles]].[[<resolvedCalendar>]].
    5. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
  48. Else,
  49. If dateStyle is undefined and timeStyle is undefined, then
    1. Let needDefaults be true.
    2. If required is date or any, then
      1. For each property name prop of « "weekday", "year", "month", "day" », do
        1. Let value be formatOptionsexpandedOptions.[[<prop>]].
        2. If value is not undefined, set needDefaults to false.
    3. If required is time or any, then
      1. For each property name prop of « "dayPeriod", "hour", "minute", "second", "fractionalSecondDigits" », do
        1. Let value be formatOptionsexpandedOptions.[[<prop>]].
        2. If value is not undefined, set needDefaults to false.
    4. If needDefaults is true and defaults is either date or all, then
      1. For each property name prop of « "year", "month", "day" », do
        1. Set formatOptionsexpandedOptions.[[<prop>]] to "numeric".
    5. If needDefaults is true and defaults is either time or all, then
      1. For each property name prop of « "hour", "minute", "second" », do
        1. Set formatOptionsexpandedOptions.[[<prop>]] to "numeric".
    6. Let formats be dataLocaleData.[[formats]].[[<resolvedCalendar>]].
    7. If formatMatcher is "basic", then
      1. Let bestFormat be BasicFormatMatcher(formatOptions, formats).
    8. Else,
      1. Let bestFormat be BestFitFormatMatcher(formatOptions, formats).
  50. For each row in Table 7, except the header row, in table order, do
    1. Let prop be the name given in the Property column of the row.
    2. If bestFormat has a field [[<prop>]], then
      1. Let p be bestFormat.[[<prop>]].
      2. Set dateTimeFormat's internal slot whose name is the Internal Slot column of the row to p.
  51. If dateTimeFormat.[[Hour]] is undefined, then
    1. Set dateTimeFormat.[[HourCycle]] to undefined.
  52. If dateTimeFormat.[[HourCycle]] is "h11" or "h12", then
    1. Let pattern be bestFormat.[[pattern12]].
    2. Let rangePatterns be bestFormat.[[rangePatterns12]].
  53. Else,
    1. Let pattern be bestFormat.[[pattern]].
    2. Let rangePatterns be bestFormat.[[rangePatterns]].
  54. Let bestFormat be ? GetDateTimeFormatPattern(required, dateStyle, timeStyle, formatMatcher, expandedOptions, dataLocaleData, resolvedCalendar, hasExplicitFormatComponents).
  55. Set dateTimeFormat.[[Pattern]] to patternbestFormat.[[pattern]].
  56. Set dateTimeFormat.[[RangePatterns]] to rangePatternsbestFormat.[[rangePatterns]].
  57. For each row in Table 27, except the header row, in table order, do
    1. Let limitedOptions be a new Record.
    2. If dateStyle is undefined and timeStyle is undefined, then
      1. Set needDefaults to true.
      2. Let fields be the list of fields in the Supported fields column of the row.
      3. For each property name prop of formatOptions, do
        1. If prop is in fields, then
          1. Set needDefaults to false.
          2. Set limitedOptions.[[<prop>]] to formatOptions.[[<prop>]].
      4. If needDefaults is true, then
        1. Let defaultFields be the list of fields in the Default fields column of the row.
        2. If the Pattern column of the row is [[TemporalInstantPattern]], and toLocaleStringTimeZone is present, append [[timeZoneName]] to defaultFields.
        3. For each property name prop of defaultFields, do
          1. If prop is [[timeZoneName]], then
            1. Let defaultValue be "short".
          2. Else,
            1. Let defaultValue be "numeric".
          3. Set limitedOptions.[[<prop>]] to defaultValue.
    3. Set bestFormat to ! GetDateTimeFormatPattern(any, dateStyle, timeStyle, matcher, limitedOptions, dataLocaleData, resolvedCalendar, hasExplicitFormatComponents).
    4. If bestFormat does not have any fields that are in fields, then
      1. Set bestFormat to null.
    5. Set dateTimeFormat's internal slot whose name is the Pattern column of the row to bestFormat.
  58. Return dateTimeFormat.
Table 27: Supported fields for Temporal patterns
Pattern Supported fields Default fields
[[TemporalPlainDatePattern]] [[weekday]], [[era]], [[year]], [[month]], [[day]] [[year]], [[month]], [[day]]
[[TemporalPlainYearMonthPattern]] [[era]], [[year]], [[month]] [[year]], [[month]]
[[TemporalPlainMonthDayPattern]] [[month]], [[day]] [[month]], [[day]]
[[TemporalPlainTimePattern]] [[hour]], [[minute]], [[second]], [[dayPeriod]], [[fractionalSecondDigits]] [[hour]], [[minute]], [[second]]
[[TemporalPlainDateTimePattern]] [[weekday]], [[era]], [[year]], [[month]], [[day]], [[hour]], [[minute]], [[second]], [[dayPeriod]], [[fractionalSecondDigits]] [[year]], [[month]], [[day]], [[hour]], [[minute]], [[second]]
[[TemporalInstantPattern]] [[weekday]], [[era]], [[year]], [[month]], [[day]], [[hour]], [[minute]], [[second]], [[dayPeriod]], [[fractionalSecondDigits]], [[timeZoneName]] [[year]], [[month]], [[day]], [[hour]], [[minute]], [[second]]

15.6.2 DateTime Format Functions

A DateTime format function is an anonymous built-in function that has a [[DateTimeFormat]] internal slot.

When a DateTime format function F is called with optional argument date, the following steps are taken:

  1. Let dtf be F.[[DateTimeFormat]].
  2. Assert: Type(dtf) is Object and dtf has an [[InitializedDateTimeFormat]] internal slot.
  3. If date is not provided or is undefined, then
    1. Let x be ! Call(%Date.now%, undefined).
  4. Else,
    1. Let x be ? ToNumberToDateTimeFormattable(date).
  5. Return ? FormatDateTime(dtf, x).

The "length" property of a DateTime format function is 1𝔽.

15.6.3 FormatDateTimePattern ( dateTimeFormat, pattern, patternParts, x, epochNanoseconds, rangeFormatOptions )

The abstract operation FormatDateTimePattern takes arguments dateTimeFormat (an Intl.DateTimeFormat), pattern (a Record of the type contained by the %Intl.DateTimeFormat%.[[LocaleData]].[[<locale>]].[[formats]].[[<calendar>]] List as described in Internal slots), patternParts (a List of Records as returned by PartitionPattern), x (a Number), epochNanoseconds (a BigInt), and rangeFormatOptions (a range pattern Record as used in [[rangePattern]], or undefined) and returns either a normal completion containing a List of Records with fields [[Type]] (a String) and [[Value]] (a String), or a throw completion. It interprets x as a time value as specified in es2024, 21.4.1.1, and creates the corresponding parts for the epoch time epochNanoseconds according pattern and to the effective locale and the formatting options of dateTimeFormat and rangeFormatOptions. It performs the following steps when called:

  1. Let x be TimeClip(x).
  2. If x is NaN, throw a RangeError exception.
  3. Let locale be dateTimeFormat.[[Locale]].
  4. Let nfOptions be OrdinaryObjectCreate(null).
  5. Perform ! CreateDataPropertyOrThrow(nfOptions, "useGrouping", false).
  6. Let nf be ! Construct(%Intl.NumberFormat%, « locale, nfOptions »).
  7. Let nf2Options be OrdinaryObjectCreate(null).
  8. Perform ! CreateDataPropertyOrThrow(nf2Options, "minimumIntegerDigits", 2𝔽).
  9. Perform ! CreateDataPropertyOrThrow(nf2Options, "useGrouping", false).
  10. Let nf2 be ! Construct(%Intl.NumberFormat%, « locale, nf2Options »).
  11. Let fractionalSecondDigits be dateTimeFormat.[[FractionalSecondDigits]].
  12. If fractionalSecondDigits is not undefined, then
    1. Let nf3Options be OrdinaryObjectCreate(null).
    2. Perform ! CreateDataPropertyOrThrow(nf3Options, "minimumIntegerDigits", 𝔽(fractionalSecondDigits)).
    3. Perform ! CreateDataPropertyOrThrow(nf3Options, "useGrouping", false).
    4. Let nf3 be ! Construct(%Intl.NumberFormat%, « locale, nf3Options »).
  13. Let tm be ToLocalTime(((x) × 106)epochNanoseconds, dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
  14. Let result be a new empty List.
  15. For each Record { [[Type]], [[Value]] } patternPart of patternParts, do
    1. Let p be patternPart.[[Type]].
    2. If p is "literal", then
      1. Append the Record { [[Type]]: "literal", [[Value]]: patternPart.[[Value]] } to result.
    3. Else if p is equal to "fractionalSecondDigits", then
      1. Assert: fractionalSecondDigits is not undefined.
      2. Let v be tm.[[Millisecond]].
      3. Set v to floor(v × 10( fractionalSecondDigits - 3 )).
      4. Let fv be FormatNumeric(nf3, v).
      5. Append the Record { [[Type]]: "fractionalSecond", [[Value]]: fv } to result.
    4. Else if p is equal to "dayPeriod", then
      1. Let f be dateTimeFormat.[[DayPeriod]].
      2. Let fv be a String value representing the day period of tm in the form given by f; the String value depends upon the implementation and the effective locale of dateTimeFormat.
      3. Append the Record { [[Type]]: p, [[Value]]: fv } to result.
    5. Else if p is equal to "timeZoneName", then
      1. Let f be dateTimeFormat.[[TimeZoneName]].
      2. Let v be dateTimeFormat.[[TimeZone]].
      3. Let fv be a String value representing v in the form given by f; the String value depends upon the implementation and the effective locale of dateTimeFormat. The String value may also depend on the value of the [[InDST]] field of tm if f is "short", "long", "shortOffset", or "longOffset". If the implementation does not have such a localized representation of v, then use the String value of v itself.
      4. Append the Record { [[Type]]: p, [[Value]]: fv } to result.
    6. Else if p matches a Property column of the row in Table 7, then
      1. If rangeFormatOptions is not undefined, let f be the value of rangeFormatOptions's field whose name matches p.
      2. Else, let f be the value of dateTimeFormat's internal slotpattern's field whose name is the Internal Slot column of the matching rowp.
      3. Let v be the value of tm's field whose name is the Internal Slot column of the matching row.
      4. If p is "year" and v ≤ 0, set v to 1 - v.
      5. If p is "month", set v to v + 1.
      6. If p is "hour" and dateTimeFormat.[[HourCycle]]pattern.[[hourCycle]] is "h11" or "h12", then
        1. Set v to v modulo 12.
        2. If v is 0 and dateTimeFormat.[[HourCycle]]pattern.[[hourCycle]] is "h12", set v to 12.
      7. If p is "hour" and dateTimeFormat.[[HourCycle]]pattern.[[hourCycle]] is "h24", then
        1. If v is 0, set v to 24.
      8. If f is "numeric", then
        1. Let fv be FormatNumeric(nf, v).
      9. Else if f is "2-digit", then
        1. Let fv be FormatNumeric(nf2, v).
        2. If the "length" property of fv is greater than 2, set fv to the substring of fv containing the last two characters.
      10. Else if f is "narrow", "short", or "long", then
        1. Let fv be a String value representing v in the form given by f; the String value depends upon the implementation and the effective locale and calendar of dateTimeFormat. If p is "month" and rangeFormatOptions is undefined, then the String value may also depend on whether dateTimeFormat.[[Day]]pattern.[[day]] is undefined. If p is "month" and rangeFormatOptions is not undefined, then the String value may also depend on whether rangeFormatOptions.[[day]] is undefined. If p is "era" and rangeFormatOptions is undefined, then the String value may also depend on whether dateTimeFormat.[[Era]]pattern.[[era]] is undefined. If p is "era" and rangeFormatOptions is not undefined, then the String value may also depend on whether rangeFormatOptions.[[era]] is undefined. If the implementation does not have such a localized representation of v, then use ! ToString(v).
      11. Append the Record { [[Type]]: p, [[Value]]: fv } to result.
    7. Else if p is equal to "ampm", then
      1. Let v be tm.[[Hour]].
      2. If v is greater than 11, then
        1. Let fv be an implementation and locale dependent String value representing "post meridiem".
      3. Else,
        1. Let fv be an implementation and locale dependent String value representing "ante meridiem".
      4. Append the Record { [[Type]]: "dayPeriod", [[Value]]: fv } to result.
    8. Else if p is equal to "relatedYear", then
      1. Let v be tm.[[RelatedYear]].
      2. Let fv be FormatNumeric(nf, v).
      3. Append the Record { [[Type]]: "relatedYear", [[Value]]: fv } to result.
    9. Else if p is equal to "yearName", then
      1. Let v be tm.[[YearName]].
      2. Let fv be an implementation and locale dependent String value representing v.
      3. Append the Record { [[Type]]: "yearName", [[Value]]: fv } to result.
    10. Else,
      1. Let unknown be an implementation-, locale-, and numbering system-dependent String based on xepochNanoseconds and p.
      2. Append the Record { [[Type]]: "unknown", [[Value]]: unknown } to result.
  16. Return result.
Note
It is recommended that implementations use the locale and calendar dependent strings provided by the Common Locale Data Repository (available at https://cldr.unicode.org/), and use CLDR "abbreviated" strings for DateTimeFormat "short" strings, and CLDR "wide" strings for DateTimeFormat "long" strings.

15.6.4 PartitionDateTimePattern ( dateTimeFormat, x )

The abstract operation PartitionDateTimePattern takes arguments dateTimeFormat (an Intl.DateTimeFormat) and x (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing a List of Records with fields [[Type]] (a String) and [[Value]] (a String), or a throw completion. It interprets x as a time value as specified in es2024, 21.4.1.1an epoch time, and creates the corresponding parts according to the type of x, effective locale, and the formatting options of dateTimeFormat. It performs the following steps when called:

  1. Let xFormatRecord be ? HandleDateTimeValue(dateTimeFormat, x).
  2. Let patternParts be PartitionPattern(dateTimeFormat.[[Pattern]]xFormatRecord.[[pattern]]).
  3. Let result be ? FormatDateTimePattern(dateTimeFormat, xFormatRecord.[[pattern]], patternParts, xxFormatRecord.[[EpochNanoseconds]], undefined).
  4. Return result.

15.6.5 FormatDateTime ( dateTimeFormat, x )

The abstract operation FormatDateTime takes arguments dateTimeFormat (an Intl.DateTimeFormat) and x (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x).
  2. Let result be the empty String.
  3. For each Record { [[Type]], [[Value]] } part of parts, do
    1. Set result to the string-concatenation of result and part.[[Value]].
  4. Return result.

15.6.6 FormatDateTimeToParts ( dateTimeFormat, x )

The abstract operation FormatDateTimeToParts takes arguments dateTimeFormat (an Intl.DateTimeFormat) and x (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing an Array or a throw completion. It performs the following steps when called:

  1. Let parts be ? PartitionDateTimePattern(dateTimeFormat, x).
  2. Let result be ! ArrayCreate(0).
  3. Let n be 0.
  4. For each Record { [[Type]], [[Value]] } part of parts, do
    1. Let O be OrdinaryObjectCreate(%Object.prototype%).
    2. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
    3. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
    4. Perform ! CreateDataPropertyOrThrow(result, ! ToString(𝔽(n)), O).
    5. Increment n by 1.
  5. Return result.

15.6.7 PartitionDateTimeRangePattern ( dateTimeFormat, x, y )

The abstract operation PartitionDateTimeRangePattern takes arguments dateTimeFormat (an Intl.DateTimeFormat), x (a Number or an Object for which IsTemporalObject returns true), and y (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing a List of Records with fields [[Type]] (a String), [[Value]] (a String), and [[Source]] (a String), or a throw completion. It interprets x and y a time value as specified in es2024, 21.4.1.1epoch times, and creates the corresponding parts according to the types of x and y, effective locale, and the formatting options of dateTimeFormat. It performs the following steps when called:

  1. Let x be TimeClip(x).
  2. If x is NaN, throw a RangeError exception.
  3. Let y be TimeClip(y).
  4. If y is NaN, throw a RangeError exception.
  5. If IsTemporalObject(x) is true or IsTemporalObject(y) is true, then
    1. If SameTemporalType(x, y) is false, throw a TypeError exception.
  6. Let xFormatRecord be ? HandleDateTimeValue(dateTimeFormat, x).
  7. Let yFormatRecord be ? HandleDateTimeValue(dateTimeFormat, y).
  8. Let tm1 be ToLocalTime(((x) × 106)xFormatRecord.[[epochNanoseconds]], dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
  9. Let tm2 be ToLocalTime(((y) × 106)yFormatRecord.[[epochNanoseconds]], dateTimeFormat.[[Calendar]], dateTimeFormat.[[TimeZone]]).
  10. Let rangePatterns be dateTimeFormat.[[RangePatterns]]xFormatRecord.[[rangePatterns]].
  11. Assert: rangePatterns is equal to yFormatRecord.[[rangePatterns]].
  12. Let selectedRangePattern be undefined.
  13. Let relevantFieldsEqual be true.
  14. Let checkMoreFields be true.
  15. For each row of Table 5, except the header row, in table order, do
    1. Let fieldName be the name given in the Range Pattern Field column of the row.
    2. If rangePatterns has a field [[<fieldName>]], let rangePattern be rangePatterns.[[<fieldName>]]; else let rangePattern be undefined.
    3. If selectedRangePattern is not undefined and rangePattern is undefined, then
      1. NOTE: Because there is no range pattern for differences at or below this field, no further checks will be performed.
      2. Set checkMoreFields to false.
    4. If relevantFieldsEqual is true and checkMoreFields is true, then
      1. Set selectedRangePattern to rangePattern.
      2. If fieldName is equal to [[AmPm]], then
        1. If tm1.[[Hour]] is less than 12, let v1 be "am"; else let v1 be "pm".
        2. If tm2.[[Hour]] is less than 12, let v2 be "am"; else let v2 be "pm".
      3. Else if fieldName is equal to [[DayPeriod]], then
        1. Let v1 be a String value representing the day period of tm1; the String value depends upon the implementation and the effective locale of dateTimeFormat.
        2. Let v2 be a String value representing the day period of tm2; the String value depends upon the implementation and the effective locale of dateTimeFormat.
      4. Else if fieldName is equal to [[FractionalSecondDigits]], then
        1. Let fractionalSecondDigits be dateTimeFormat.[[FractionalSecondDigits]].
        2. If fractionalSecondDigits is undefined, then
          1. Set fractionalSecondDigits to 3.
        3. Let exp be fractionalSecondDigits - 3.
        4. Let v1 be floor(tm1.[[Millisecond]] × 10exp).
        5. Let v2 be floor(tm2.[[Millisecond]] × 10exp).
      5. Else,
        1. Let v1 be tm1.[[<fieldName>]].
        2. Let v2 be tm2.[[<fieldName>]].
      6. If v1 is not equal to v2, then
        1. Set relevantFieldsEqual to false.
  16. If relevantFieldsEqual is true, then
    1. Let collapsedResult be a new empty List.
    2. Let pattern be dateTimeFormat.[[Pattern]]xFormatRecord.[[pattern]].
    3. Let patternParts be PartitionPattern(pattern).
    4. Let resultParts be ! FormatDateTimePattern(dateTimeFormat, pattern, patternParts, xxFormatRecord.[[epochNanoseconds]], undefined).
    5. For each Record { [[Type]], [[Value]] } r of resultParts, do
      1. Append the Record { [[Type]]: r.[[Type]], [[Value]]: r.[[Value]], [[Source]]: "shared" } to collapsedResult.
    6. Return collapsedResult.
  17. Let rangeResult be a new empty List.
  18. If selectedRangePattern is undefined, then
    1. Set selectedRangePattern to rangePatterns.[[Default]].
  19. For each Record { [[Pattern]], [[Source]] } rangePatternPart of selectedRangePattern.[[PatternParts]], do
    1. Let pattern be rangePatternPart.[[Pattern]].
    2. Let source be rangePatternPart.[[Source]].
    3. If source is "startRange" or "shared", then
      1. Let z be xxFormatRecord.[[epochNanoseconds]].
    4. Else,
      1. Let z be yyFormatRecord.[[epochNanoseconds]].
    5. Let patternParts be PartitionPattern(pattern).
    6. Let resultParts be ! FormatDateTimePattern(dateTimeFormat, pattern, patternParts, z, selectedRangePattern).
    7. For each Record { [[Type]], [[Value]] } r of resultParts, do
      1. Append the Record { [[Type]]: r.[[Type]], [[Value]]: r.[[Value]], [[Source]]: source } to rangeResult.
  20. Return rangeResult.

15.6.8 FormatDateTimeRange ( dateTimeFormat, x, y )

The abstract operation FormatDateTimeRange takes arguments dateTimeFormat (an Intl.DateTimeFormat), x (a Number or an Object for which IsTemporalObject returns true), and y (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y).
  2. Let result be the empty String.
  3. For each Record { [[Type]], [[Value]], [[Source]] } part of parts, do
    1. Set result to the string-concatenation of result and part.[[Value]].
  4. Return result.

15.6.9 FormatDateTimeRangeToParts ( dateTimeFormat, x, y )

The abstract operation FormatDateTimeRangeToParts takes arguments dateTimeFormat (an Intl.DateTimeFormat), x (a Number or an Object for which IsTemporalObject returns true), and y (a Number or an Object for which IsTemporalObject returns true) and returns either a normal completion containing an Array or a throw completion. It performs the following steps when called:

  1. Let parts be ? PartitionDateTimeRangePattern(dateTimeFormat, x, y).
  2. Let result be ! ArrayCreate(0).
  3. Let n be 0.
  4. For each Record { [[Type]], [[Value]], [[Source]] } part of parts, do
    1. Let O be OrdinaryObjectCreate(%Object.prototype%).
    2. Perform ! CreateDataPropertyOrThrow(O, "type", part.[[Type]]).
    3. Perform ! CreateDataPropertyOrThrow(O, "value", part.[[Value]]).
    4. Perform ! CreateDataPropertyOrThrow(O, "source", part.[[Source]]).
    5. Perform ! CreateDataPropertyOrThrow(result, ! ToString(𝔽(n)), O).
    6. Increment n by 1.
  5. Return result.

15.6.10 ToDateTimeFormattable ( value )

The abstract operation ToDateTimeFormattable takes argument value (an ECMAScript language value, but not undefined) and returns either a normal completion containing either a Number or an Object for which IsTemporalObject returns true, or a throw completion. It converts value to a value that can be formatted by an %Intl.DateTimeFormat% object. It performs the following steps when called:

  1. If IsTemporalObject(value) is true, return value.
  2. Return ? ToNumber(value).

15.6.11 IsTemporalObject ( value )

The abstract operation IsTemporalObject takes argument value (an ECMAScript language value) and returns a Boolean. It performs the following steps when called:

  1. If Type(value) is not Object, then
    1. Return false.
  2. If value does not have an [[InitializedTemporalDate]], [[InitializedTemporalTime]], [[InitializedTemporalDateTime]], [[InitializedTemporalZonedDateTime]], [[InitializedTemporalYearMonth]], [[InitializedTemporalMonthDay]], or [[InitializedTemporalInstant]] internal slot, then
    1. Return false.
  3. Return true.

15.6.12 SameTemporalType ( x, y )

The abstract operation SameTemporalType takes arguments x (an ECMAScript language value) and y (an ECMAScript language value) and returns a Boolean. It determines whether x and y are both instances of the same Temporal type. It performs the following steps when called:

  1. If either of IsTemporalObject(x) or IsTemporalObject(y) is false, return false.
  2. If x has an [[InitializedTemporalDate]] internal slot and y does not, return false.
  3. If x has an [[InitializedTemporalTime]] internal slot and y does not, return false.
  4. If x has an [[InitializedTemporalDateTime]] internal slot and y does not, return false.
  5. If x has an [[InitializedTemporalZonedDateTime]] internal slot and y does not, return false.
  6. If x has an [[InitializedTemporalYearMonth]] internal slot and y does not, return false.
  7. If x has an [[InitializedTemporalMonthDay]] internal slot and y does not, return false.
  8. If x has an [[InitializedTemporalInstant]] internal slot and y does not, return false.
  9. Return true.

15.6.13 GetDateTimeFormatPattern ( required, dateStyle, timeStyle, formatMatcher, formatOptions, dataLocaleData, resolvedCalendar, hasExplicitFormatComponents )

The abstract operation GetDateTimeFormatPattern takes arguments required (date, time, or any), dateStyle ("full", "long", "medium", "short", or undefined), timeStyle ("full", "long", "medium", "short", or undefined), formatMatcher ("basic" or "best fit"), formatOptions (a Record), dataLocaleData (a Record of the same type as %Intl.DateTimeFormat%.[[LocaleData]] as described in Internal slots), resolvedCalendar (a String), and hasExplicitFormatComponents (a Boolean) and returns either a normal completion containing a Record of the type contained by the List %Intl.DateTimeFormat%.[[LocaleData]].[[<locale>]].[[formats]].[[<calendar>]] as described in Internal slots, or a throw completion. It performs the following steps when called:

  1. If dateStyle is not undefined or timeStyle is not undefined, then
    1. If hasExplicitFormatComponents is true, then
      1. Throw a TypeError exception.
    2. If required is date and timeStyle is not undefined, then
      1. Throw a TypeError exception.
    3. If required is time and dateStyle is not undefined, then
      1. Throw a TypeError exception.
    4. Let styles be dataLocaleData.[[styles]].[[<resolvedCalendar>]].
    5. Let bestFormat be DateTimeStyleFormat(dateStyle, timeStyle, styles).
  2. Else,
    1. Let formats be dataLocaleData.[[formats]].[[<resolvedCalendar>]].
    2. If formatMatcher is "basic", then
      1. Let bestFormat be BasicFormatMatcher(formatOptions, formats).
    3. Else,
      1. Let bestFormat be BestFitFormatMatcher(formatOptions, formats).
  3. If bestFormat.[[Hour]] is undefined, then
    1. Set bestFormat.[[HourCycle]] to undefined.
  4. If bestFormat.[[HourCycle]] is "h11" or "h12", then
    1. Set bestFormat.[[pattern]] to bestFormat.[[pattern12]].
    2. Set bestFormat.[[rangePatterns]] to bestFormat.[[rangePatterns12]].
  5. Remove the [[pattern12]] field from bestFormat.
  6. Remove the [[rangePatterns12]] field from bestFormat.
  7. Return bestFormat.

15.6.14 Value Format Records

Each Value Format Record has the fields defined in Table 28.

Table 28: Record returned by HandleDateTimeValue
Field Name Value Type
[[pattern]] a String value as described in Internal slots
[[rangePatterns]] a Record as described in Internal slots
[[epochNanoseconds]] a BigInt

15.6.15 HandleDateTimeTemporalDate ( dateTimeFormat, temporalDate )

The abstract operation HandleDateTimeTemporalDate takes arguments dateTimeFormat (an Intl.DateTimeFormat) and temporalDate (a Temporal.PlainDate) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalPlainDatePattern]].
  2. Let calendar be ? ToTemporalCalendarIdentifier(temporalDate.[[Calendar]]).
  3. If calendar is not dateTimeFormat.[[Calendar]] or "iso8601", throw a RangeError exception.
  4. Let plainDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], 12, 0, 0, 0, 0, 0, dateTimeFormat.[[Calendar]]).
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(dateTimeFormat.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  6. Let instant be ? GetInstantFor(timeZoneRec, plainDateTime, "compatible").
  7. If pattern is null, throw a TypeError exception.
  8. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.16 HandleDateTimeTemporalYearMonth ( dateTimeFormat, temporalYearMonth )

The abstract operation HandleDateTimeTemporalYearMonth takes arguments dateTimeFormat (an Intl.DateTimeFormat) and temporalYearMonth (a Temporal.PlainYearMonth) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalPlainYearMonthPattern]].
  2. Let calendar be ? ToTemporalCalendarIdentifier(temporalYearMonth.[[Calendar]]).
  3. If calendar is not equal to dateTimeFormat.[[Calendar]], then
    1. Throw a RangeError exception.
  4. Let plainDateTime be ? CreateTemporalDateTime(temporalYearMonth.[[ISOYear]], temporalYearMonth.[[ISOMonth]], temporalYearMonth.[[ISODay]], 12, 0, 0, 0, 0, 0, dateTimeFormat.[[Calendar]]).
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(dateTimeFormat.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  6. Let instant be ? GetInstantFor(timeZoneRec, plainDateTime, "compatible").
  7. If pattern is null, throw a TypeError exception.
  8. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.17 HandleDateTimeTemporalMonthDay ( dateTimeFormat, temporalMonthDay )

The abstract operation HandleDateTimeTemporalMonthDay takes arguments dateTimeFormat (an Intl.DateTimeFormat) and temporalMonthDay (a Temporal.PlainMonthDay) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalPlainMonthDayPattern]].
  2. Let calendar be ? ToTemporalCalendarIdentifier(temporalMonthDay.[[Calendar]]).
  3. If calendar is not equal to dateTimeFormat.[[Calendar]], then
    1. Throw a RangeError exception.
  4. Let plainDateTime be ? CreateTemporalDateTime(temporalMonthDay.[[ISOYear]], temporalMonthDay.[[ISOMonth]], temporalMonthDay.[[ISODay]], 12, 0, 0, 0, 0, 0, dateTimeFormat.[[Calendar]]).
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(dateTimeFormat.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  6. Let instant be ? GetInstantFor(timeZoneRec, plainDateTime, "compatible").
  7. If pattern is null, throw a TypeError exception.
  8. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.18 HandleDateTimeTemporalTime ( dateTimeFormat, temporalTime )

The abstract operation HandleDateTimeTemporalTime takes arguments dateTimeFormat (an Intl.DateTimeFormat) and temporalTime (a Temporal.PlainTime) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalPlainTimePattern]].
  2. Let plainDateTime be ? CreateTemporalDateTime(1970, 1, 1, temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], "iso8601").
  3. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(dateTimeFormat.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  4. Let instant be ? GetInstantFor(timeZoneRec, plainDateTime, "compatible").
  5. If pattern is null, throw a TypeError exception.
  6. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.19 HandleDateTimeTemporalDateTime ( dateTimeFormat, dateTime )

The abstract operation HandleDateTimeTemporalDateTime takes arguments dateTimeFormat (an Intl.DateTimeFormat) and dateTime (a Temporal.PlainDateTime) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalPlainDateTimePattern]].
  2. Let calendar be ? ToTemporalCalendarIdentifier(dateTime.[[Calendar]]).
  3. If calendar is not "iso8601" and not equal to dateTimeFormat.[[Calendar]], then
    1. Throw a RangeError exception.
  4. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(dateTimeFormat.[[TimeZone]], « get-offset-nanoseconds-for, get-possible-instants-for »).
  5. Let instant be ? GetInstantFor(timeZoneRec, dateTime, "compatible").
  6. If pattern is null, throw a TypeError exception.
  7. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.20 HandleDateTimeTemporalInstant ( dateTimeFormat, instant )

The abstract operation HandleDateTimeTemporalInstant takes arguments dateTimeFormat (an Intl.DateTimeFormat) and instant (a Temporal.Instant) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[TemporalInstantPattern]].
  2. If pattern is null, throw a TypeError exception.
  3. Return the Record { [[pattern]]: pattern.[[pattern]], [[rangePatterns]]: pattern.[[rangePatterns]], [[epochNanoseconds]]: instant.[[Nanoseconds]]  }.

15.6.21 HandleDateTimeOthers ( dateTimeFormat, x )

The abstract operation HandleDateTimeOthers takes arguments dateTimeFormat (an Intl.DateTimeFormat) and x (a Number) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. Let pattern be dateTimeFormat.[[Pattern]].
  2. Let rangePatterns be dateTimeFormat.[[RangePatterns]].
  3. Set x to TimeClip(x).
  4. If x is NaN, throw a RangeError exception.
  5. Let epochNanoseconds be (x) × (106).
  6. Return the Record { [[pattern]]: pattern, [[rangePatterns]]: rangePatterns, [[epochNanoseconds]]: epochNanoseconds  }.

15.6.22 HandleDateTimeValue ( dateTimeFormat, x )

The abstract operation HandleDateTimeValue takes arguments dateTimeFormat (an Intl.DateTimeFormat) and x (a Number, or an Object for which IsTemporalObject returns true) and returns either a normal completion containing a Value Format Record, or a throw completion. It performs the following steps when called:

  1. If x is an Object, then
    1. If x has an [[InitializedTemporalDate]] internal slot, then
      1. Return ? HandleDateTimeTemporalDate(dateTimeFormat, x).
    2. If x has an [[InitializedTemporalYearMonth]] internal slot, then
      1. Return ? HandleDateTimeTemporalYearMonth(dateTimeFormat, x).
    3. If x has an [[InitializedTemporalMonthDay]] internal slot, then
      1. Return ? HandleDateTimeTemporalMonthDay(dateTimeFormat, x).
    4. If x has an [[InitializedTemporalTime]] internal slot, then
      1. Return ? HandleDateTimeTemporalTime(dateTimeFormat, x).
    5. If x has an [[InitializedTemporalDateTime]] internal slot, then
      1. Return ? HandleDateTimeTemporalDateTime(dateTimeFormat, x).
    6. If x has an [[InitializedTemporalInstant]] internal slot, then
      1. Return ? HandleDateTimeTemporalInstant(dateTimeFormat, x).
    7. Assert: x has an [[InitializedTemporalZonedDateTime]] internal slot.
    8. Throw a TypeError exception.
  2. Return ? HandleDateTimeOthers(dateTimeFormat, x).

15.6.23 ToLocalTime ( epochNs, calendar, timeZoneIdentifier )

The implementation-defined abstract operation ToLocalTime takes arguments epochNs (a BigInt), calendar (a String), and timeZoneIdentifier (a String) and returns a ToLocalTime Record. It performs the following steps when called:

  1. If IsTimeZoneOffsetString(timeZoneIdentifier) is true, then
    1. Let offsetNs be ParseTimeZoneOffsetString(timeZoneIdentifier).
  2. Else,
    1. Assert: IsValidTimeZoneName(timeZoneIdentifier) is true.
    2. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(timeZoneIdentifier, epochNs).
  3. Let tz be (epochNs) + offsetNs.
  4. If calendar is "gregory", then
    1. Return a ToLocalTime Record with fields calculated from tz according to Table 8.
  5. Else,
    1. Return a ToLocalTime Record with the fields calculated from tz for the given calendar. The calculations should use best available information about the specified calendar. Given the same values of epochNs, calendar, and timeZoneIdentifier, the result must be the same for the lifetime of the surrounding agent.
Note 1
A conforming implementation must recognize "UTC" and all Zone and Link names from the IANA Time Zone Database (and only such names), and use best available current and historical information about their offsets from UTC and their daylight saving time rules in calculations.
Note 2
Time zone information is subject to change, and host environments may update their time zone database at any time. At a minimum, implementations must ensure that the time zone information for each particular value of timeZone individually remains constant starting from the time it is first accessed, for the lifetime of the surrounding agent. Furthermore, it is recommended that the time zone information for all values of timeZone as a whole (i.e. the time zone database) remains the same for the lifetime of the surrounding agent.

15.7 Properties of the Intl.DateTimeFormat Prototype Object

15.7.1 Intl.DateTimeFormat.prototype.formatToParts ( date )

When the formatToParts method is called with an argument date, the following steps are taken:

  1. Let dtf be the this value.
  2. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
  3. If date is undefined, then
    1. Let x be ! Call(%Date.now%, undefined).
  4. Else,
    1. Let x be ? ToNumberToDateTimeFormattable(date).
  5. Return ? FormatDateTimeToParts(dtf, x).

15.7.2 Intl.DateTimeFormat.prototype.formatRange ( startDate, endDate )

When the formatRange method is called with an arguments startDate and endDate, the following steps are taken:

  1. Let dtf be this value.
  2. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
  3. If startDate is undefined or endDate is undefined, throw a TypeError exception.
  4. Let x be ? ToNumberToDateTimeFormattable(startDate).
  5. Let y be ? ToNumberToDateTimeFormattable(endDate).
  6. Return ? FormatDateTimeRange(dtf, x, y).

15.7.3 Intl.DateTimeFormat.prototype.formatRangeToParts ( startDate, endDate )

When the formatRangeToParts method is called with arguments startDate and endDate, the following steps are taken:

  1. Let dtf be this value.
  2. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
  3. If startDate is undefined or endDate is undefined, throw a TypeError exception.
  4. Let x be ? ToNumberToDateTimeFormattable(startDate).
  5. Let y be ? ToNumberToDateTimeFormattable(endDate).
  6. Return ? FormatDateTimeRangeToParts(dtf, x, y).

15.7.4 Intl.DateTimeFormat.prototype.resolvedOptions ( )

This function provides access to the locale and formatting options computed during initialization of the object.

  1. Let dtf be the this value.
  2. If the implementation supports the normative optional constructor mode of Note undefined, then
    1. Set dtf to ? UnwrapDateTimeFormat(dtf).
  3. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
  4. Let options be OrdinaryObjectCreate(%Object.prototype%).
  5. For each row of Table 29, except the header row, in table order, do
    1. If the Location value of the current row is object, then
      1. Let v be the value of dtf's internal slot whose name is the Internal Slot value of the current row.
    2. Else,
      1. Assert: The Location value of the current row is pattern.
      2. Let v be the value of dtf.[[Pattern]]'s internal slot whose name is the Internal Slot value of the current row.
    3. Let p be the Property value of the current row.
    4. If the Internal Slot value of the current row is an Internal Slot value in Table 7, then
      1. If dtf.[[DateStyle]] is not undefined or dtf.[[TimeStyle]] is not undefined, then
        1. Set v to undefined.
    5. If v is not undefined, then
      1. If there is a Conversion value in the current row, then
        1. Let conversion be the Conversion value of the current row.
        2. If conversion is hour12, then
          1. If v is "h11" or "h12", set v to true. Otherwise, set v to false.
        3. Else,
          1. Assert: conversion is number.
          2. Set v to 𝔽(v).
      2. Perform ! CreateDataPropertyOrThrow(options, p, v).
  6. Return options.
Table 29: Resolved Options of DateTimeFormat Instances
Internal Slot Property Conversion Location
[[Locale]] "locale" object
[[Calendar]] "calendar" object
[[NumberingSystem]] "numberingSystem" object
[[TimeZone]] "timeZone" object
[[HourCycle]][[hourCycle]] "hourCycle" pattern
[[HourCycle]][[hourCycle]] "hour12" hour12 pattern
[[Weekday]][[weekday]] "weekday" pattern
[[Era]][[era]] "era" pattern
[[Year]][[year]] "year" pattern
[[Month]][[month]] "month" pattern
[[Day]][[day]] "day" pattern
[[DayPeriod]][[dayPeriod]] "dayPeriod" pattern
[[Hour]][[hour]] "hour" pattern
[[Minute]][[minute]] "minute" pattern
[[Second]][[second]] "second" pattern
[[FractionalSecondDigits]][[fractionalSecondDigits]] "fractionalSecondDigits" number pattern
[[TimeZoneName]][[timeZoneName]] "timeZoneName" pattern
[[DateStyle]] "dateStyle" object
[[TimeStyle]] "timeStyle" object

For web compatibility reasons, if the property "hourCycle" is set, the "hour12" property should be set to true when "hourCycle" is "h11" or "h12", or to false when "hourCycle" is "h23" or "h24".

Note 1
In this version of the API, the "timeZone" property will be the identifier of the host environment's time zone if no "timeZone" property was provided in the options object provided to the Intl.DateTimeFormat constructor. The first edition left the "timeZone" property undefined in this case.
Note 2
For compatibility with versions prior to the fifth edition, the "hour12" property is set in addition to the "hourCycle" property.

15.8 Properties of Intl.DateTimeFormat Instances

Intl.DateTimeFormat instances are ordinary objects that inherit properties from %Intl.DateTimeFormat.prototype%.

Intl.DateTimeFormat instances have an [[InitializedDateTimeFormat]] internal slot.

Intl.DateTimeFormat instances also have several internal slots that are computed by the constructor:

  • [[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
  • [[Calendar]] is a String value representing the Unicode Calendar Identifier used for formatting.
  • [[NumberingSystem]] is a String value representing the Unicode Number System Identifier used for formatting.
  • [[TimeZone]] is a String value used for formatting that is either a time zone identifier from the IANA Time Zone Database or a UTC offset in ISO 8601 extended format.
  • [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[DayPeriod]], [[Hour]], [[Minute]], [[Second]], [[TimeZoneName]] are each either undefined, indicating that the component is not used for formatting, or one of the String values given in Table 7, indicating how the component should be presented in the formatted output.
  • [[FractionalSecondDigits]] is either undefined or a positive, non-zero integer indicating the fraction digits to be used for fractional seconds. Numbers will be rounded or padded with trailing zeroes if necessary.
  • [[HourCycle]] is a String value indicating whether the 12-hour format ("h11", "h12") or the 24-hour format ("h23", "h24") should be used. "h11" and "h23" start with hour 0 and go up to 11 and 23 respectively. "h12" and "h24" start with hour 1 and go up to 12 and 24. [[HourCycle]] is only used when [[Hour]] is not undefined.
  • [[DateStyle]], [[TimeStyle]] are each either undefined, or a String value with values "full", "long", "medium", or "short".
  • [[Pattern]] is a String value as described in Internal slots.
  • [[RangePatterns]] is a Record as described in Internal slots.
  • [[TemporalPlainDatePattern]], [[TemporalPlainYearMonthPattern]], [[TemporalPlainMonthDayPattern]], [[TemporalPlainTimePattern]], [[TemporalPlainDateTimePattern]], and [[TemporalInstantPattern]] are records containing at least a [[pattern]] field as described in Internal slots.

Finally, Intl.DateTimeFormat instances have a [[BoundFormat]] internal slot that caches the function returned by the format accessor (get Intl.DateTimeFormat.prototype.format).

15.9 Locale Sensitive Functions of the ECMAScript Language Specification

15.9.1 Abstract Operations for Temporal.Calendar Objects

15.9.1.1 CalendarEra ( calendar, dateLike )

The abstract operation CalendarEra takes arguments calendar (an Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing either a String or undefined, or an abrupt completion. It calls the given calendar's era() method and validates the result. It performs the following steps when called:

  1. Let result be ? Invoke(calendar, "era", « dateLike »).
  2. If result is undefined, return undefined.
  3. If Type(result) is not String, throw a TypeError exception.
  4. Return result.

15.9.1.2 CalendarEraYear ( calendar, dateLike )

The abstract operation CalendarEraYear takes arguments calendar (an Object) and dateLike (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth) and returns either a normal completion containing either an integer or undefined, or an abrupt completion. It calls the given calendar's eraYear() method and validates the result. It performs the following steps when called:

  1. Let result be ? Invoke(calendar, "eraYear", « dateLike »).
  2. If result is undefined, return undefined.
  3. If Type(result) is not Number, throw a TypeError exception.
  4. If IsIntegralNumber(result) is false, throw a RangeError exception.
  5. Return (result).

15.9.1.3 CalendarDateToISO ( calendar, fields, overflow )

The implementation-defined abstract operation CalendarDateToISO takes arguments calendar (a String), fields (an ordinary Object for which the value of the [[Prototype]] internal slot is null and every property is a data property), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record, or an abrupt completion. It performs implementation-defined processing to convert fields, which represents a date or year and month or month and day in the built-in calendar identified by calendar, to a corresponding representative date in the ISO 8601 calendar, subject to processing specified by overflow. For "reject", values that do not form a valid date cause an exception to be thrown, as described below. For "constrain", values that do not form a valid date are clamped to the correct range. It then returns an ISO Date Record with the corresponding ISO 8601 date.

Clamping an invalid date to the correct range when overflow is "constrain" is a behaviour specific to each built-in calendar, but all built-in calendars follow this guideline:

  • Pick the closest day in the same month. If there are two equally-close dates in that month, pick the later one.
  • If the month is a leap month that doesn't exist in the year, pick another date according to the cultural conventions of that calendar's users. Usually this will result in the same day in the month before or after where that month would normally fall in a leap year.
  • Otherwise, pick the closest date that is still in the same year. If there are two equally-close dates in that year, pick the later one.
  • If the entire year doesn't exist, pick the closest date in a different year. If there are two equally-close dates, pick the later one.

Like RegulateISODate, the operation throws a RangeError exception if the date described by fields is outside the range allowed by ISODateTimeWithinLimits, or if overflow is "reject" and the date described by fields does not exist.

15.9.1.4 CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow )

The abstract operation CalendarMonthDayToISOReferenceDate takes arguments calendar (a String), fields (an ordinary Object for which the value of the [[Prototype]] internal slot is null and every property is a data property), and overflow ("constrain" or "reject") and returns either a normal completion containing a Record with fields [[ISOMonth]], [[ISODay]], and [[ReferenceISOYear]], or an abrupt completion. It performs implementation-defined processing to convert fields, which represents a calendar date without a year (i.e., month code and day pair, or equivalent) in the built-in calendar identified by calendar, to a corresponding reference date in the ISO 8601 calendar as described below, subject to processing specified by overflow. For "reject", values that do not form a valid date cause an exception to be thrown. For "constrain", values that do not form a valid date are clamped to the correct range as in CalendarDateToISO. It then returns a Record representing the reference ISO 8601 date.

The fields of the returned Record represent a reference date in the ISO 8601 calendar that, when converted to the built-in calendar identified by calendar, corresponds to the month code and day of fields in an arbitrary but deterministically chosen reference year. The reference date is the latest ISO 8601 date corresponding to the calendar date, that is also earlier than or equal to the ISO 8601 date December 31, 1972. If that calendar date never occurs on or before the ISO 8601 date December 31, 1972, then the reference date is the earliest ISO 8601 date corresponding to that calendar date. The reference year is almost always 1972 (the first ISO 8601 leap year after the epoch), with exceptions for calendars where some dates (e.g. leap days or days in leap months) didn't occur during that ISO 8601 year. For example, Hebrew calendar leap month Adar I was a part of calendar years 5730 and 5733 (respectively overlapping ISO 8601 February/March 1970 and February/March 1973), but did not occur between them.

Like RegulateISODate, the operation throws a RangeError exception if overflow is "reject" and the month and day described by fields does not exist. For example, when calendar is "gregory" and overflow is "reject", fields values of { monthCode: "M01", day: "32" } and { "year": 2001, "month": 2, "day": 29 } would both cause a RangeError to be thrown. In the latter case, even though February 29 is a date in leap years of the Gregorian calendar, 2001 was not a leap year and a month code cannot be determined from the nonexistent date 2001-02-29 with the specified month index.

15.9.1.5 CalendarDateAddition ( calendar, date, duration, overflow )

The implementation-defined abstract operation CalendarDateAddition takes arguments calendar (a String), date (a Temporal.PlainDate), duration (a Date Duration Record), and overflow (a String) and returns either a normal completion containing an ISO Date Record, or an abrupt completion. It performs implementation-defined processing to add duration to date in the context of the calendar represented by calendar and returns the corresponding day, month and year of the result in the ISO 8601 calendar values as an ISO Date Record. It may throw a RangeError exception if overflow is "reject" and the resulting month or day would need to be clamped in order to form a valid date in calendar, or if the date resulting from the addition is outside the range allowed by ISODateTimeWithinLimits.

15.9.1.6 CalendarDateDifference ( calendar, one, two, largestUnit )

The abstract operation CalendarDateDifference takes arguments calendar (a String), one (a Temporal.PlainDate), two (a Temporal.PlainDate), and largestUnit (a String). It performs implementation-defined processing to find the difference between the two dates one and two in the context of the calendar represented by calendar and returns the corresponding years, months, weeks and days as a Date Duration Record.

15.9.1.7 CalendarDateEra ( calendar, date )

The abstract operation CalendarDateEra takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth). It performs implementation-defined processing to find the era for the date corresponding to date in the context of the calendar represented by calendar and returns a lowercase String value representing that era, or undefined for calendars that do not have eras.

15.9.1.8 CalendarDateEraYear ( calendar, date )

The abstract operation CalendarDateEraYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth). It performs implementation-defined processing to find the era for the date corresponding to date in the context of the calendar represented by calendar and returns an integer representing the ordinal position of the year of date in that era, or undefined for calendars that do not have eras.

Note
Era years are 1-indexed for many calendars, but not all (e.g., the eras of the Burmese calendar each start with a year 0). Years can also advance opposite the flow of time (as for BCE years in the Gregorian calendar).

15.9.1.9 CalendarDateYear ( calendar, date )

The abstract operation CalendarDateYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth). It performs implementation-defined processing to find the year for the date corresponding to date in the context of the calendar represented by calendar and returns it. The value should be a signed integer relative to the first day of a calendar-specific "epoch year".

Note
The year is relative to the first day of the calendar's epoch year, so if the epoch era starts in the middle of the year, the year will be the same value before and after the start date of the era.

15.9.1.10 CalendarDateMonth ( calendar, date )

The abstract operation CalendarDateMonth takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainYearMonth, or Temporal.PlainMonthDay). It performs implementation-defined processing to find the month for the date corresponding to date in the context of the calendar represented by calendar and returns an integer representing the 1-based ordinal position of that month in the corresponding year of the calendar.

Note
When the number of months in a year of the identified calendar is variable, a different value can be returned for dates that are part of the same month in different years. For example, in the Hebrew calendar, 1 Nisan 5781 is associated with value 7 while 1 Nisan 5782 is associated with value 8 because 5782 is a leap year and Nisan follows the insertion of Adar I.

15.9.1.11 CalendarDateMonthCode ( calendar, date )

The abstract operation CalendarDateMonthCode takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainYearMonth, or Temporal.PlainMonthDay). It performs implementation-defined processing to find the month for the date corresponding to date in the context of the calendar represented by calendar and returns its month code. The month code for a month that is not a leap month and whose 1-based ordinal position in a common year of the calendar (i.e., a year that is not a leap year) is n should be the string-concatenation of "M" and ToZeroPaddedDecimalString(n, 2), and the month code for a month that is a leap month inserted after a month whose 1-based ordinal position in a common year of the calendar is p should be the string-concatenation of "M", ToZeroPaddedDecimalString(p, 2), and "L".

Note
For example, in the Hebrew calendar, the month code of Adar (and Adar II, in leap years) is "M06" and the month code of Adar I (the leap month inserted before Adar II) is "M05L". In a calendar with a leap month at the start of some years, the month code of that month would be "M00L".

15.9.1.12 CalendarDateDay ( calendar, date )

The abstract operation CalendarDateDay takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainMonthDay). It performs implementation-defined processing to find the day of the month for the date corresponding to date in the context of the calendar represented by calendar and returns an integer representing the 1-based ordinal position of that day in the corresponding month.

15.9.1.13 CalendarDateDayOfWeek ( calendar, date )

The abstract operation CalendarDateDayOfWeek takes arguments calendar (a String) and date (a Temporal.PlainDateTime or Temporal.PlainDate). It takes a date-like object date and returns the day of the week in the calendar represented by calendar. The return value should be 1-based, where 1 is the day corresponding to Monday in the given calendar.

15.9.1.14 CalendarDateDayOfYear ( calendar, date )

The abstract operation CalendarDateDayOfYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime or Temporal.PlainDate). It takes a date-like object date and returns the day of the year in the calendar represented by calendar. The return value should be 1-based.

15.9.1.15 CalendarDateWeekOfYear ( calendar, date )

The abstract operation CalendarDateWeekOfYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime or Temporal.PlainDate) and returns a Year-Week Record. It takes a date-like object date and calculates the calendar week of year, and the corresponding week calendar year, in the calendar represented by calendar.

The value in the [[Week]] field should be 1-based.

The value in the [[Year]] field is relative to the first day of a calendar-specific "epoch year", as in CalendarDateYear, not relative to an era as in CalendarDateEraYear.

Usually the [[Year]] field will contain the same value given by CalendarDateYear, but may contain the previous or next year if the week number in the [[Week]] field overlaps two different years. See also ToISOWeekOfYear.

It returns undefined in [[Week]] and [[Year]] field for calendars that do not have a well-defined week calendar system.

Editor's Note

More details about this function will be specified in the Intl era and monthCode proposal.

15.9.1.16 CalendarDateDaysInWeek ( calendar, date )

The abstract operation CalendarDateDaysInWeek takes arguments calendar (a String) and date (a Temporal.PlainDateTime or Temporal.PlainDate). It takes a date-like object date and returns the number of days in the given week in the calendar represented by calendar.

15.9.1.17 CalendarDateDaysInMonth ( calendar, date )

The abstract operation CalendarDateDaysInMonth takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate or Temporal.PlainYearMonth). It identifies the month in the specified calendar that contains date and returns the number of days in that month.

15.9.1.18 CalendarDateDaysInYear ( calendar, date )

The abstract operation CalendarDateDaysInYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate or Temporal.PlainYearMonth). It takes a date-like object date and returns the number of days in the given year in the calendar represented by calendar.

15.9.1.19 CalendarDateMonthsInYear ( calendar, date )

The abstract operation CalendarDateMonthsInYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate or Temporal.PlainYearMonth). It takes a date-like object date and returns the number of months in the given year in the calendar represented by calendar.

15.9.1.20 CalendarDateInLeapYear ( calendar, date )

The abstract operation CalendarDateInLeapYear takes arguments calendar (a String) and date (a Temporal.PlainDateTime, Temporal.PlainDate or Temporal.PlainYearMonth). It takes a date-like object date and returns true if it falls within a leap year for the calendar represented by calendar and false otherwise.

Note
A "leap year" is a year that contains more days than other years (for solar or lunar calendars) or more months than other years (for lunisolar calendars like Hebrew or Chinese). Some calendars, especially lunisolar ones, have further variation in year length that is not represented in the output of this operation (e.g., the Hebrew calendar includes common years with 353, 354, or 355 days and leap years with 383, 384, or 385 days).

15.9.1.21 CalendarFieldDescriptors ( calendar, type )

The implementation-defined abstract operation CalendarFieldDescriptors takes arguments calendar (a String) and type (date, year-month, month-day, or a List of Strings) and returns a List of Calendar Field Descriptor Records. It characterizes calendar-specific fields that are relevant for values of the provided type in the built-in calendar identified by calendar (inferring the type when type is a List by interpreting its elements as field names). For example, "era" (with ToString conversion) and "eraYear" (with ToIntegerWithTruncation conversion) are returned when calendar is "gregory" or "japanese" and type is date or year-month or a List containing "year".

15.9.1.22 CalendarFieldKeysToIgnore ( calendar, keys )

The abstract operation CalendarFieldKeysToIgnore takes arguments calendar (a String) and keys (a List of property keys) and returns a List of property keys. It determines which calendar date fields changing any of the fields named in keys can potentially conflict with or invalidate, for the given calendar. A field always invalidates at least itself.

This operation is relevant for calendars which accept fields other than the standard set of ISO 8601 calendar fields, in order to implement the Temporal objects' with() methods, and Temporal.Calendar.prototype.mergeFields() in such a way that the result is free of ambiguity or conflicts.

For example, given a calendar that uses eras, such as "gregory", a key in keys being any one of "year", "era", or "eraYear" would exclude all three. Passing any one of the three to a with() method might conflict with either of the other two properties on the receiver object, so those properties of the receiver object should be ignored. Given this, in addition to the ISO 8601 mutual exclusion of "month" and "monthCode" as in ISOFieldKeysToIgnore, a possible implementation might produce the following results when calendar is "gregory":

Table 30: Example results of CalendarFieldKeysToIgnore
keys Returned List
« "era" » « "era", "eraYear", "year" »
« "eraYear" » « "era", "eraYear", "year" »
« "year" » « "era", "eraYear", "year" »
« "month" » « "month", "monthCode" »
« "monthCode" » « "month", "monthCode" »
« "day" » « "day" »
« "year", "month", "day" » « "era", "eraYear", "year", "month", "monthCode", "day" »
Note
In a calendar such as "japanese" where eras do not start and end at year and/or month boundaries, note that the returned List should contain "era" and "eraYear" if keys contains "day", "month", or "monthCode" (not only if it contains "era", "eraYear", or "year", as in the example above) because it's possible for changing the day or month to cause a conflict with the era.

15.9.1.23 CalendarResolveFields ( calendar, fields, type )

The abstract operation CalendarResolveFields takes arguments calendar (a String), fields (an Object), and type (date, year-month, or month-day) and returns either a normal completion containing unused or a throw completion. It performs implementation-defined processing to validate that fields (which describes a date or partial date in the built-in calendar identified by calendar) is sufficiently complete to satisfy type and not internally inconsistent, and mutates fields into acceptable input for CalendarDateToISO ( calendar, fields, overflow ) or CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow ) by merging data that can be represented in multiple forms into standard properties and removing redundant properties (for example, merging "month" and "monthCode" into "month" and merging "era" and "eraYear" into "year").

The operation throws a TypeError exception if the properties of fields are internally inconsistent within the calendar or insufficient to identify a unique instance of type in the calendar. For example:

  • If type is date or month-day and "day" in the calendar has an interpretation analogous to ISO 8601 and its corresponding value is undefined.
  • If "month" and "monthCode" in the calendar have interpretations analogous to ISO 8601 and either the corresponding values for both are undefined or neither value is undefined but they do not identify the same month.
  • If type is month-day and the value for "monthCode" is undefined and a year cannot be determined from fields.
  • If type is date or year-month and the calendar supports the usual partitioning of years into eras with their own year counting as represented by "year", "era", and "eraYear" (as in the Gregorian or traditional Japanese calendars) and any of the following cases apply:
    • The value for each of "year" and "era" and "eraYear" is undefined.
    • The value for "era" is undefined but the value for "eraYear" is not.
    • The value for "eraYear" is undefined but the value for "era" is not.
    • None of the three values are undefined but the values for "era" and "eraYear" do not together identify the same year as the value for "year".
Note
When type is month-day and "month" is provided without "monthCode", it is recommended that all built-in calendars other than the ISO 8601 calendar require a disambiguating year (e.g., either "year" or "era" and "eraYear"), including those that always use exactly the same months as the ISO 8601 calendar (which receives special handling in this specification as a default calendar that is permanently stable for automated processing).

15.9.2 Properties of the Temporal.Calendar Prototype Object

15.9.2.1 Temporal.Calendar.prototype.dateFromFields ( fields [ , options ] )

This definition supersedes the definition provided in 12.5.4.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(fields) is not Object, throw a TypeError exception.
  4. Set options to ? GetOptionsObject(options).
  5. Let relevantFieldNames be « "day", "month", "monthCode", "year" ».
  6. If calendar.[[Identifier]] is "iso8601", then
    1. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "year", "day" »).
  7. Else,
    1. Let calendarRelevantFieldDescriptors be CalendarFieldDescriptors(calendar.[[Identifier]], date).
    2. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « », calendarRelevantFieldDescriptors).
  8. Let overflow be ? ToTemporalOverflow(options).
  9. If calendar.[[Identifier]] is "iso8601", then
    1. Perform ? ISOResolveMonth(fields).
    2. Let result be ? ISODateFromFields(fields, overflow).
  10. Else,
    1. Perform ? CalendarResolveFields(calendar.[[Identifier]], fields, date).
    2. Let result be ? CalendarDateToISO(calendar.[[Identifier]], fields, overflow).
  11. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar.[[Identifier]]).

15.9.2.2 Temporal.Calendar.prototype.yearMonthFromFields ( fields [ , options ] )

This definition supersedes the definition provided in 12.5.5.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(fields) is not Object, throw a TypeError exception.
  4. Set options to ? GetOptionsObject(options).
  5. Let relevantFieldNames be « "month", "monthCode", "year" ».
  6. If calendar.[[Identifier]] is "iso8601", then
    1. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "year" »).
  7. Else,
    1. Let calendarRelevantFieldDescriptors be CalendarFieldDescriptors(calendar.[[Identifier]], year-month).
    2. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « », calendarRelevantFieldDescriptors).
    3. Let firstDayIndex be the 1-based index of the first day of the month described by fields (i.e., 1 unless the month's first day is skipped by this calendar.)
    4. Perform ! CreateDataPropertyOrThrow(fields, "day", 𝔽(firstDayIndex)).
  8. Let overflow be ? ToTemporalOverflow(options).
  9. If calendar.[[Identifier]] is "iso8601", then
    1. Perform ? ISOResolveMonth(fields).
    2. Let result be ? ISOYearMonthFromFields(fields, overflow).
  10. Else,
    1. Perform ? CalendarResolveFields(calendar.[[Identifier]], fields, year-month).
    2. Let result be ? CalendarDateToISO(calendar.[[Identifier]], fields, overflow).
    3. Set result.[[ReferenceISODay]] to result.[[Day]].
  11. Return ? CreateTemporalYearMonth(result.[[Year]], result.[[Month]], calendar.[[Identifier]], result.[[ReferenceISODay]]).

15.9.2.3 Temporal.Calendar.prototype.monthDayFromFields ( fields [ , options ] )

This definition supersedes the definition provided in 12.5.6.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(fields) is not Object, throw a TypeError exception.
  4. Set options to ? GetOptionsObject(options).
  5. Let relevantFieldNames be « "day", "month", "monthCode", "year" ».
  6. If calendar.[[Identifier]] is "iso8601", then
    1. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « "day" »).
  7. Else,
    1. Let calendarRelevantFieldDescriptors be CalendarFieldDescriptors(calendar.[[Identifier]], month-day).
    2. Set fields to ? PrepareTemporalFields(fields, relevantFieldNames, « », calendarRelevantFieldDescriptors).
  8. Let overflow be ? ToTemporalOverflow(options).
  9. If calendar.[[Identifier]] is "iso8601", then
    1. Perform ? ISOResolveMonth(fields).
    2. Let result be ? ISOMonthDayFromFields(fields, overflow).
  10. Else,
    1. Perform ? CalendarResolveFields(calendar.[[Identifier]], fields, month-day).
    2. Let result be ? CalendarMonthDayToISOReferenceDate(calendar.[[Identifier]], fields, overflow).
  11. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]], calendar.[[Identifier]], result.[[ReferenceISOYear]]).

15.9.2.4 Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] )

This definition supersedes the definition provided in 12.5.7.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Set date to ? ToTemporalDate(date).
  4. Set duration to ? ToTemporalDuration(duration).
  5. Set options to ? GetOptionsObject(options).
  6. Let overflow be ? ToTemporalOverflow(options).
  7. Let norm be NormalizeTimeDuration(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  8. Let balanceResult be BalanceTimeDuration(norm, "day").
  9. If calendar.[[Identifier]] is "iso8601", then
    1. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]] + balanceResult.[[Days]], overflow).
  10. Else,
    1. Let balancedDuration be ! CreateDateDurationRecord(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]] + balanceResult.[[Days]]).
    2. Let result be ? CalendarDateAddition(calendar.[[Identifier]], date, balancedDuration, overflow).
  11. Return ? CreateTemporalDate(result.[[Year]], result.[[Month]], result.[[Day]], calendar.[[Identifier]]).

15.9.2.5 Temporal.Calendar.prototype.dateUntil ( one, two [ , options ] )

This definition supersedes the definition provided in 12.5.8.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Set one to ? ToTemporalDate(one).
  4. Set two to ? ToTemporalDate(two).
  5. Set options to ? GetOptionsObject(options).
  6. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", date, "auto").
  7. If largestUnit is "auto", set largestUnit to "day".
  8. If calendar.[[Identifier]] is "iso8601", then
    1. Let result be DifferenceISODate(one.[[ISOYear]], one.[[ISOMonth]], one.[[ISODay]], two.[[ISOYear]], two.[[ISOMonth]], two.[[ISODay]], largestUnit).
  9. Else,
    1. Let result be ! CalendarDateDifference(calendar.[[Identifier]], one, two, largestUnit).
    2. Assert: ! IsValidDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0) is true.
  10. Return ! CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], 0, 0, 0, 0, 0, 0).

15.9.2.6 Temporal.Calendar.prototype.era ( temporalDateLike )

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Return undefined.
  5. Return ! CalendarDateEra(calendar.[[Identifier]], temporalDateLike).

15.9.2.7 Temporal.Calendar.prototype.eraYear ( temporalDateLike )

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Return undefined.
  5. Let eraYear be ! CalendarDateEraYear(calendar.[[Identifier]], temporalDateLike).
  6. If eraYear is undefined, then
    1. Return undefined.
  7. Return 𝔽(eraYear).

15.9.2.8 Temporal.Calendar.prototype.year ( temporalDateLike )

This definition supersedes the definition provided in 12.5.9.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Assert: temporalDateLike has an [[ISOYear]] internal slot.
    2. Let year be temporalDateLike.[[ISOYear]].
  5. Else,
    1. Let year be ! CalendarDateYear(calendar.[[Identifier]], temporalDateLike).
  6. Return 𝔽(year).

15.9.2.9 Temporal.Calendar.prototype.month ( temporalDateLike )

This definition supersedes the definition provided in 12.5.10.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is Object and temporalDateLike has an [[InitializedTemporalMonthDay]] internal slot, then
    1. Throw a TypeError exception.
  4. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  5. If calendar.[[Identifier]] is "iso8601", then
    1. Assert: temporalDateLike has an [[ISOMonth]] internal slot.
    2. Let month be temporalDateLike.[[ISOMonth]].
  6. Else,
    1. Let month be ! CalendarDateMonth(calendar.[[Identifier]], temporalDateLike).
  7. Return 𝔽(month).

15.9.2.10 Temporal.Calendar.prototype.monthCode ( temporalDateLike )

This definition supersedes the definition provided in 12.5.11.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Assert: temporalDateLike has an [[ISOMonth]] internal slot.
    2. Let monthCode be ISOMonthCode(temporalDateLike.[[ISOMonth]]).
  5. Else,
    1. Let monthCode be ! CalendarDateMonthCode(calendar.[[Identifier]], temporalDateLike).
  6. Return monthCode.

15.9.2.11 Temporal.Calendar.prototype.day ( temporalDateLike )

This definition supersedes the definition provided in 12.5.12.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalMonthDay]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Assert: temporalDateLike has an [[ISODay]] internal slot.
    2. Let day be temporalDateLike.[[ISODay]].
  5. Else,
    1. Let day be ! CalendarDateDay(calendar.[[Identifier]], temporalDateLike).
  6. Return 𝔽(day).

15.9.2.12 Temporal.Calendar.prototype.dayOfWeek ( dateOrDateTime )

This definition supersedes the definition temporalDateLike in 12.5.13.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Return 𝔽(ToISODayOfWeek(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])).
  5. Let dayOfWeek be ! CalendarDateDayOfWeek(calendar.[[Identifier]], temporalDate).
  6. Return 𝔽(dayOfWeek).

15.9.2.13 Temporal.Calendar.prototype.dayOfYear ( temporalDateLike )

This definition supersedes the definition provided in 12.5.14.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Return 𝔽(ToISODayOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]])).
  5. Let dayOfYear be ! CalendarDateDayOfYear(calendar.[[Identifier]], temporalDate).
  6. Return 𝔽(dayOfYear).

15.9.2.14 Temporal.Calendar.prototype.weekOfYear ( temporalDateLike )

This definition supersedes the definition provided in 12.5.15.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Let yearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]).
  5. Else,
    1. Let yearWeek be CalendarDateWeekOfYear(calendar.[[Identifier]], temporalDate).
  6. Return 𝔽(yearWeek.[[Week]]).

15.9.2.15 Temporal.Calendar.prototype.yearOfWeek ( temporalDateLike )

This definition supersedes the definition provided in 12.5.16.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Let yearWeek be ToISOWeekOfYear(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]]).
  5. Else,
    1. Let yearWeek be CalendarDateWeekOfYear(calendar.[[Identifier]], temporalDate).
  6. Return 𝔽(yearWeek.[[Year]]).

15.9.2.16 Temporal.Calendar.prototype.daysInWeek ( temporalDateLike )

This definition supersedes the definition provided in 12.5.17.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let temporalDate be ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Let daysInWeek be 7.
  5. Else,
    1. Let daysInWeek be ! CalendarDateDaysInWeek(calendar.[[Identifier]], temporalDate).
  6. Return 𝔽(daysInWeek).

15.9.2.17 Temporal.Calendar.prototype.daysInMonth ( temporalDateLike )

This definition supersedes the definition provided in 12.5.18.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slots, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Let daysInMonth be ISODaysInMonth(temporalDateLike.[[ISOYear]], temporalDateLike.[[ISOMonth]]).
  5. Else,
    1. Let daysInMonth be ! CalendarDateDaysInMonth(calendar.[[Identifier]], temporalDateLike).
  6. Return 𝔽(daysInMonth).

15.9.2.18 Temporal.Calendar.prototype.daysInYear ( temporalDateLike )

This definition supersedes the definition provided in 12.5.19.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Return 𝔽(MathematicalDaysInYear(temporalDateLike.[[ISOYear]])).
  5. Let daysInYear be ! CalendarDateDaysInYear(calendar.[[Identifier]], temporalDateLike).
  6. Return 𝔽(daysInYear).

15.9.2.19 Temporal.Calendar.prototype.monthsInYear ( temporalDateLike )

This definition supersedes the definition provided in 12.5.20.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. Let monthsInYear be 12.
  5. Else,
    1. Let monthsInYear be ! CalendarDateMonthsInYear(calendar.[[Identifier]], temporalDateLike).
  6. Return 𝔽(monthsInYear).

15.9.2.20 Temporal.Calendar.prototype.inLeapYear ( temporalDateLike )

This definition supersedes the definition provided in 12.5.21.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. If Type(temporalDateLike) is not Object or temporalDateLike does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
    1. Set temporalDateLike to ? ToTemporalDate(temporalDateLike).
  4. If calendar.[[Identifier]] is "iso8601", then
    1. If MathematicalInLeapYear(EpochTimeForYear(temporalDateLike.[[ISOYear]])) is 1, then
      1. Let inLeapYear be true.
    2. Else,
      1. Let inLeapYear be false.
  5. Else,
    1. Let inLeapYear be ! CalendarDateInLeapYear(calendar.[[Identifier]], temporalDateLike).
  6. Return inLeapYear.

15.9.2.21 Temporal.Calendar.prototype.fields ( fields )

This definition supersedes the definition provided in 12.5.22.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let iteratorRecord be ? GetIterator(fields, sync).
  4. Let fieldNames be a new empty List.
  5. Let next be undefined.
  6. Repeat, while next is not done,
    1. Set next to ? IteratorStepValue(iteratorRecord).
    2. If next is not done, then
      1. If next is not a String, then
        1. Let completion be ThrowCompletion(a newly created TypeError object).
        2. Return ? IteratorClose(iteratorRecord, completion).
      2. If fieldNames contains next, then
        1. Let completion be ThrowCompletion(a newly created RangeError object).
        2. Return ? IteratorClose(iteratorRecord, completion).
      3. If next is not one of "year", "month", "monthCode", or "day", then
        1. Let completion be ThrowCompletion(a newly created RangeError object).
        2. Return ? IteratorClose(iteratorRecord, completion).
      4. Append next to the end of the List fieldNames.
  7. Let result be fieldNames.
  8. If calendar.[[Identifier]] is not "iso8601", then
    1. NOTE: Every built-in calendar preserves all input field names in output.
    2. Let extraFieldDescriptors be CalendarFieldDescriptors(calendar.[[Identifier]], fieldNames).
    3. For each Calendar Field Descriptor Record desc of extraFieldDescriptors, do
      1. Append desc.[[Property]] to result.
  9. Return CreateArrayFromList(result).

15.9.2.22 Temporal.Calendar.prototype.mergeFields ( fields, additionalFields )

This definition supersedes the definition provided in 12.5.23.

This method performs the following steps when called:

  1. Let calendar be the this value.
  2. Perform ? RequireInternalSlot(calendar, [[InitializedTemporalCalendar]]).
  3. Let fieldsCopy be ? SnapshotOwnProperties(? ToObject(fields), null, « », « undefined »).
  4. Let additionalFieldsCopy be ? SnapshotOwnProperties(? ToObject(additionalFields), null, « », « undefined »).
  5. NOTE: Every property of fieldsCopy and additionalFieldsCopy is an enumerable data property with non-undefined value, but some property keys may be Symbols.
  6. Let additionalKeys be ! additionalFieldsCopy.[[OwnPropertyKeys]]().
  7. If calendar.[[Identifier]] is "iso8601", then
    1. Let overriddenKeys be ISOFieldKeysToIgnore(additionalKeys).
  8. Else,
    1. Let overriddenKeys be CalendarFieldKeysToIgnore(calendar, additionalKeys).
  9. Let merged be OrdinaryObjectCreate(null).
  10. NOTE: The following steps ensure that property iteration order of merged matches that of fields as modified by omitting overridden properties and appending non-overlapping properties from additionalFields in iteration order.
  11. Let fieldsKeys be ! fieldsCopy.[[OwnPropertyKeys]]().
  12. For each element key of fieldsKeys, do
    1. Let propValue be undefined.
    2. If overriddenKeys contains key, then
      1. Set propValue to ! Get(additionalFieldsCopy, key).
    3. Else,
      1. Set propValue to ! Get(fieldsCopy, key).
    4. If propValue is not undefined, perform ! CreateDataPropertyOrThrow(merged, key, propValue).
  13. Perform ! CopyDataProperties(merged, additionalFieldsCopy, « »).
  14. Return merged.

15.9.3 Properties of the Temporal.Duration Prototype Object

15.9.3.1 Temporal.Duration.prototype.toLocaleString ( [ locales [ , options ] ] )

Editor's Note

This function is currently not specified. See the Intl.DurationFormat proposal.

15.9.4 Properties of the Temporal.Instant Prototype Object

15.9.4.1 Temporal.Instant.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 8.3.14.

This method performs the following steps when called:

  1. Let instant be the this value.
  2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, any, all).
  4. Return ? FormatDateTime(dateFormat, instant).

15.9.5 Properties of the Temporal.PlainDate Prototype Object

15.9.5.1 Temporal.PlainDate.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 3.3.31.

This method performs the following steps when called:

  1. Let temporalDate be the this value.
  2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, date, date).
  4. Return ? FormatDateTime(dateFormat, temporalDate).

15.9.5.2 get Temporal.PlainDate.prototype.era

Temporal.PlainDate.prototype.era is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let calendar be plainDate.[[Calendar]].
  4. Return ? CalendarEra(calendar, plainDate).

15.9.5.3 get Temporal.PlainDate.prototype.eraYear

Temporal.PlainDate.prototype.eraYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let calendar be plainDate.[[Calendar]].
  4. Return ? CalendarEraYear(calendar, plainDate).

15.9.6 Properties of the Temporal.PlainDateTime Prototype Object

15.9.6.1 Temporal.PlainDateTime.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 5.3.34.

This method performs the following steps when called:

  1. Let dateTime be the this value.
  2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, any, all).
  4. Return ? FormatDateTime(dateFormat, dateTime).

15.9.6.2 get Temporal.PlainDateTime.prototype.era

Temporal.PlainDate.prototype.era is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be plainDateTime.[[Calendar]].
  4. Return ? CalendarEra(calendar, plainDateTime).

15.9.6.3 get Temporal.PlainDateTime.prototype.eraYear

Temporal.PlainDateTime.prototype.eraYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be plainDateTime.[[Calendar]].
  4. Return ? CalendarEraYear(calendar, plainDateTime).

15.9.7 Properties of the Temporal.PlainMonthDay Prototype Object

15.9.7.1 Temporal.PlainMonthDay.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 10.3.9.

This method performs the following steps when called:

  1. Let monthDay be the this value.
  2. Perform ? RequireInternalSlot(monthDay, [[InitializedTemporalMonthDay]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, date, date).
  4. Return ? FormatDateTime(dateFormat, monthDay).

15.9.8 Properties of the Temporal.PlainTime Prototype Object

15.9.8.1 Temporal.PlainTime.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 4.3.20.

This method performs the following steps when called:

  1. Let temporalTime be the this value.
  2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, time, time).
  4. Return ? FormatDateTime(dateFormat, temporalTime).

15.9.9 Properties of the Temporal.PlainYearMonth Prototype Object

15.9.9.1 Temporal.PlainYearMonth.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 9.3.18.

This method performs the following steps when called:

  1. Let yearMonth be the this value.
  2. Perform ? RequireInternalSlot(yearMonth, [[InitializedTemporalYearMonth]]).
  3. Let dateFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, date, date).
  4. Return ? FormatDateTime(dateFormat, yearMonth).

15.9.9.2 get Temporal.PlainYearMonth.prototype.era

Temporal.PlainYearMonth.prototype.era is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be plainYearMonth.[[Calendar]].
  4. Return ? CalendarEra(calendar, plainYearMonth).

15.9.9.3 get Temporal.PlainYearMonth.prototype.eraYear

Temporal.PlainYearMonth.prototype.eraYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Let calendar be plainYearMonth.[[Calendar]].
  4. Return ? CalendarEraYear(calendar, plainYearMonth).

15.9.10 Properties of the Temporal.ZonedDateTime Prototype Object

15.9.10.1 Temporal.ZonedDateTime.prototype.toLocaleString ( [ locales [ , options ] ] )

This definition supersedes the definition provided in 6.3.43.

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZone be ? ToTemporalTimeZoneIdentifier(zonedDateTime.[[TimeZone]]).
  4. Let timeZoneParseResult be ? ParseTimeZoneIdentifier(timeZone).
  5. If timeZoneParseResult.[[OffsetMinutes]] is not empty, throw a RangeError exception.
  6. Let timeZoneIdentifierRecord be GetAvailableNamedTimeZoneIdentifier(timeZone).
  7. If timeZoneIdentifierRecord is empty, throw a RangeError exception.
  8. Set timeZone to timeZoneIdentifierRecord.[[Identifier]].
  9. Let dateTimeFormat be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, locales, options, any, all, timeZone).
  10. Let calendar be ? ToTemporalCalendarIdentifier(zonedDateTime.[[Calendar]]).
  11. If calendar is not "iso8601" and not equal to dateTimeFormat.[[Calendar]], then
    1. Throw a RangeError exception.
  12. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  13. Return ? FormatDateTime(dateTimeFormat, instant).

15.9.10.2 get Temporal.ZonedDateTime.prototype.era

Temporal.ZonedDateTime.prototype.era is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ? CalendarEra(calendar, plainDateTime).

15.9.10.3 get Temporal.ZonedDateTime.prototype.eraYear

Temporal.ZonedDateTime.prototype.eraYear is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let instant be ! CreateTemporalInstant(zonedDateTime.[[Nanoseconds]]).
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let timeZoneRec be ? CreateTimeZoneMethodsRecord(zonedDateTime.[[TimeZone]], « get-offset-nanoseconds-for »).
  6. Let plainDateTime be ? GetPlainDateTimeFor(timeZoneRec, instant, calendar).
  7. Return ? CalendarEraYear(calendar, plainDateTime).

A Copyright & Software License

Copyright Notice

© 2024 Maggie Pint, Matt Johnson, Brian Terlson, Daniel Ehrenberg, Philipp Dunkel, Sasha Pierson, Ujjwal Sharma, Philip Chimento, Justin Grant

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.