PR #3966

This document is a preview of the specification for PR #3966 commit 3d4a6e7124a6878cb5af3132af7e01e01a88317f, and should only be used as a historical reference. This commit may not have even been merged into the specification.

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://github.com/tc39/ecma262 for the living specification.

Multipage preference

22 Dates and Temporal

22.1 Date Objects

22.1.1 Overview of Date Objects and Definitions of Abstract Operations

The following abstract operations operate on time values (defined in 22.1.1.1). Note that, in every case, if any argument to one of these functions is NaN, the result will be NaN.

22.1.1.1 Time Values and Time Range

Time measurement in ECMAScript is analogous to time measurement in POSIX, in particular sharing definition in terms of the proleptic Gregorian calendar, an epoch of midnight at the beginning of 1 January 1970 UTC, and an accounting of every day as comprising exactly 86,400 seconds (each of which is 1000 milliseconds long).

An ECMAScript time value is a Number, either a finite integral Number representing an instant in time to millisecond precision or NaN representing no specific instant. A time value that is an integer multiple of MillisecondsPerDay (i.e., is MillisecondsPerDay × d for some integer d) represents the instant at the start of the UTC day that follows the epoch by d whole UTC days (preceding the epoch for negative d). Every other finite time value tv is defined relative to the greatest preceding time value s that is such a multiple, and represents the instant that occurs within the same UTC day as s but follows it by (tv - s) milliseconds.

Time values do not account for UTC leap seconds—there are no time values representing instants within positive leap seconds, and there are time values representing instants removed from the UTC timeline by negative leap seconds. However, the definition of time values nonetheless yields piecewise alignment with UTC, with discontinuities only at leap second boundaries and zero difference outside of leap seconds.

A Number can exactly represent all integers from -9,007,199,254,740,992 to 9,007,199,254,740,992 (21.1.2.8 and 21.1.2.6). A time value supports a slightly smaller range of -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds. This yields a supported time value range of exactly -100,000,000 days to 100,000,000 days relative to midnight at the beginning of 1 January 1970 UTC.

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

Note

In the proleptic Gregorian calendar, leap years are precisely those which are both divisible by 4 and either divisible by 400 or not divisible by 100.

The 400 year cycle of the proleptic Gregorian calendar contains 97 leap years. This yields an average of 365.2425 days per year, which is 31,556,952,000 milliseconds. Therefore, the maximum range a Number could represent exactly with millisecond precision is approximately -285,426 to 285,426 years relative to 1970. The smaller range supported by a time value as specified in this section is approximately -273,790 to 273,790 years relative to 1970.

22.1.1.2 Time-related Constants

These constants are referenced by algorithms in the following sections.

HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
MillisecondsPerSecond = 1000
MillisecondsPerMinute = 60000 = MillisecondsPerSecond × SecondsPerMinute
MillisecondsPerHour = 3600000 = MillisecondsPerMinute × MinutesPerHour
MillisecondsPerDay = 86400000 = MillisecondsPerHour × HoursPerDay
NanosecondsPerDay = 106 × MillisecondsPerDay = 8.64 × 1013
NanosecondsPerHour = 106 × MillisecondsPerHour = 3.6 × 1012
NanosecondsPerMinute = 106 × MillisecondsPerMinute = 6 × 1010
NanosecondsPerSecond = 106 × MillisecondsPerSecond = 109
NanosecondsPerMillisecond = 106
NanosecondsPerMicrosecond = 103
MaxEpochNanoseconds = 108 × NanosecondsPerDay = 8.64 × 1021
MinEpochNanoseconds = -MaxEpochNanoseconds = -8.64 × 1021

22.1.1.3 Day ( tv )

The abstract operation Day takes argument tv (a finite time value) and returns an integer. It returns the day number of the day in which tv falls. It performs the following steps when called:

  1. Return floor((tv) / MillisecondsPerDay).

22.1.1.4 TimeWithinDay ( tv )

The abstract operation TimeWithinDay takes argument tv (a finite time value) and returns an integer in the interval from 0 (inclusive) to MillisecondsPerDay (exclusive). It returns the number of milliseconds since the start of the day in which tv falls. It performs the following steps when called:

  1. Return (tv) modulo MillisecondsPerDay.

22.1.1.5 DayFromYear ( y )

The abstract operation DayFromYear takes argument y (an integer) and returns an integer. It returns the day number of the first day of year y. It performs the following steps when called:

  1. NOTE: In the following steps, numberYears1, numberYears4, numberYears100, and numberYears400 represent the number of years divisible by 1, 4, 100, and 400, respectively, that occur between the epoch and the start of year y. The number is negative if y is before the epoch.
  2. Let numberYears1 be (y - 1970).
  3. Let numberYears4 be floor((y - 1969) / 4).
  4. Let numberYears100 be floor((y - 1901) / 100).
  5. Let numberYears400 be floor((y - 1601) / 400).
  6. Return 365 × numberYears1 + numberYears4 - numberYears100 + numberYears400.

22.1.1.6 TimeFromYear ( y )

The abstract operation TimeFromYear takes argument y (an integer) and returns a time value. It returns the time value of the start of year y. It performs the following steps when called:

  1. Return 𝔽(MillisecondsPerDay × DayFromYear(y)).

22.1.1.7 YearFromTime ( tv )

The abstract operation YearFromTime takes argument tv (a finite time value) and returns an integer. It returns the year in which tv falls. It performs the following steps when called:

  1. Return the largest integer y (closest to +∞) such that TimeFromYear(y) ≤ tv.

22.1.1.8 DayWithinYear ( tv )

The abstract operation DayWithinYear takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 365. It performs the following steps when called:

  1. Return Day(tv) - DayFromYear(YearFromTime(tv)).

22.1.1.9 InLeapYear ( tv )

The abstract operation InLeapYear takes argument tv (a finite time value) and returns 0 or 1. It returns 1 if tv is within a leap year and 0 otherwise. It performs the following steps when called:

  1. Let y be YearFromTime(tv).
  2. If (y modulo 400) = 0, return 1.
  3. If (y modulo 100) = 0, return 0.
  4. If (y modulo 4) = 0, return 1.
  5. Return 0.

22.1.1.10 MonthFromTime ( tv )

The abstract operation MonthFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 11. It returns an integer identifying the month in which tv falls. 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 MonthFromTime(+0𝔽) = 0, corresponding to Thursday, 1 January 1970. It performs the following steps when called:

  1. Let inLeapYear be InLeapYear(tv).
  2. Let dayWithinYear be DayWithinYear(tv).
  3. If dayWithinYear < 31, return 0.
  4. If dayWithinYear < 59 + inLeapYear, return 1.
  5. If dayWithinYear < 90 + inLeapYear, return 2.
  6. If dayWithinYear < 120 + inLeapYear, return 3.
  7. If dayWithinYear < 151 + inLeapYear, return 4.
  8. If dayWithinYear < 181 + inLeapYear, return 5.
  9. If dayWithinYear < 212 + inLeapYear, return 6.
  10. If dayWithinYear < 243 + inLeapYear, return 7.
  11. If dayWithinYear < 273 + inLeapYear, return 8.
  12. If dayWithinYear < 304 + inLeapYear, return 9.
  13. If dayWithinYear < 334 + inLeapYear, return 10.
  14. Assert: dayWithinYear < 365 + inLeapYear.
  15. Return 11.

22.1.1.11 DateFromTime ( tv )

The abstract operation DateFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 1 to 31. It returns the day of the month in which tv falls. It performs the following steps when called:

  1. Let inLeapYear be InLeapYear(tv).
  2. Let dayWithinYear be DayWithinYear(tv).
  3. Let month be MonthFromTime(tv).
  4. If month = 0, return dayWithinYear + 1.
  5. If month = 1, return dayWithinYear - 30.
  6. If month = 2, return dayWithinYear - 58 - inLeapYear.
  7. If month = 3, return dayWithinYear - 89 - inLeapYear.
  8. If month = 4, return dayWithinYear - 119 - inLeapYear.
  9. If month = 5, return dayWithinYear - 150 - inLeapYear.
  10. If month = 6, return dayWithinYear - 180 - inLeapYear.
  11. If month = 7, return dayWithinYear - 211 - inLeapYear.
  12. If month = 8, return dayWithinYear - 242 - inLeapYear.
  13. If month = 9, return dayWithinYear - 272 - inLeapYear.
  14. If month = 10, return dayWithinYear - 303 - inLeapYear.
  15. Assert: month = 11.
  16. Return dayWithinYear - 333 - inLeapYear.

22.1.1.12 WeekDay ( tv )

The abstract operation WeekDay takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 6. It returns an integer identifying the day of the week in which tv falls. 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 WeekDay(+0𝔽) = 4, corresponding to Thursday, 1 January 1970. It performs the following steps when called:

  1. Return (Day(tv) + 4) modulo 7.

22.1.1.13 HourFromTime ( tv )

The abstract operation HourFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 23. It returns the hour of the day in which tv falls. It performs the following steps when called:

  1. Return floor((tv) / MillisecondsPerHour) modulo HoursPerDay.

22.1.1.14 MinuteFromTime ( tv )

The abstract operation MinuteFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 59. It returns the minute of the hour in which tv falls. It performs the following steps when called:

  1. Return floor((tv) / MillisecondsPerMinute) modulo MinutesPerHour.

22.1.1.15 SecondFromTime ( tv )

The abstract operation SecondFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 59. It returns the second of the minute in which tv falls. It performs the following steps when called:

  1. Return floor((tv) / MillisecondsPerSecond) modulo SecondsPerMinute.

22.1.1.16 MillisecondFromTime ( tv )

The abstract operation MillisecondFromTime takes argument tv (a finite time value) and returns an integer in the inclusive interval from 0 to 999. It returns the millisecond of the second in which tv falls. It performs the following steps when called:

  1. Return (tv) modulo MillisecondsPerSecond.

22.1.1.17 GetUTCEpochNanoseconds ( isoDateTime )

The abstract operation GetUTCEpochNanoseconds takes argument isoDateTime (an ISO Date-Time Record) and returns an epoch nanoseconds count. The returned value is the epoch nanoseconds count that corresponds to the given ISO 8601 calendar date and wall-clock time in UTC. It performs the following steps when called:

  1. Let date be MakeDay(𝔽(isoDateTime.[[ISODate]].[[Year]]), 𝔽(isoDateTime.[[ISODate]].[[Month]] - 1), 𝔽(isoDateTime.[[ISODate]].[[Day]])).
  2. Let time be MakeTime(𝔽(isoDateTime.[[Time]].[[Hour]]), 𝔽(isoDateTime.[[Time]].[[Minute]]), 𝔽(isoDateTime.[[Time]].[[Minute]]), 𝔽(isoDateTime.[[Time]].[[Millisecond]])).
  3. Let epochMilliseconds be MakeDate(date, time).
  4. Assert: epochMilliseconds is an integral Number.
  5. Return (epochMilliseconds) × NanosecondsPerMillisecond + isoDateTime.[[Time]].[[Microsecond]] × NanosecondsPerMicrosecond + isoDateTime.[[Time]].[[Nanosecond]].

22.1.1.18 LocalTime ( tv )

The abstract operation LocalTime takes argument tv (a finite time value) and returns an integral Number. It converts tv from UTC to local time. The local political rules for standard time and daylight saving time in effect at tv 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 parseResult.[[OffsetMinutes]] is not empty, then
    1. Let offsetNanoseconds be parseResult.[[OffsetMinutes]] × NanosecondsPerMinute.
  4. Else,
    1. Let offsetNanoseconds be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, (tv) × NanosecondsPerMillisecond).
  5. Let offsetMilliseconds be truncate(offsetNanoseconds / NanosecondsPerMillisecond).
  6. Return tv + 𝔽(offsetMilliseconds).
Note 1

If political rules for the local time tv are not available within the implementation, the result is tv 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.

Note 3

Two different input time values tvUTC 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(tvlocal)) is not necessarily always equal to tvlocal. Correspondingly, UTC(LocalTime(tvUTC)) is not necessarily always equal to tvUTC.

22.1.1.19 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 parseResult.[[OffsetMinutes]] is not empty, then
    1. Let offsetNanoseconds be parseResult.[[OffsetMinutes]] × NanosecondsPerMinute.
  5. Else,
    1. Let isoDateTime be TimeValueToISODateTimeRecord(t).
    2. Let possibleInstants be GetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, isoDateTime).
    3. 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.
    4. If possibleInstants is not empty, then
      1. Let disambiguatedInstant be possibleInstants[0].
    5. 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, TimeValueToISODateTimeRecord(tBefore)), 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.
    6. Let offsetNanoseconds be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant).
  6. Let offsetMilliseconds be truncate(offsetNanoseconds / NanosecondsPerMillisecond).
  7. Return t - 𝔽(offsetMilliseconds).

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.

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 offsetMilliseconds is -4 × MillisecondsPerHour.

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 offsetMilliseconds is -5 × MillisecondsPerHour.

Note 2

UTC(LocalTime(tUTC)) is not necessarily always equal to tUTC. Correspondingly, LocalTime(UTC(tlocal)) is not necessarily always equal to tlocal.

22.1.1.20 MakeTime ( hour, minute, second, millisecond )

The abstract operation MakeTime takes arguments hour (a Number), minute (a Number), second (a Number), and millisecond (a Number) and returns a Number. It calculates a number of milliseconds. It performs the following steps when called:

  1. If hour is not finite, minute is not finite, second is not finite, or millisecond is not finite, return NaN.
  2. Let hourMV be ! ToIntegerOrInfinity(hour).
  3. Let minuteMV be ! ToIntegerOrInfinity(minute).
  4. Let secondMV be ! ToIntegerOrInfinity(second).
  5. Let millisecondMV be ! ToIntegerOrInfinity(millisecond).
  6. Return ((𝔽(hourMV) × 𝔽(MillisecondsPerHour) + 𝔽(minuteMV) × 𝔽(MillisecondsPerMinute)) + 𝔽(secondMV) × 𝔽(MillisecondsPerSecond)) + 𝔽(millisecondMV).
Note

The arithmetic in MakeTime is floating-point arithmetic, which is not associative, so the operations must be performed in the correct order.

22.1.1.21 MakeDay ( year, month, day )

The abstract operation MakeDay takes arguments year (a Number), month (a Number), and day (a Number) and returns a finite Number or NaN. It calculates a number of days. It performs the following steps when called:

  1. If year is not finite, month is not finite, or day is not finite, return NaN.
  2. Let yearMV be ! ToIntegerOrInfinity(year).
  3. Let monthMV be ! ToIntegerOrInfinity(month).
  4. Let dayMV be ! ToIntegerOrInfinity(day).
  5. Let balancedYear be 𝔽(yearMV) + 𝔽(floor(monthMV / 12)).
  6. If balancedYear is not finite, return NaN.
  7. Let balancedMonthMV be monthMV modulo 12.
  8. Find a finite time value tv such that YearFromTime(tv) = (balancedYear), MonthFromTime(tv) = balancedMonthMV, and DateFromTime(tv) = 1; but if this is not possible (because some argument is out of range), return NaN.
  9. Return 𝔽(Day(tv)) + 𝔽(dayMV) - 1𝔽.

22.1.1.22 MakeDate ( day, time )

The abstract operation MakeDate takes arguments day (a Number) and time (a Number) and returns a finite Number or NaN. It calculates a number of milliseconds. It performs the following steps when called:

  1. If day is not finite or time is not finite, return NaN.
  2. Let tv be day × 𝔽(MillisecondsPerDay) + time.
  3. If tv is not finite, return NaN.
  4. Return tv.

22.1.1.23 MakeFullYear ( year )

The abstract operation MakeFullYear takes argument year (a Number) and returns an integral Number or NaN. It returns the full year associated with the integer part of year, interpreting any value in the inclusive interval from 0 to 99 as a count of years since the start of 1900. For alignment with the proleptic Gregorian calendar, “full year” is defined as the signed count of complete years since the start of year 0 (1 B.C.). It performs the following steps when called:

  1. If year is one of NaN, +∞𝔽, or -∞𝔽, return NaN.
  2. Let truncated be ! ToIntegerOrInfinity(year).
  3. If truncated is in the inclusive interval from 0 to 99, return 1900𝔽 + 𝔽(truncated).
  4. Return 𝔽(truncated).

22.1.1.24 TimeClip ( time )

The abstract operation TimeClip takes argument time (a Number) and returns a time value. It calculates a number of milliseconds. It performs the following steps when called:

  1. If time is not finite, return NaN.
  2. If abs((time)) > 8.64 × 1015, return NaN.
  3. Return 𝔽(! ToIntegerOrInfinity(time)).

22.1.1.25 Date Time String Format

ECMAScript defines a string interchange format for date-times which is adapted from the ISO 8601 calendar date extended format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ

Where the elements are as follows:

YYYY is the year in the proleptic Gregorian calendar as four decimal digits from 0000 to 9999, or as an expanded year of "+" or "-" followed by six decimal digits.
- "-" (hyphen) appears literally twice in the string.
MM is the month of the year as two decimal digits from 01 (January) to 12 (December).
DD is the day of the month as two decimal digits from 01 to 31.
T "T" appears literally in the string, to indicate the beginning of the time element.
HH is the number of complete hours that have passed since midnight as two decimal digits from 00 to 24.
: ":" (colon) appears literally twice in the string.
mm is the number of complete minutes since the start of the hour as two decimal digits from 00 to 59.
ss is the number of complete seconds since the start of the minute as two decimal digits from 00 to 59.
. "." (dot) appears literally in the string.
sss is the number of complete milliseconds since the start of the second as three decimal digits.
Z is the UTC offset representation specified as "Z" (for UTC with no offset) or as either "+" or "-" followed by a time expression HH:mm (a subset of the time zone offset string format for indicating local time ahead of or behind UTC, respectively)

This format includes date-only forms:

YYYY
YYYY-MM
YYYY-MM-DD
        

It also includes “date-time” forms that consist of one of the above date-only forms immediately followed by one of the following time forms with an optional UTC offset representation appended:

THH:mm
THH:mm:ss
THH:mm:ss.sss
        

A string containing out-of-bounds or nonconforming elements is not a valid instance of this format.

Note 1

As every day both starts and ends with midnight, the two notations 00:00 and 24:00 are available to distinguish the two midnights that can be associated with one date. This means that the following two notations refer to exactly the same point in time: 1995-02-04T24:00 and 1995-02-05T00:00.

Note 2

This format does not support annotations with a time zone name as defined in RFC 9557, only a numeric representation of the time zone offset. For strings with a time zone annotation, see 22.4.

22.1.1.25.1 Expanded Years

Covering the full time value range of approximately 273,790 years forward or backward from 1 January 1970 (22.1.1.1) requires representing years before 0 or after 9999. ISO 8601 permits expansion of the year representation, but only by mutual agreement of the partners in information interchange. In the simplified ECMAScript format, such an expanded year representation shall have 6 digits and is always prefixed with a + or - sign. The year 0 is considered positive and must be prefixed with a + sign. The representation of the year 0 as -000000 is invalid. Strings matching the Date Time String Format with expanded years representing instants in time outside the range of a time value are treated as unrecognizable by Date.parse and cause that function to return NaN without falling back to implementation-specific behaviour or heuristics.

Note

Examples of date-time values with expanded years:

-271821-04-20T00:00:00Z 271822 B.C.
-000001-01-01T00:00:00Z 2 B.C.
+000000-01-01T00:00:00Z 1 B.C.
+000001-01-01T00:00:00Z 1 A.D.
+001970-01-01T00:00:00Z 1970 A.D.
+002009-12-15T00:00:00Z 2009 A.D.
+275760-09-13T00:00:00Z 275760 A.D.

22.1.1.26 Time Zone Offset String Format

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 UTCOffset[~SubMinutePrecision]. UTC offsets that represent the offset of a named time zone can be more precise, and are specified by UTCOffset[+SubMinutePrecision].

These formats are described by the grammar in 22.4.1.

22.1.1.26.1 ParseDateTimeUTCOffset ( offsetString )

The abstract operation ParseDateTimeUTCOffset takes argument offsetString (a String) and returns either a normal completion containing an integer in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive), or a throw completion. It returns 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(offsetString, UTCOffset[+SubMinutePrecision]).
  2. If parseResult is not a Parse Node, throw a RangeError exception.
  3. Assert: parseResult contains a ASCIISign Parse Node.
  4. Let parsedSign be the source text matched by the ASCIISign Parse Node contained within parseResult.
  5. If parsedSign is the single code point U+002D (HYPHEN-MINUS), then
    1. Let sign be -1.
  6. Else,
    1. Let sign be 1.
  7. 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.
  8. Assert: parseResult contains an Hour Parse Node.
  9. Let parsedHours be the source text matched by the Hour Parse Node contained within parseResult.
  10. Let hours be (StringToNumber(CodePointsToString(parsedHours))).
  11. If parseResult does not contain a Minute Parse Node, then
    1. Let minutes be 0.
  12. Else,
    1. Let parsedMinutes be the source text matched by the Minute Parse Node contained within parseResult.
    2. Let minutes be (StringToNumber(CodePointsToString(parsedMinutes))).
  13. If parseResult does not contain a Second Parse Node, then
    1. Let seconds be 0.
  14. Else,
    1. Let parsedSeconds be the source text matched by the Second Parse Node contained within parseResult.
    2. Let seconds be (StringToNumber(CodePointsToString(parsedSeconds))).
  15. If parseResult does not contain a TemporalDecimalFraction Parse Node, then
    1. Let nanoseconds be 0.
  16. 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)).
  17. Return sign × (((hours × MinutesPerHour + minutes) × SecondsPerMinute + seconds) × NanosecondsPerSecond + nanoseconds).

22.1.1.27 HostSystemUTCEpochNanoseconds ( global )

The host-defined abstract operation HostSystemUTCEpochNanoseconds takes argument global (a global object) and returns an epoch nanoseconds count. 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 operation provides the current time to the Date constructor (22.1.2.1), Date.now (22.1.3.1), and the functions on the Temporal.Now object. The range requirement is necessary if the system clock is set to a time outside the range that Date and Temporal.Instant objects can represent. This is not expected to affect implementations in practice.

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

  1. Let epochNanoseconds be the approximate current UTC date and time, in nanoseconds since the epoch.
  2. Return the result of clamping epochNanoseconds between MinEpochNanoseconds and MaxEpochNanoseconds.

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

22.1.1.28 SystemUTCEpochMilliseconds ( )

The abstract operation SystemUTCEpochMilliseconds takes no arguments and returns an integral Number. It performs the following steps when called:

  1. Let global be GetGlobalObject().
  2. Let nowEpochNanoseconds be HostSystemUTCEpochNanoseconds(global).
  3. Return 𝔽(floor(nowEpochNanoseconds / NanosecondsPerMillisecond)).

22.1.2 The Date Constructor

The Date constructor:

  • is %Date%.
  • is the initial value of the "Date" property of the global object.
  • creates and initializes a new Date when called as a constructor.
  • returns a String representing the current time (UTC) when called as a function rather than as a constructor.
  • is a function whose behaviour differs based upon the number and types of its arguments.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified Date behaviour must include a super call to the Date constructor to create and initialize the subclass instance with a [[DateValue]] internal slot.

22.1.2.1 Date ( ...values )

This function performs the following steps when called:

  1. If NewTarget is undefined, return ToDateString(SystemUTCEpochMilliseconds()).
  2. Let numberOfArgs be the number of elements in values.
  3. If numberOfArgs = 0, then
    1. Let dv be SystemUTCEpochMilliseconds().
  4. 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 (22.1.3.2).
      3. Else,
        1. Let tv be ? ToNumber(v).
    4. Let dv be TimeClip(tv).
  5. Else,
    1. Assert: numberOfArgs ≥ 2.
    2. Let yearNumber be ? ToNumber(values[0]).
    3. Let monthNumber be ? ToNumber(values[1]).
    4. If numberOfArgs > 2, let dayNumber be ? ToNumber(values[2]); else let dayNumber be 1𝔽.
    5. If numberOfArgs > 3, let hourNumber be ? ToNumber(values[3]); else let hourNumber be +0𝔽.
    6. If numberOfArgs > 4, let minuteNumber be ? ToNumber(values[4]); else let minuteNumber be +0𝔽.
    7. If numberOfArgs > 5, let secondNumber be ? ToNumber(values[5]); else let secondNumber be +0𝔽.
    8. If numberOfArgs > 6, let millisecondNumber be ? ToNumber(values[6]); else let millisecondNumber be +0𝔽.
    9. Set yearNumber to MakeFullYear(yearNumber).
    10. Let finalDate be MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber)).
    11. Let dv be TimeClip(UTC(finalDate)).
  6. Let obj be ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »).
  7. Set obj.[[DateValue]] to dv.
  8. Return obj.

22.1.3 Properties of the Date Constructor

The Date constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has a "length" property whose value is 7𝔽.
  • has the following properties:

22.1.3.1 Date.now ( )

This function performs the following steps when called:

  1. Return SystemUTCEpochMilliseconds().

22.1.3.2 Date.parse ( string )

This function applies the ToString operator to its argument. If ToString results in an abrupt completion the Completion Record is immediately returned. Otherwise, this function interprets the resulting String as a date and time; it returns a Number, the UTC time value corresponding to the date and time. The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String. The function first attempts to parse the String according to the format described in Date Time String Format (22.1.1.25), including expanded years. If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats. Strings that are unrecognizable or contain out-of-bounds format element values shall cause this function to return NaN.

If the String conforms to the Date Time String Format, substitute values take the place of absent format elements. When the MM or DD elements are absent, "01" is used. When the HH, mm, or ss elements are absent, "00" is used. When the sss element is absent, "000" is used. When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.

If x is any Date whose milliseconds amount is zero within a particular implementation of ECMAScript, then all of the following expressions should produce the same numeric value in that implementation, if all the properties referenced have their initial values:

x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())

However, the expression

Date.parse(x.toLocaleString())

is not required to produce the same Number value as the preceding three expressions and, in general, the value produced by this function is implementation-defined when given any String value that does not conform to the Date Time String Format (22.1.1.25) and that could not be produced in that implementation by the toString or toUTCString method.

22.1.3.3 Date.prototype

The initial value of Date.prototype is the Date prototype object.

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

22.1.3.4 Date.UTC ( year [ , month [ , day [ , hour [ , minute [ , second [ , millisecond ] ] ] ] ] ] )

This function performs the following steps when called:

  1. Let yearNumber be ? ToNumber(year).
  2. If month is present, let monthNumber be ? ToNumber(month); else let monthNumber be +0𝔽.
  3. If day is present, let dayNumber be ? ToNumber(day); else let dayNumber be 1𝔽.
  4. If hour is present, let hourNumber be ? ToNumber(hour); else let hourNumber be +0𝔽.
  5. If minute is present, let minuteNumber be ? ToNumber(minute); else let minuteNumber be +0𝔽.
  6. If second is present, let secondNumber be ? ToNumber(second); else let secondNumber be +0𝔽.
  7. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond); else let millisecondNumber be +0𝔽.
  8. Set yearNumber to MakeFullYear(yearNumber).
  9. Return TimeClip(MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber))).

The "length" property of this function is 7𝔽.

Note

This function differs from the Date constructor in two ways: it returns a time value as a Number, rather than creating a Date, and it interprets the arguments in UTC rather than as local time.

22.1.4 Properties of the Date Prototype Object

The Date prototype object:

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

Unless explicitly defined otherwise, the methods of the Date prototype object defined below are not generic and the this value passed to them must be an object that has a [[DateValue]] internal slot that has been initialized to a time value.

22.1.4.1 Date.prototype.constructor

The initial value of Date.prototype.constructor is %Date%.

22.1.4.2 Date.prototype.getDate ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(DateFromTime(LocalTime(tv))).

22.1.4.3 Date.prototype.getDay ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(WeekDay(LocalTime(tv))).

22.1.4.4 Date.prototype.getFullYear ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(YearFromTime(LocalTime(tv))).

22.1.4.5 Date.prototype.getHours ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(HourFromTime(LocalTime(tv))).

22.1.4.6 Date.prototype.getMilliseconds ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MillisecondFromTime(LocalTime(tv))).

22.1.4.7 Date.prototype.getMinutes ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MinuteFromTime(LocalTime(tv))).

22.1.4.8 Date.prototype.getMonth ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MonthFromTime(LocalTime(tv))).

22.1.4.9 Date.prototype.getSeconds ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(SecondFromTime(LocalTime(tv))).

22.1.4.10 Date.prototype.getTime ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Return dateObj.[[DateValue]].

22.1.4.11 Date.prototype.getTimezoneOffset ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return (tv - LocalTime(tv)) / 𝔽(MillisecondsPerMinute).

22.1.4.12 Date.prototype.getUTCDate ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(DateFromTime(tv)).

22.1.4.13 Date.prototype.getUTCDay ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(WeekDay(tv)).

22.1.4.14 Date.prototype.getUTCFullYear ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(YearFromTime(tv)).

22.1.4.15 Date.prototype.getUTCHours ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(HourFromTime(tv)).

22.1.4.16 Date.prototype.getUTCMilliseconds ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MillisecondFromTime(tv)).

22.1.4.17 Date.prototype.getUTCMinutes ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MinuteFromTime(tv)).

22.1.4.18 Date.prototype.getUTCMonth ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(MonthFromTime(tv)).

22.1.4.19 Date.prototype.getUTCSeconds ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return NaN.
  5. Return 𝔽(SecondFromTime(tv)).

22.1.4.20 Date.prototype.setDate ( day )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let dayNumber be ? ToNumber(day).
  5. If tv is NaN, return NaN.
  6. Set tv to LocalTime(tv).
  7. Let newDate be MakeDate(MakeDay(𝔽(YearFromTime(tv)), 𝔽(MonthFromTime(tv)), dayNumber), 𝔽(TimeWithinDay(tv))).
  8. Let u be TimeClip(UTC(newDate)).
  9. Set dateObj.[[DateValue]] to u.
  10. Return u.

22.1.4.21 Date.prototype.setFullYear ( year [ , month [ , day ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let yearNumber be ? ToNumber(year).
  5. If tv is NaN, set tv to +0𝔽; else set tv to LocalTime(tv).
  6. If month is present, let monthNumber be ? ToNumber(month); else let monthNumber be 𝔽(MonthFromTime(tv)).
  7. If day is present, let dayNumber be ? ToNumber(day); else let dayNumber be 𝔽(DateFromTime(tv)).
  8. Let newDate be MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), 𝔽(TimeWithinDay(tv))).
  9. Let u be TimeClip(UTC(newDate)).
  10. Set dateObj.[[DateValue]] to u.
  11. Return u.

The "length" property of this method is 3𝔽.

Note

If month is not present, this method behaves as if month was present with the value getMonth(). If day is not present, it behaves as if day was present with the value getDate().

22.1.4.22 Date.prototype.setHours ( hour [ , minute [ , second [ , millisecond ] ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let hourNumber be ? ToNumber(hour).
  5. If minute is present, let minuteNumber be ? ToNumber(minute).
  6. If second is present, let secondNumber be ? ToNumber(second).
  7. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  8. If tv is NaN, return NaN.
  9. Set tv to LocalTime(tv).
  10. If minute is not present, let minuteNumber be 𝔽(MinuteFromTime(tv)).
  11. If second is not present, let secondNumber be 𝔽(SecondFromTime(tv)).
  12. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  13. Let date be MakeDate(𝔽(Day(tv)), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber)).
  14. Let u be TimeClip(UTC(date)).
  15. Set dateObj.[[DateValue]] to u.
  16. Return u.

The "length" property of this method is 4𝔽.

Note

If minute is not present, this method behaves as if minute was present with the value getMinutes(). If second is not present, it behaves as if second was present with the value getSeconds(). If millisecond is not present, it behaves as if millisecond was present with the value getMilliseconds().

22.1.4.23 Date.prototype.setMilliseconds ( millisecond )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let millisecondNumber be ? ToNumber(millisecond).
  5. If tv is NaN, return NaN.
  6. Set tv to LocalTime(tv).
  7. Let time be MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), 𝔽(SecondFromTime(tv)), millisecondNumber).
  8. Let u be TimeClip(UTC(MakeDate(𝔽(Day(tv)), time))).
  9. Set dateObj.[[DateValue]] to u.
  10. Return u.

22.1.4.24 Date.prototype.setMinutes ( minute [ , second [ , millisecond ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let minuteNumber be ? ToNumber(minute).
  5. If second is present, let secondNumber be ? ToNumber(second).
  6. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  7. If tv is NaN, return NaN.
  8. Set tv to LocalTime(tv).
  9. If second is not present, let secondNumber be 𝔽(SecondFromTime(tv)).
  10. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  11. Let date be MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), minuteNumber, secondNumber, millisecondNumber)).
  12. Let u be TimeClip(UTC(date)).
  13. Set dateObj.[[DateValue]] to u.
  14. Return u.

The "length" property of this method is 3𝔽.

Note

If second is not present, this method behaves as if second was present with the value getSeconds(). If millisecond is not present, this behaves as if millisecond was present with the value getMilliseconds().

22.1.4.25 Date.prototype.setMonth ( month [ , day ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let monthNumber be ? ToNumber(month).
  5. If day is present, let dayNumber be ? ToNumber(day).
  6. If tv is NaN, return NaN.
  7. Set tv to LocalTime(tv).
  8. If day is not present, let dayNumber be 𝔽(DateFromTime(tv)).
  9. Let newDate be MakeDate(MakeDay(𝔽(YearFromTime(tv)), monthNumber, dayNumber), 𝔽(TimeWithinDay(tv))).
  10. Let u be TimeClip(UTC(newDate)).
  11. Set dateObj.[[DateValue]] to u.
  12. Return u.

The "length" property of this method is 2𝔽.

Note

If day is not present, this method behaves as if day was present with the value getDate().

22.1.4.26 Date.prototype.setSeconds ( second [ , millisecond ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let secondNumber be ? ToNumber(second).
  5. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  6. If tv is NaN, return NaN.
  7. Set tv to LocalTime(tv).
  8. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  9. Let date be MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), secondNumber, millisecondNumber)).
  10. Let u be TimeClip(UTC(date)).
  11. Set dateObj.[[DateValue]] to u.
  12. Return u.

The "length" property of this method is 2𝔽.

Note

If millisecond is not present, this method behaves as if millisecond was present with the value getMilliseconds().

22.1.4.27 Date.prototype.setTime ( time )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let t be ? ToNumber(time).
  4. Let v be TimeClip(t).
  5. Set dateObj.[[DateValue]] to v.
  6. Return v.

22.1.4.28 Date.prototype.setUTCDate ( day )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let dayNumber be ? ToNumber(day).
  5. If tv is NaN, return NaN.
  6. Let newDate be MakeDate(MakeDay(𝔽(YearFromTime(tv)), 𝔽(MonthFromTime(tv)), dayNumber), 𝔽(TimeWithinDay(tv))).
  7. Let v be TimeClip(newDate).
  8. Set dateObj.[[DateValue]] to v.
  9. Return v.

22.1.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , day ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, set tv to +0𝔽.
  5. Let yearNumber be ? ToNumber(year).
  6. If month is present, let monthNumber be ? ToNumber(month); else let monthNumber be 𝔽(MonthFromTime(tv)).
  7. If day is present, let dayNumber be ? ToNumber(day); else let dayNumber be 𝔽(DateFromTime(tv)).
  8. Let newDate be MakeDate(MakeDay(yearNumber, monthNumber, dayNumber), 𝔽(TimeWithinDay(tv))).
  9. Let v be TimeClip(newDate).
  10. Set dateObj.[[DateValue]] to v.
  11. Return v.

The "length" property of this method is 3𝔽.

Note

If month is not present, this method behaves as if month was present with the value getUTCMonth(). If day is not present, it behaves as if day was present with the value getUTCDate().

22.1.4.30 Date.prototype.setUTCHours ( hour [ , minute [ , second [ , millisecond ] ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let hourNumber be ? ToNumber(hour).
  5. If minute is present, let minuteNumber be ? ToNumber(minute).
  6. If second is present, let secondNumber be ? ToNumber(second).
  7. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  8. If tv is NaN, return NaN.
  9. If minute is not present, let minuteNumber be 𝔽(MinuteFromTime(tv)).
  10. If second is not present, let secondNumber be 𝔽(SecondFromTime(tv)).
  11. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  12. Let date be MakeDate(𝔽(Day(tv)), MakeTime(hourNumber, minuteNumber, secondNumber, millisecondNumber)).
  13. Let v be TimeClip(date).
  14. Set dateObj.[[DateValue]] to v.
  15. Return v.

The "length" property of this method is 4𝔽.

Note

If minute is not present, this method behaves as if minute was present with the value getUTCMinutes(). If second is not present, it behaves as if second was present with the value getUTCSeconds(). If millisecond is not present, it behaves as if millisecond was present with the value getUTCMilliseconds().

22.1.4.31 Date.prototype.setUTCMilliseconds ( millisecond )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let millisecondNumber be ? ToNumber(millisecond).
  5. If tv is NaN, return NaN.
  6. Let time be MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), 𝔽(SecondFromTime(tv)), millisecondNumber).
  7. Let v be TimeClip(MakeDate(𝔽(Day(tv)), time)).
  8. Set dateObj.[[DateValue]] to v.
  9. Return v.

22.1.4.32 Date.prototype.setUTCMinutes ( minute [ , second [ , millisecond ] ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let minuteNumber be ? ToNumber(minute).
  5. If second is present, let secondNumber be ? ToNumber(second).
  6. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  7. If tv is NaN, return NaN.
  8. If second is not present, let secondNumber be 𝔽(SecondFromTime(tv)).
  9. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  10. Let date be MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), minuteNumber, secondNumber, millisecondNumber)).
  11. Let v be TimeClip(date).
  12. Set dateObj.[[DateValue]] to v.
  13. Return v.

The "length" property of this method is 3𝔽.

Note

If second is not present, this method behaves as if second was present with the value getUTCSeconds(). If millisecond is not present, it behaves as if millisecond was present with the value return by getUTCMilliseconds().

22.1.4.33 Date.prototype.setUTCMonth ( month [ , day ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let monthNumber be ? ToNumber(month).
  5. If day is present, let dayNumber be ? ToNumber(day).
  6. If tv is NaN, return NaN.
  7. If day is not present, let dayNumber be 𝔽(DateFromTime(tv)).
  8. Let newDate be MakeDate(MakeDay(𝔽(YearFromTime(tv)), monthNumber, dayNumber), 𝔽(TimeWithinDay(tv))).
  9. Let v be TimeClip(newDate).
  10. Set dateObj.[[DateValue]] to v.
  11. Return v.

The "length" property of this method is 2𝔽.

Note

If day is not present, this method behaves as if day was present with the value getUTCDate().

22.1.4.34 Date.prototype.setUTCSeconds ( second [ , millisecond ] )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Let secondNumber be ? ToNumber(second).
  5. If millisecond is present, let millisecondNumber be ? ToNumber(millisecond).
  6. If tv is NaN, return NaN.
  7. If millisecond is not present, let millisecondNumber be 𝔽(MillisecondFromTime(tv)).
  8. Let date be MakeDate(𝔽(Day(tv)), MakeTime(𝔽(HourFromTime(tv)), 𝔽(MinuteFromTime(tv)), secondNumber, millisecondNumber)).
  9. Let v be TimeClip(date).
  10. Set dateObj.[[DateValue]] to v.
  11. Return v.

The "length" property of this method is 2𝔽.

Note

If millisecond is not present, this method behaves as if millisecond was present with the value getUTCMilliseconds().

22.1.4.35 Date.prototype.toDateString ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return "Invalid Date".
  5. Let t be LocalTime(tv).
  6. Return DateString(t).

22.1.4.36 Date.prototype.toISOString ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, throw a RangeError exception.
  5. Assert: tv is an integral Number.
  6. If tv corresponds with a year that cannot be represented in the Date Time String Format, throw a RangeError exception.
  7. Return a String representation of tv in the Date Time String Format on the UTC time scale, including all format elements and the UTC offset representation "Z".

22.1.4.37 Date.prototype.toJSON ( key )

This method provides a String representation of a Date for use by JSON.stringify (26.5.4).

It performs the following steps when called:

  1. Let obj be ? ToObject(this value).
  2. Let tv be ? ToPrimitive(obj, number).
  3. If tv is a Number and tv is not finite, return null.
  4. Return ? Invoke(obj, "toISOString").
Note 1

The argument is ignored.

Note 2

This method is intentionally generic; it does not require that its this value be a Date. Therefore, it can be transferred to other kinds of objects for use as a method. However, it does require that any such object have a toISOString method.

22.1.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used:

This method returns a String value. The contents of the String are implementation-defined, but are intended to represent the “date” portion of the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment's current locale.

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

22.1.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used:

This method returns a String value. The contents of the String are implementation-defined, but are intended to represent the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment's current locale.

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

22.1.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used:

This method returns a String value. The contents of the String are implementation-defined, but are intended to represent the “time” portion of the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment's current locale.

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

22.1.4.41 Date.prototype.toString ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. Return ToDateString(tv).
Note 1

For any Date d such that d.[[DateValue]] is evenly divisible by 1000, the result of Date.parse(d.toString()) = d.valueOf(). See 22.1.3.2.

Note 2

This method is not generic; it throws a TypeError exception if its this value is not a Date. Therefore, it cannot be transferred to other kinds of objects for use as a method.

22.1.4.41.1 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 timeString be FormatTimeString(HourFromTime(tv), MinuteFromTime(tv), SecondFromTime(tv), 0, 0).
  2. Return the string-concatenation of timeString, the code unit 0x0020 (SPACE), and "GMT".

22.1.4.41.2 DateString ( tv )

The abstract operation DateString takes argument tv (a Number, but not NaN) and returns a String. It performs the following steps when called:

  1. Let weekday be the Name of the entry in Table 60 whose WeekDay Index = WeekDay(tv).
  2. Let month be the Name of the entry in Table 61 whose Month Index = MonthFromTime(tv).
  3. Let day be ToZeroPaddedDecimalString(DateFromTime(tv), 2).
  4. Let yv be YearFromTime(tv).
  5. If yv ≥ 0, let yearSign be the empty String; else let yearSign be "-".
  6. Let paddedYear be ToZeroPaddedDecimalString(abs(yv), 4).
  7. Return the string-concatenation of weekday, the code unit 0x0020 (SPACE), month, the code unit 0x0020 (SPACE), day, the code unit 0x0020 (SPACE), yearSign, and paddedYear.
Table 60: Names of days of the week
WeekDay Index Name
0 "Sun"
1 "Mon"
2 "Tue"
3 "Wed"
4 "Thu"
5 "Fri"
6 "Sat"
Table 61: Names of months of the year
Month Index Name
0 "Jan"
1 "Feb"
2 "Mar"
3 "Apr"
4 "May"
5 "Jun"
6 "Jul"
7 "Aug"
8 "Sep"
9 "Oct"
10 "Nov"
11 "Dec"

22.1.4.41.3 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. Let offsetMinutes be ! ParseTimeZoneIdentifier(systemTimeZoneIdentifier).[[OffsetMinutes]].
  3. If offsetMinutes is empty, then
    1. Let offsetNanoseconds be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, (tv) × NanosecondsPerMillisecond).
    2. Set offsetMinutes to truncate(offsetNanoseconds / NanosecondsPerMinute).
  4. Let offsetString be FormatOffsetTimeZoneIdentifier(offsetMinutes, unseparated).
  5. 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).
  6. Return the string-concatenation of offsetString and tzName.

22.1.4.41.4 ToDateString ( tv )

The abstract operation ToDateString takes argument tv (an integral Number or NaN) and returns a String. It performs the following steps when called:

  1. If tv is NaN, return "Invalid Date".
  2. Let localTime be LocalTime(tv).
  3. Return the string-concatenation of DateString(localTime), the code unit 0x0020 (SPACE), TimeString(localTime), and TimeZoneString(tv).

22.1.4.42 Date.prototype.toTemporalInstant ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is not an integral Number, throw a RangeError exception.
  5. Let epochNanoseconds be (tv) × NanosecondsPerMillisecond.
  6. Return ! CreateTemporalInstant(epochNanoseconds).

22.1.4.43 Date.prototype.toTimeString ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return "Invalid Date".
  5. Let localTime be LocalTime(tv).
  6. Return the string-concatenation of TimeString(localTime) and TimeZoneString(tv).

22.1.4.44 Date.prototype.toUTCString ( )

This method returns a String value representing the instant in time corresponding to the this value. The format of the String is based upon HTTP-date from RFC 7231, generalized to support the full range of times supported by ECMAScript Dates.

It performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Let tv be dateObj.[[DateValue]].
  4. If tv is NaN, return "Invalid Date".
  5. Let weekday be the Name of the entry in Table 60 whose WeekDay Index = WeekDay(tv).
  6. Let month be the Name of the entry in Table 61 whose Month Index = MonthFromTime(tv).
  7. Let day be ToZeroPaddedDecimalString(DateFromTime(tv), 2).
  8. Let yv be YearFromTime(tv).
  9. If yv ≥ 0, let yearSign be the empty String; else let yearSign be "-".
  10. Let paddedYear be ToZeroPaddedDecimalString(abs(yv), 4).
  11. Return the string-concatenation of weekday, ",", the code unit 0x0020 (SPACE), day, the code unit 0x0020 (SPACE), month, the code unit 0x0020 (SPACE), yearSign, paddedYear, the code unit 0x0020 (SPACE), and TimeString(tv).

22.1.4.45 Date.prototype.valueOf ( )

This method performs the following steps when called:

  1. Let dateObj be the this value.
  2. Perform ? RequireInternalSlot(dateObj, [[DateValue]]).
  3. Return dateObj.[[DateValue]].

22.1.4.46 Date.prototype [ %Symbol.toPrimitive% ] ( hint )

This method is called by ECMAScript language operators to convert a Date to a primitive value. The allowed values for hint are "default", "number", and "string". Dates are unique among built-in ECMAScript object in that they treat "default" as being equivalent to "string", All other built-in ECMAScript objects treat "default" as being equivalent to "number".

It performs the following steps when called:

  1. Let obj be the this value.
  2. If obj is not an Object, throw a TypeError exception.
  3. If hint is either "string" or "default", then
    1. Let tryFirst be string.
  4. Else if hint is "number", then
    1. Let tryFirst be number.
  5. Else,
    1. Throw a TypeError exception.
  6. Return ? OrdinaryToPrimitive(obj, tryFirst).

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

The value of the "name" property of this method is "[Symbol.toPrimitive]".

22.1.5 Properties of Date Instances

Date instances are ordinary objects that inherit properties from the Date prototype object. Date instances also have a [[DateValue]] internal slot. The [[DateValue]] internal slot is the time value represented by this Date.

22.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 0x0021 to 0x007E, described by TimeZoneIdentifier in the grammar below. 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 a String s for which ParseText(s, UTCOffset[~SubMinutePrecision]) returns a Parse Node.

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.

An available time zone identifier is either an available named time zone identifier or an offset time zone identifier.

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 of the formats specified by UTCOffset[~SubMinutePrecision]. 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 in the grammar below, 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 ECMA-402. 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.

Time zone identifiers are described by the grammar in 22.4.1.

22.2.1 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, isoDateTime )

The implementation-defined abstract operation GetNamedTimeZoneEpochNanoseconds takes arguments timeZoneIdentifier (an available named time zone identifier) and isoDateTime (an ISO Date-Time Record) and returns a List of epoch nanoseconds values. Each value in the returned List represents an epoch nanoseconds count that corresponds to the given ISO 8601 calendar date and wall-clock time in the named time zone identified by timeZoneIdentifier.

When the input represents a local time occurring more than once because of a negative time zone transition (e.g. when daylight saving time ends or the time zone offset is decreased due to a time zone rule change), the returned List will have more than one element and will be sorted by ascending numerical value. When the input represents a local time skipped because of a positive time zone transition (e.g. when daylight saving time begins or the time zone offset is increased due to a time zone rule change), the returned List will be empty. Otherwise, the returned List will have one element.

The default implementation of GetNamedTimeZoneEpochNanoseconds, to be used 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. Let epochNanoseconds be GetUTCEpochNanoseconds(isoDateTime).
  3. Return « epochNanoseconds ».
Note

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.

1:30 AM on 5 November 2017 in America/New_York is repeated twice, so GetNamedTimeZoneEpochNanoseconds for that time zone and ISO date-time would return a List of length 2 in which the first element represents 05:30 UTC (corresponding with 01:30 US Eastern Daylight Time at UTC offset -04:00) and the second element represents 06:30 UTC (corresponding with 01:30 US Eastern Standard Time at UTC offset -05:00).

2:30 AM on 12 March 2017 in America/New_York does not exist, so GetNamedTimeZoneEpochNanoseconds for that time zone and ISO date-time would return an empty List.

22.2.2 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZoneOffsetNanoseconds takes arguments timeZoneIdentifier (an available named time zone identifier) and epochNanoseconds (an epoch nanoseconds count) and returns an integer.

The returned integer represents the offset from UTC in nanoseconds of the named time zone identified by timeZoneIdentifier, at the epoch nanoseconds count epochNanoseconds. Time zone offset values may be positive or negative.

The default implementation of GetNamedTimeZoneOffsetNanoseconds, to be used 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 0.

22.2.3 GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZoneNextTransition takes arguments timeZoneIdentifier (an available named time zone identifier) and epochNanoseconds (an epoch nanoseconds count) and returns either an epoch nanoseconds count or null.

The returned value transition is the epoch nanoseconds count that corresponds to the first time zone UTC offset transition strictly after epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which transitionMaxEpochNanoseconds.

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 transition represents the first epoch nanoseconds count where the new UTC offset is used in this time zone, not the last epoch nanoseconds count where the previous UTC offset is used. In other words, GetOffsetNanosecondsFor(timeZone, transition) ≠ GetOffsetNanosecondsFor(timeZone, transition - 1).

If this operation is called multiple times with the same values for timeZoneIdentifier and epochNanoseconds, the result must be the same for each such call for the lifetime of the surrounding agent.

The default 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.

22.2.4 GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds )

The implementation-defined abstract operation GetNamedTimeZonePreviousTransition takes arguments timeZoneIdentifier (an available named time zone identifier) and epochNanoseconds (an epoch nanoseconds count) and returns either an epoch nanoseconds count or null.

The returned value transition is the epoch nanoseconds count that corresponds to the last time zone UTC offset transition strictly before epochNanoseconds in the IANA time zone identified by timeZoneIdentifier. The operation returns null if no such transition exists for which transitionMinEpochNanoseconds.

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 transition represents the first epoch nanoseconds count where the new UTC offset is used in this time zone, not the last epoch nanoseconds count where the previous UTC offset is used. In other words, GetOffsetNanosecondsFor(timeZone, transition) ≠ GetOffsetNanosecondsFor(timeZone, transition - 1).

If this operation is called multiple times with the same values for timeZoneIdentifier and epochNanoseconds, the result must be the same for each such call for the lifetime of the surrounding agent.

The default 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.

22.2.5 Time Zone Identifier Record

A Time Zone Identifier Record is a Record used to describe an available named time zone identifier and its corresponding primary time zone identifier.

Time Zone Identifier Records have the fields listed in Table 62.

Table 62: Time Zone Identifier Record Fields
Field Name Value Meaning
[[Identifier]] a String An available named time zone identifier that is supported by the implementation.
[[PrimaryIdentifier]] a String The primary time zone identifier that [[Identifier]] resolves to.
Note

If [[Identifier]] is a primary time zone identifier, then [[Identifier]] is [[PrimaryIdentifier]].

22.2.6 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 ECMA-402. Otherwise, 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, sorted according to lexicographic code unit order.
  3. Let result be a new empty List.
  4. 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.
  5. Assert: result contains a Time Zone Identifier Record record such that record.[[Identifier]] is "UTC" and record.[[PrimaryIdentifier]] is "UTC".
  6. Return result.
Note

Due to the complexity of supporting the requirements of GetAvailableNamedTimeZoneIdentifier, it is recommended that the result of every call to AvailableNamedTimeZoneIdentifiers be the same for the lifetime of the surrounding agent.

22.2.7 SystemTimeZoneIdentifier ( )

The implementation-defined abstract operation SystemTimeZoneIdentifier takes no arguments and returns an available time zone identifier. It returns a String representing the host environment's current time zone, which is either a 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 primary time zone identifier or offset time zone identifier representing the host environment's current time zone in normalized time zone identifier format.
  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".

22.2.8 Available Named Time Zone Identifier Return Record

An Available Named Time Zone Identifier Return Record is a Record used to memoize returns from the GetAvailableNamedTimeZoneIdentifier abstract operation.

Available Named Time Zone Identifier Return Records have the fields listed in Table 63.

Table 63: Available Named Time Zone Identifier Return Record Fields
Field Name Value Meaning
[[Identifier]] a String A named time zone identifier.
[[Result]] a Time Zone Identifier Record or empty The previously computed result of GetAvailableNamedTimeZoneIdentifier, given the [[Identifier]] field as input.

22.2.9 GetAvailableNamedTimeZoneIdentifier ( timeZoneIdentifier )

The abstract operation GetAvailableNamedTimeZoneIdentifier takes argument timeZoneIdentifier (a named time zone identifier) 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. Let agentRecord be the Agent Record of the surrounding agent.
  2. Let previousReturns be agentRecord.[[GetAvailableNamedTimeZoneIdentifierReturns]].
  3. For each element previousReturn of previousReturns, do
    1. If previousReturn.[[Identifier]] is an ASCII-case-insensitive match for timeZoneIdentifier, then
      1. Return previousReturn.[[Result]].
    2. If previousReturn.[[PrimaryIdentifier]] is an ASCII-case-insensitive match for timeZoneIdentifier, then
      1. Let record be Time Zone Identifier Record { [[Identifier]]: timeZoneIdentifier, [[PrimaryIdentifier]]: timeZoneIdentifier }.
      2. Append Available Named Time Zone Identifier Return Record { [[Identifier]]: timeZoneIdentifier, [[Result]]: record } to previousReturns.
      3. Return record.
  4. For each element record of AvailableNamedTimeZoneIdentifiers(), do
    1. If record.[[Identifier]] is an ASCII-case-insensitive match for timeZoneIdentifier, then
      1. Append Available Named Time Zone Identifier Return Record { [[Identifier]]: timeZoneIdentifier, [[Result]]: record } to previousReturns.
      2. Return record.
  5. Append Available Named Time Zone Identifier Return Record { [[Identifier]]: timeZoneIdentifier, [[Result]]: empty } to previousReturns.
  6. Return empty.
Note

The use of agentRecord.[[GetAvailableNamedTimeZoneIdentifierReturns]] expresses that calling this operation with equivalent time zone identifiers must produce the same results, and that time zone identifiers must not change from primary to non-primary, during the lifetime of the surrounding agent. See the note in AvailableNamedTimeZoneIdentifiers.

22.2.10 ToTemporalTimeZoneIdentifier ( temporalTimeZoneLike )

The abstract operation ToTemporalTimeZoneIdentifier takes argument temporalTimeZoneLike (an ECMAScript language value) and returns either a normal completion containing an available time zone identifier or a throw completion. It attempts to derive an available time zone identifier from temporalTimeZoneLike. It performs the following steps when called:

  1. If temporalTimeZoneLike is an Object and temporalTimeZoneLike has an [[InitializedTemporalZonedDateTime]] internal slot, return temporalTimeZoneLike.[[TimeZone]].
  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. Assert: name is not empty.
  8. Let timeZoneIdentifierRecord be GetAvailableNamedTimeZoneIdentifier(name).
  9. If timeZoneIdentifierRecord is empty, throw a RangeError exception.
  10. Return timeZoneIdentifierRecord.[[Identifier]].

22.2.11 GetOffsetNanosecondsFor ( timeZone, epochNanoseconds )

The abstract operation GetOffsetNanosecondsFor takes arguments timeZone (an available time zone identifier) and epochNanoseconds (an epoch nanoseconds count) and returns an integer in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive). It determines the UTC offset in nanoseconds of an epoch nanoseconds count. It performs the following steps when called:

  1. Let parseResult be ! ParseTimeZoneIdentifier(timeZone).
  2. If parseResult.[[OffsetMinutes]] is not empty, return parseResult.[[OffsetMinutes]] × NanosecondsPerMinute.
  3. Assert: parseResult.[[Name]] is not empty.
  4. Return GetNamedTimeZoneOffsetNanoseconds(parseResult.[[Name]], epochNanoseconds).

22.2.12 GetISODateTimeFor ( timeZone, epochNanoseconds )

The abstract operation GetISODateTimeFor takes arguments timeZone (an available time zone identifier) and epochNanoseconds (an epoch nanoseconds count) and returns an ISO Date-Time Record. It returns the components of a wall-clock time in the given timeZone, corresponding to the given epoch nanoseconds count. It performs the following steps when called:

  1. Assert: IsWithinEpochNanosecondsInterval(epochNanoseconds) is true.
  2. Let offsetNanoseconds be GetOffsetNanosecondsFor(timeZone, epochNanoseconds).
  3. Let remainderNanoseconds be epochNanoseconds modulo NanosecondsPerMillisecond.
  4. Let epochMilliseconds be (epochNanoseconds - remainderNanoseconds) / NanosecondsPerMillisecond.
  5. Let year be YearFromTime(𝔽(epochMilliseconds)).
  6. Let month be MonthFromTime(𝔽(epochMilliseconds)) + 1.
  7. Let day be DateFromTime(𝔽(epochMilliseconds)).
  8. Let hour be HourFromTime(𝔽(epochMilliseconds)).
  9. Let minute be MinuteFromTime(𝔽(epochMilliseconds)).
  10. Let second be SecondFromTime(𝔽(epochMilliseconds)).
  11. Let millisecond be MillisecondFromTime(𝔽(epochMilliseconds)).
  12. Let microsecond be floor(remainderNanoseconds / 1000).
  13. Assert: microsecond < 1000.
  14. Let nanosecond be remainderNanoseconds modulo 1000.
  15. Return BalanceISODateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond + offsetNanoseconds).

22.2.13 GetEpochNanosecondsFor ( timeZone, isoDateTime, disambiguation )

The abstract operation GetEpochNanosecondsFor takes arguments timeZone (an available time zone identifier), isoDateTime (an ISO Date-Time Record), and disambiguation ("compatible", "earlier", "later", or "reject") and returns either a normal completion containing an epoch nanoseconds count or a throw completion.

It performs the following steps when called:

  1. Let possibleEpochNanoseconds be ? GetPossibleEpochNanoseconds(timeZone, isoDateTime).
  2. Return ? DisambiguatePossibleEpochNanoseconds(possibleEpochNanoseconds, timeZone, isoDateTime, disambiguation).

22.2.14 DisambiguatePossibleEpochNanoseconds ( possibleEpochNanoseconds, timeZone, isoDateTime, disambiguation )

The abstract operation DisambiguatePossibleEpochNanoseconds takes arguments possibleEpochNanoseconds (a List of epoch nanoseconds counts), timeZone (an available time zone identifier), isoDateTime (an ISO Date-Time Record), and disambiguation ("compatible", "earlier", "later", or "reject") and returns either a normal completion containing an epoch nanoseconds count or a throw completion. It chooses from a List of possible epoch nanoseconds counts the one indicated by the disambiguation parameter. It performs the following steps when called:

  1. Let count be the number of elements in possibleEpochNanoseconds.
  2. If count = 1, return the sole element of possibleEpochNanoseconds.
  3. If count ≠ 0, then
    1. If disambiguation is either "earlier" or "compatible", return possibleEpochNanoseconds[0].
    2. If disambiguation is "later", return possibleEpochNanoseconds[count - 1].
    3. Assert: disambiguation is "reject".
    4. Throw a RangeError exception.
  4. Assert: count = 0.
  5. If disambiguation is "reject", throw a RangeError exception.
  6. Let before be the latest possible ISO Date-Time Record which is earlier than isoDateTime and for which ! GetPossibleEpochNanoseconds(timeZone, before) is not empty.
  7. Let after be the earliest possible ISO Date-Time Record which is later than isoDateTime and for which ! GetPossibleEpochNanoseconds(timeZone, after) is not empty.
  8. Let beforePossible be ! GetPossibleEpochNanoseconds(timeZone, before).
  9. Assert: The number of elements in beforePossible = 1.
  10. Let afterPossible be ! GetPossibleEpochNanoseconds(timeZone, after).
  11. Assert: The number of elements in afterPossible = 1.
  12. Let offsetBefore be GetOffsetNanosecondsFor(timeZone, the sole element of beforePossible).
  13. Let offsetAfter be GetOffsetNanosecondsFor(timeZone, the sole element of afterPossible).
  14. Let nanoseconds be offsetAfter - offsetBefore.
  15. Assert: nanoseconds is in the inclusive interval from -NanosecondsPerDay to NanosecondsPerDay.
  16. If disambiguation is "earlier", then
    1. Let timeDuration be ! TimeDurationFromComponents(0, 0, 0, 0, 0, -nanoseconds).
    2. Let earlierTime be AddTime(isoDateTime.[[Time]], timeDuration).
    3. Let earlierDate be AddDaysToISODate(isoDateTime.[[ISODate]], earlierTime.[[Days]]).
    4. Let earlierDateTime be the ISO Date-Time Record { [[ISODate]]: earlierDate, [[Time]]: earlierTime }.
    5. Set possibleEpochNanoseconds to ? GetPossibleEpochNanoseconds(timeZone, earlierDateTime).
    6. Assert: possibleEpochNanoseconds is not empty.
    7. Return possibleEpochNanoseconds[0].
  17. Assert: disambiguation is "compatible" or "later".
  18. Let timeDuration be ! TimeDurationFromComponents(0, 0, 0, 0, 0, nanoseconds).
  19. Let laterTime be AddTime(isoDateTime.[[Time]], timeDuration).
  20. Let laterDate be AddDaysToISODate(isoDateTime.[[ISODate]], laterTime.[[Days]]).
  21. Let laterDateTime be the ISO Date-Time Record { [[ISODate]]: laterDate, [[Time]]: laterTime }.
  22. Set possibleEpochNanoseconds to ? GetPossibleEpochNanoseconds(timeZone, laterDateTime).
  23. Set count to the number of elements in possibleEpochNanoseconds.
  24. Assert: count ≠ 0.
  25. Return possibleEpochNanoseconds[count - 1].

22.2.15 GetPossibleEpochNanoseconds ( timeZone, isoDateTime )

The abstract operation GetPossibleEpochNanoseconds takes arguments timeZone (an available time zone identifier) and isoDateTime (an ISO Date-Time Record) and returns either a normal completion containing a List of epoch nanoseconds counts or a throw completion. It determines the possible epoch nanoseconds counts that may correspond to isoDateTime. It performs the following steps when called:

  1. Let parseResult be ! ParseTimeZoneIdentifier(timeZone).
  2. If parseResult.[[OffsetMinutes]] is not empty, then
    1. Let balanced be BalanceISODateTime(isoDateTime.[[ISODate]].[[Year]], isoDateTime.[[ISODate]].[[Month]], isoDateTime.[[ISODate]].[[Day]], isoDateTime.[[Time]].[[Hour]], isoDateTime.[[Time]].[[Minute]] - parseResult.[[OffsetMinutes]], isoDateTime.[[Time]].[[Second]], isoDateTime.[[Time]].[[Millisecond]], isoDateTime.[[Time]].[[Microsecond]], isoDateTime.[[Time]].[[Nanosecond]]).
    2. Perform ? ValidateISODaysRange(balanced.[[ISODate]]).
    3. Let epochNanoseconds be GetUTCEpochNanoseconds(balanced).
    4. Let possibleEpochNanoseconds be « epochNanoseconds ».
  3. Else,
    1. Assert: parseResult.[[Name]] is not empty.
    2. Let possibleEpochNanoseconds be GetNamedTimeZoneEpochNanoseconds(parseResult.[[Name]], isoDateTime).
  4. For each value epochNanoseconds of possibleEpochNanoseconds, do
    1. If IsWithinEpochNanosecondsInterval(epochNanoseconds) is false, throw a RangeError exception.
  5. Return possibleEpochNanoseconds.

22.2.16 GetStartOfDay ( timeZone, isoDate )

The abstract operation GetStartOfDay takes arguments timeZone (an available time zone identifier) and isoDate (an ISO Date Record) and returns either a normal completion containing an epoch nanoseconds count or a throw completion. It determines the epoch nanoseconds count that corresponds to the first valid wall-clock time in the calendar date isoDate in timeZone. It performs the following steps when called:

  1. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: MidnightTimeRecord() }.
  2. Let possibleEpochNanoseconds be ? GetPossibleEpochNanoseconds(timeZone, isoDateTime).
  3. If possibleEpochNanoseconds is not empty, return possibleEpochNanoseconds[0].
  4. Assert: timeZone is a named time zone identifier.
  5. Let wallClockAdvance be 1.
  6. Repeat,
    1. Let timeAfter be AddTime(isoDateTime.[[Time]], wallClockAdvance).
    2. Let isoDateAfter be AddDaysToISODate(isoDate, timeAfter.[[Days]]).
    3. Let isoDateTimeAfter be the ISO Date-Time Record { [[ISODate]]: isoDateAfter, [[Time]]: timeAfter }.
    4. Let possibleEpochNanosecondsAfter be GetNamedTimeZoneEpochNanoseconds(timeZone, isoDateTimeAfter).
    5. If possibleEpochNanosecondsAfter is not empty, then
      1. Assert: The number of elements in possibleEpochNanosecondsAfter = 1.
      2. Let result be the sole element of possibleEpochNanosecondsAfter.
      3. If IsWithinEpochNanosecondsInterval(result) is false, throw a RangeError exception.
      4. Return result.
    6. Set wallClockAdvance to wallClockAdvance + 1.

22.2.17 TimeZoneEquals ( xTimeZone, yTimeZone )

The abstract operation TimeZoneEquals takes arguments xTimeZone (an available time zone identifier) and yTimeZone (an available time zone identifier) and returns a Boolean. It returns true if its arguments represent time zones using the same identifier. It performs the following steps when called:

  1. If xTimeZone is yTimeZone, return true.
  2. If xTimeZone is a named time zone identifier and yTimeZone is a named time zone identifier, then
    1. Let xRecord be GetAvailableNamedTimeZoneIdentifier(xTimeZone).
    2. Let yRecord be GetAvailableNamedTimeZoneIdentifier(yTimeZone).
    3. Assert: xRecord is not empty.
    4. Assert: yRecord is not empty.
    5. If xRecord.[[PrimaryIdentifier]] is yRecord.[[PrimaryIdentifier]], return true.
  3. Assert: If xTimeZone and yTimeZone are both offset time zone identifiers, they do not represent the same number of offset minutes.
  4. Return false.

22.3 Definitions and Abstract Operations for Temporal Objects

22.3.1 Calendar Date Records and Calendar Fields Records

22.3.1.1 Calendar Date Records

A Calendar Date Record is a Record used to represent a date that exists in a calendar, which may or may not be the ISO 8601 calendar. Calendar Date Records are produced by the abstract operation CalendarISOToDate.

Calendar Date Records have the fields listed in Table 64.

Table 64: Calendar Date Record Fields
Field Name Value Meaning
[[Era]] a String or empty A lowercase String representing the date's era, or empty for calendars that do not have eras.
[[EraYear]] an integer or empty The ordinal position of the date's year within its era, or empty for calendars that do not have eras. Note 1
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).
[[Year]] an integer The date's year relative to the first day of a calendar-specific “epoch year”. Note 2
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.
[[Month]] a positive integer The 1-based ordinal position of the date's month within its year. Note 3
When the number of months in a year of the calendar is variable, this field can contain different values 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.
[[MonthCode]] a month code The month code of the date's month.
[[Day]] a positive integer The 1-based ordinal position of the date's day within its month.
[[DayOfWeek]] a positive integer The day of the week corresponding to the date. The value should be 1-based, where 1 is the day corresponding to Monday in the given calendar.
[[DayOfYear]] a positive integer The 1-based ordinal position of the date's day within its year.
[[WeekOfYear]] a Year-Week Record

The Year-Week Record corresponding to the date.

[[DaysInWeek]] a positive integer The number of days in the date's week.
[[DaysInMonth]] a positive integer The number of days in the date's month.
[[DaysInYear]] a positive integer The number of days in the date's year.
[[MonthsInYear]] a positive integer The number of months in the date's year.
[[InLeapYear]] a Boolean true if the date falls within a leap year, and false otherwise. Note 4
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).

22.3.1.2 Calendar Fields Records

A Calendar Fields Record is a Record used to represent full or partial input for a calendar date in a non-ISO 8601 calendar. Calendar Fields Records are produced by several abstract operations, such as ISODateToFields and PrepareCalendarFields, and are passed to abstract operations such as CalendarDateFromFields.

Many of the fields in a Calendar Fields Record have the same meaning as the fields of the same name in Calendar Date Records, but each field in a Calendar Fields Record may additionally be empty to indicate partial input.

Each field has a corresponding calendar property key, which is one of "era", "eraYear", "year", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "offset", or "timeZone". These property keys correspond to the properties that are read from user input objects to populate the field, in methods such as Temporal.PlainDate.prototype.with (22.11.3.23).

Calendar Fields Records have the fields listed in Table 65.

Table 65: Calendar Fields Record Fields
Field Name Value Meaning
[[Era]] a String or empty A lowercase String representing the era.
[[EraYear]] an integer or empty The ordinal position of the year within the era.
[[Year]] an integer or empty The year relative to the first day of a calendar-specific “epoch year”.
[[Month]] a positive integer or empty The 1-based ordinal position of the month within the year.
[[MonthCode]] a month code or empty The month code of the month.
[[Day]] a positive integer or empty The 1-based ordinal position of the day within the month.
[[Hour]] an integer or empty The number of the hour within the day.
[[Minute]] an integer or empty The number of the minute within the hour.
[[Second]] an integer or empty The number of the second within the minute.
[[Millisecond]] an integer or empty The number of the millisecond within the second.
[[Microsecond]] an integer or empty The number of the microsecond within the millisecond.
[[Nanosecond]] an integer or empty The number of the nanosecond within the microsecond.
[[OffsetString]] a String or empty A string of the form ±HH:MM[:SS.SSSSSSSSS] that can be parsed by ParseDateTimeUTCOffset.
[[TimeZone]] a String or empty An available time zone identifier.

22.3.1.3 PrepareCalendarFields ( calendar, fields, calendarFields, nonCalendarFields, requiredFields )

The abstract operation PrepareCalendarFields takes arguments calendar (a known calendar type), fields (an Object), calendarFields (date-fields, year-month-fields, only-day, or only-year), nonCalendarFields (time-fields, time-fields-with-offset, time-fields-with-time-zone-and-offset, or no-non-calendar-fields), and requiredFields (partial, time-zone, or no-required-fields) and returns either a normal completion containing a Calendar Fields Record, or a throw completion. It returns the result of reading from fields all of the property names corresponding to calendarFields and nonCalendarFields, plus any extra fields required by the calendar. The returned Record has a non-empty value for each property corresponding to calendarFields and nonCalendarFields that has a non-undefined value on fields, which is 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 time-zone, this operation throws if fields's "timeZone" property is absent or undefined. It performs the following steps when called:

  1. If calendarFields is date-fields, then
    1. Let propertyNames be « "day", "month", "monthCode", "year" ».
  2. Else if calendarFields is year-month-fields, then
    1. Let propertyNames be « "month", "monthCode", "year" ».
  3. Else if calendarFields is only-day, then
    1. Let propertyNames be « "day" ».
  4. Else,
    1. Assert: calendarFields is only-year.
    2. Let propertyNames be « "year" ».
  5. Let extraFieldNames be CalendarExtraFields(calendar, propertyNames).
  6. If nonCalendarFields is not no-non-calendar-fields, then
    1. Set propertyNames to the list-concatenation of propertyNames and « "hour", "microsecond", "millisecond", "minute", "nanosecond", "second" ».
  7. If nonCalendarFields is either time-fields-with-offset or time-fields-with-time-zone-and-offset, append "offset" to propertyNames.
  8. If nonCalendarFields is time-fields-with-time-zone-and-offset, append "timeZone" to propertyNames.
  9. Set propertyNames to the list-concatenation of propertyNames and extraFieldNames.
  10. Assert: propertyNames contains no duplicate elements.
  11. Let result be the Calendar Fields Record { [[Era]]: empty, [[EraYear]]: empty, [[Year]]: empty, [[Month]]: empty, [[MonthCode]]: empty, [[Day]]: empty, [[Hour]]: empty, [[Minute]]: empty, [[Second]]: empty, [[Millisecond]]: empty, [[Microsecond]]: empty, [[Nanosecond]]: empty, [[OffsetString]]: empty, [[TimeZone]]: empty  }.
  12. If requiredFields is not partial, then
    1. Set result.[[Hour]] to 0.
    2. Set result.[[Minute]] to 0.
    3. Set result.[[Second]] to 0.
    4. Set result.[[Millisecond]] to 0.
    5. Set result.[[Microsecond]] to 0.
    6. Set result.[[Nanosecond]] to 0.
  13. Let anyPresent be false.
  14. Sort propertyNames according to lexicographic code unit order.
  15. For each property name property of propertyNames, do
    1. Let value be ? Get(fields, property).
    2. If value is undefined, then
      1. If requiredFields is time-zone and property is "timeZone", throw a TypeError exception.
    3. Else,
      1. Set anyPresent to true.
      2. If property is "era", then
        1. Set result.[[Era]] to ? ToString(value).
      3. Else if property is "eraYear", then
        1. Set result.[[EraYear]] to ? SnapToInteger(value, truncate).
      4. Else if property is "year", then
        1. Set result.[[Year]] to ? SnapToInteger(value, truncate).
      5. Else if property is "month", then
        1. Set result.[[Month]] to ? SnapToInteger(value, truncate, 1).
      6. Else if property is "monthCode", then
        1. Let parsed be ? ParseMonthCode(value).
        2. Set result.[[MonthCode]] to CreateMonthCode(parsed.[[MonthNumber]], parsed.[[IsLeapMonth]]).
      7. Else if property is "day", then
        1. Set result.[[Day]] to ? SnapToInteger(value, truncate, 1).
      8. Else if property is "hour", then
        1. Set result.[[Hour]] to ? SnapToInteger(value, truncate).
      9. Else if property is "minute", then
        1. Set result.[[Minute]] to ? SnapToInteger(value, truncate).
      10. Else if property is "second", then
        1. Set result.[[Second]] to ? SnapToInteger(value, truncate).
      11. Else if property is "millisecond", then
        1. Set result.[[Millisecond]] to ? SnapToInteger(value, truncate).
      12. Else if property is "microsecond", then
        1. Set result.[[Microsecond]] to ? SnapToInteger(value, truncate).
      13. Else if property is "nanosecond", then
        1. Set result.[[Nanosecond]] to ? SnapToInteger(value, truncate).
      14. Else if property is "timeZone", then
        1. Set result.[[TimeZone]] to ? ToTemporalTimeZoneIdentifier(value).
      15. Else,
        1. Assert: property is "offset".
        2. Set value be ? ToPrimitive(value, string).
        3. If value is not a String, throw a TypeError exception.
        4. Perform ? ParseDateTimeUTCOffset(value).
        5. Set result.[[OffsetString]] to value.
  16. If requiredFields is partial and anyPresent is false, throw a TypeError exception.
  17. Return result.

22.3.1.4 CalendarMergeFields ( calendar, fields, additionalFields )

The abstract operation CalendarMergeFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and additionalFields (a Calendar Fields Record) and returns a Calendar Fields Record. It merges the properties of fields and additionalFields. It performs the following steps when called:

  1. Let overriddenKeys be CalendarFieldKeysToIgnore(calendar, additionalFields).
  2. Let merged be the Calendar Fields Record { [[Era]]: empty, [[EraYear]]: empty, [[Year]]: empty, [[Month]]: empty, [[MonthCode]]: empty, [[Day]]: empty, [[Hour]]: empty, [[Minute]]: empty, [[Second]]: empty, [[Millisecond]]: empty, [[Microsecond]]: empty, [[Nanosecond]]: empty, [[OffsetString]]: empty, [[TimeZone]]: empty  }.
  3. If fields.[[Era]] is not empty and overriddenKeys does not contain "era", set merged.[[Era]] to fields.[[Era]].
  4. If additionalFields.[[Era]] is not empty, set merged.[[Era]] to additionalFields.[[Era]].
  5. If fields.[[EraYear]] is not empty and overriddenKeys does not contain "eraYear", set merged.[[EraYear]] to fields.[[EraYear]].
  6. If additionalFields.[[EraYear]] is not empty, set merged.[[EraYear]] to additionalFields.[[EraYear]].
  7. If fields.[[Year]] is not empty and overriddenKeys does not contain "year", set merged.[[Year]] to fields.[[Year]].
  8. If additionalFields.[[Year]] is not empty, set merged.[[Year]] to additionalFields.[[Year]].
  9. If fields.[[Month]] is not empty and overriddenKeys does not contain "month", set merged.[[Month]] to fields.[[Month]].
  10. If additionalFields.[[Month]] is not empty, set merged.[[Month]] to additionalFields.[[Month]].
  11. If fields.[[MonthCode]] is not empty and overriddenKeys does not contain "monthCode", set merged.[[MonthCode]] to fields.[[MonthCode]].
  12. If additionalFields.[[MonthCode]] is not empty, set merged.[[MonthCode]] to additionalFields.[[MonthCode]].
  13. If fields.[[Day]] is not empty and overriddenKeys does not contain "day", set merged.[[Day]] to fields.[[Day]].
  14. If additionalFields.[[Day]] is not empty, set merged.[[Day]] to additionalFields.[[Day]].
  15. If fields.[[Hour]] is not empty and overriddenKeys does not contain "hour", set merged.[[Hour]] to fields.[[Hour]].
  16. If additionalFields.[[Hour]] is not empty, set merged.[[Hour]] to additionalFields.[[Hour]].
  17. If fields.[[Minute]] is not empty and overriddenKeys does not contain "minute", set merged.[[Minute]] to fields.[[Minute]].
  18. If additionalFields.[[Minute]] is not empty, set merged.[[Minute]] to additionalFields.[[Minute]].
  19. If fields.[[Second]] is not empty and overriddenKeys does not contain "second", set merged.[[Second]] to fields.[[Second]].
  20. If additionalFields.[[Second]] is not empty, set merged.[[Second]] to additionalFields.[[Second]].
  21. If fields.[[Millisecond]] is not empty and overriddenKeys does not contain "millisecond", set merged.[[Millisecond]] to fields.[[Millisecond]].
  22. If additionalFields.[[Millisecond]] is not empty, set merged.[[Millisecond]] to additionalFields.[[Millisecond]].
  23. If fields.[[Microsecond]] is not empty and overriddenKeys does not contain "microsecond", set merged.[[Microsecond]] to fields.[[Microsecond]].
  24. If additionalFields.[[Microsecond]] is not empty, set merged.[[Microsecond]] to additionalFields.[[Microsecond]].
  25. If fields.[[Nanosecond]] is not empty and overriddenKeys does not contain "nanosecond", set merged.[[Nanosecond]] to fields.[[Nanosecond]].
  26. If additionalFields.[[Nanosecond]] is not empty, set merged.[[Nanosecond]] to additionalFields.[[Nanosecond]].
  27. If fields.[[OffsetString]] is not empty and overriddenKeys does not contain "offset", set merged.[[OffsetString]] to fields.[[OffsetString]].
  28. If additionalFields.[[OffsetString]] is not empty, set merged.[[OffsetString]] to additionalFields.[[OffsetString]].
  29. If fields.[[TimeZone]] is not empty and overriddenKeys does not contain "timeZone", set merged.[[TimeZone]] to fields.[[TimeZone]].
  30. If additionalFields.[[TimeZone]] is not empty, set merged.[[TimeZone]] to additionalFields.[[TimeZone]].
  31. Return merged.

22.3.2 Calendar Identifiers

At a minimum, ECMAScript implementations must support a calendar named "iso8601", representing the ISO 8601 calendar. In addition, implementations may support any number of other calendars corresponding with those of the Unicode Common Locale Data Repository (CLDR).

ECMAScript implementations identify calendars using a calendar type that is a Unicode Calendar Identifier as defined in Unicode Technical Standard #35 Part 1 Core, Key and Type Definitions. Their canonical form is a String matched by AnnotationValue.

A known calendar type is a calendar type in canonical form that is supported by the implementation.

22.3.2.1 AvailableCalendars ( )

The implementation-defined abstract operation AvailableCalendars takes no arguments and returns a List of calendar types. The returned List is sorted according to lexicographic code unit order, and contains unique calendar types in canonical form (22.3.2) identifying the calendars for which the implementation provides the functionality of Temporal objects, including any aliases.

The default implementation of AvailableCalendars, to be used for ECMAScript implementations that do not support any calendar types other than "iso8601", performs the following steps when called:

  1. Return « "iso8601" ».

22.3.2.2 CanonicalizeCalendar ( id )

The abstract operation CanonicalizeCalendar takes argument id (a String) and returns either a normal completion containing a known calendar type, or a throw completion. It returns the known calendar type denoted by id, or throws an exception if the implementation does not support that calendar.

The default implementation of CanonicalizeCalendar, to be used for ECMAScript implementations that do not support any calendar types other than "iso8601", performs the following steps when called:

  1. If the ASCII-lowercase of id is not "iso8601", throw a RangeError exception.
  2. Return "iso8601".

22.3.2.3 ToTemporalCalendarIdentifier ( temporalCalendarLike )

The abstract operation ToTemporalCalendarIdentifier takes argument temporalCalendarLike (an ECMAScript language value) and returns either a normal completion containing a known calendar type or a throw completion. It attempts to derive a known calendar type from temporalCalendarLike, and returns that value if found or throws an exception if not. It performs the following steps when called:

  1. If temporalCalendarLike is an Object and temporalCalendarLike has a [[Calendar]] internal slot, return temporalCalendarLike.[[Calendar]].
  2. If temporalCalendarLike is not a String, throw a TypeError exception.
  3. Let identifier be ? ParseTemporalCalendarString(temporalCalendarLike).
  4. Return ? CanonicalizeCalendar(identifier).

22.3.2.4 GetTemporalCalendarIdentifierWithISODefault ( temporalObjectLike )

The abstract operation GetTemporalCalendarIdentifierWithISODefault takes argument temporalObjectLike (an Object) and returns either a normal completion containing a known calendar type or a throw completion. It looks for a calendar property on temporalObjectLike and converts its value into a known calendar type. If no such property is present, the built-in ISO 8601 calendar is returned. It performs the following steps when called:

  1. If temporalObjectLike has a [[Calendar]] internal slot, return temporalObjectLike.[[Calendar]].
  2. Let calendarLike be ? Get(temporalObjectLike, "calendar").
  3. If calendarLike is undefined, return "iso8601".
  4. Return ? ToTemporalCalendarIdentifier(calendarLike).

22.3.3 Calendar Operations

22.3.3.1 CalendarDateAdd ( calendar, isoDate, duration, overflow )

The abstract operation CalendarDateAdd takes arguments calendar (a known calendar type), isoDate (an ISO Date Record), duration (a Date Duration Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It adds dateDuration to isoDate using the years, months, and weeks reckoning of calendar. If addition of years or months results in a nonexistent date, either the nonexistent date will be coerced to an existing date or the operation will throw, depending on the value of overflow. It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. Let intermediate be BalanceISOYearMonth(isoDate.[[Year]] + duration.[[Years]], isoDate.[[Month]] + duration.[[Months]]).
    2. Set intermediate to ? RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], isoDate.[[Day]], overflow).
    3. Let days be duration.[[Days]] + 7 × duration.[[Weeks]].
    4. Let result be AddDaysToISODate(intermediate, days).
  2. Else,
    1. Let result be ? NonISODateAdd(calendar, isoDate, duration, overflow).
  3. If ISODateWithinLimits(result) is false, throw a RangeError exception.
  4. Return result.

22.3.3.2 NonISODateAdd ( calendar, isoDate, duration, overflow )

The implementation-defined abstract operation NonISODateAdd takes arguments calendar (a known calendar type but not "iso8601"), isoDate (an ISO Date Record), duration (a Date Duration Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. The operation performs implementation-defined processing to add duration to date in the context of the calendar identified by calendar and returns the corresponding day, month, and year of the result in the ISO 8601 calendar as an ISO Date Record. It may throw a RangeError exception if overflow is "reject" and the resulting month or day would not form a date that exists in the calendar identified by calendar.

22.3.3.3 CalendarDateUntil ( calendar, isoDateFrom, isoDateTo, largestUnit )

The abstract operation CalendarDateUntil takes arguments calendar (a known calendar type), isoDateFrom (an ISO Date Record), isoDateTo (an ISO Date Record), and largestUnit (a date unit) and returns a Date Duration Record. It determines the difference between the dates isoDateFrom and isoDateTo using the years, months, and weeks reckoning of calendar. No fields larger than largestUnit will be non-zero in the resulting Date Duration Record. It performs the following steps when called:

  1. Let sign be CompareISODate(isoDateFrom, isoDateTo).
  2. If sign = 0, return ZeroDateDuration().
  3. If calendar is "iso8601", then
    1. Set sign to -sign.
    2. Let years be 0.
    3. If largestUnit is "year", then
      1. Let candidateYears be sign.
      2. Repeat, while ISODateSurpasses(sign, isoDateFrom, candidateYears, 0, 0, 0, isoDateTo) is false,
        1. Set years to candidateYears.
        2. Set candidateYears to candidateYears + sign.
    4. Let months be 0.
    5. If largestUnit is either "year" or "month", then
      1. Let candidateMonths be sign.
      2. Repeat, while ISODateSurpasses(sign, isoDateFrom, years, candidateMonths, 0, 0, isoDateTo) is false,
        1. Set months to candidateMonths.
        2. Set candidateMonths to candidateMonths + sign.
    6. Let weeks be 0.
    7. If largestUnit is "week", then
      1. Let candidateWeeks be sign.
      2. Repeat, while ISODateSurpasses(sign, isoDateFrom, years, months, candidateWeeks, 0, isoDateTo) is false,
        1. Set weeks to candidateWeeks.
        2. Set candidateWeeks to candidateWeeks + sign.
    8. Let days be 0.
    9. Let candidateDays be sign.
    10. Repeat, while ISODateSurpasses(sign, isoDateFrom, years, months, weeks, candidateDays, isoDateTo) is false,
      1. Set days to candidateDays.
      2. Set candidateDays to candidateDays + sign.
    11. Return ! CreateDateDurationRecord(years, months, weeks, days).
  4. Return NonISODateUntil(calendar, isoDateFrom, isoDateTo, largestUnit).

22.3.3.4 NonISODateUntil ( calendar, isoDateFrom, isoDateTo, largestUnit )

The implementation-defined abstract operation NonISODateUntil takes arguments calendar (a known calendar type but not "iso8601"), isoDateFrom (an ISO Date Record), isoDateTo (an ISO Date Record), and largestUnit (a date unit) and returns a Date Duration Record. It performs implementation-defined processing to determine the difference between the dates isoDateFrom and isoDateTo using the years, months, and weeks reckoning of calendar.

In the resulting Date Duration Record r, r.[[Years]] = 0 if largestUnit is one of "months", "weeks", or "days". Likewise, r.[[Months]] = 0 if largestUnit is either "weeks" or "days", and r.[[Weeks]] = 0 if largestUnit is "days".

22.3.3.5 CalendarDateToISO ( calendar, fields, overflow )

The abstract operation CalendarDateToISO takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It returns an ISO Date Record representing a date in the ISO 8601 calendar that, when converted to calendar, corresponds to the date of fields. The fields argument represents a date in the calendar identified by calendar, though it may include additional fields. If an ISO Date Record cannot be created from fields because its date does not exist, the values from fields are clamped to their respective valid ranges if overflow is "constrain", as in RegulateISODate; if it is "reject", an exception is thrown. It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. Assert: fields.[[Year]], fields.[[Month]], and fields.[[Day]] are not empty.
    2. Return ? RegulateISODate(fields.[[Year]], fields.[[Month]], fields.[[Day]], overflow).
  2. Return ? NonISOCalendarDateToISO(calendar, fields, overflow).

22.3.3.6 NonISOCalendarDateToISO ( calendar, fields, overflow )

The implementation-defined abstract operation NonISOCalendarDateToISO takes arguments calendar (a known calendar type but not "iso8601"), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It performs implementation-defined processing to return an ISO Date Record representing a date in the ISO 8601 calendar that, when converted to calendar, corresponds to the date of fields. The fields argument represents a date in the calendar identified by calendar, though it may include additional fields. If an ISO Date Record cannot be created from fields because its date does not exist, the values from fields are clamped to their respective valid ranges if overflow is "constrain"; if it is "reject", an exception is thrown.

Clamping a nonexistent date to the correct range when overflow is "constrain" is a behaviour specific to each calendar, but all 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.

22.3.3.7 CalendarMonthDayToISOReferenceDate ( calendar, fields, overflow )

The abstract operation CalendarMonthDayToISOReferenceDate takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It returns an ISO Date Record representing a reference date in the ISO 8601 calendar that, when converted to calendar, corresponds to the month and day of fields. The fields argument represents a month and day in the calendar identified by calendar, though it may include additional fields. The month and day are checked using the year in fields, if present; the year is used only for this check and is otherwise ignored in favour of a reference year. For the ISO 8601 calendar, the reference year is always 1972. For other calendars, see NonISOMonthDayToISOReferenceDate. If an ISO Date Record cannot be created from fields because its date does not exist, the values from fields are clamped to their respective valid ranges if overflow is "constrain"; if it is "reject", an exception is thrown. It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. Assert: fields.[[Month]] and fields.[[Day]] are not empty.
    2. Let referenceISOYear be 1972 (the first ISO 8601 leap year after the epoch).
    3. If fields.[[Year]] is empty, let year be referenceISOYear; else let year be fields.[[Year]].
    4. Let result be ? RegulateISODate(year, fields.[[Month]], fields.[[Day]], overflow).
    5. Return ! CreateISODateRecord(referenceISOYear, result.[[Month]], result.[[Day]]).
  2. Return ? NonISOMonthDayToISOReferenceDate(calendar, fields, overflow).

22.3.3.8 NonISOMonthDayToISOReferenceDate ( calendar, fields, overflow )

The implementation-defined abstract operation NonISOMonthDayToISOReferenceDate takes arguments calendar (a known calendar type but not "iso8601"), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It performs implementation-defined processing to return an ISO Date Record representing a reference date in the ISO 8601 calendar that, when converted to calendar, corresponds to the month and day of fields. The fields argument represents a month and day in the calendar identified by calendar, though it may include additional fields. The month and day are checked using the year in fields, if present; the year is used only for this check and is otherwise ignored in favour of a reference year. If an ISO Date Record cannot be created from fields because its date does not exist, the values from fields are clamped to their respective valid ranges if overflow is "constrain"; if it is "reject", an exception is thrown. As in NonISOCalendarDateToISO, such clamping is calendar-specific.

The reference date is the latest ISO 8601 date corresponding to the calendar date that is between January 1, 1900 and December 31, 1972 inclusive. If there is no such date, it is the earliest ISO 8601 date corresponding to the calendar date between January 1, 1973 and December 31, 2035 inclusive.

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 occurred in calendar years 5730 and 5733 (respectively overlapping ISO 8601 February/March 1970 and February/March 1973), but did not occur between them, so the reference year for days of that month is 1970.

The operation throws a RangeError if fields.[[Year]] is not empty and the ISO 8601 year year corresponding to fields.[[Year]] would cause ISODateWithinLimits to return false (i.e., year is not in the inclusive interval from -271,821 to 275,760.) This is so as not to require calculating whether the month and day described in fields exist in years arbitrarily far in the future or past. Note this restriction does not apply to CalendarMonthDayToISOReferenceDate when calendar is "iso8601".

Note 1
Example 1: 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.
Note 2
Example 2: When calendar is "gregory" and overflow is "constrain", a fields value of { [[MonthCode]]: "M02", [[Day]]: 30 } is clamped to { [[Year]]: 1972, [[Month]]: 2, [[Day]]: 29 } (because 29 is the maximum valid day for February) while fields values of { [[Year]]: 2001, [[MonthCode]]: "M02", [[Day]]: 30 } and { [[Era]]: "ce", [[EraYear]]: 2001, [[Month]]: 2, [[Day]]: 30 } (or an equivalent with a supported value for [[Era]] representing the Common Era beginning in ISO 8601 year 1) are clamped to { [[Year]]: 1972, [[Month]]: 2, [[Day]]: 28 } (because 28 is the maximum valid day for February 2001, which did not include a leap day).

22.3.3.9 CalendarISOToDate ( calendar, isoDate )

The abstract operation CalendarISOToDate takes arguments calendar (a known calendar type) and isoDate (an ISO Date Record) and returns a Calendar Date Record. It finds the date corresponding to isoDate in the context of the calendar identified by calendar and returns a Calendar Date Record representing that calendar date, with its fields filled in according to their descriptions. It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. If InLeapYear(TimeFromYear(isoDate.[[Year]])) = 1, then
      1. Let daysInYear be 366.
      2. Let inLeapYear be true.
    2. Else,
      1. Let daysInYear be 365.
      2. Let inLeapYear be false.
    3. Return the Calendar Date Record { [[Era]]: empty, [[EraYear]]: empty, [[Year]]: isoDate.[[Year]], [[Month]]: isoDate.[[Month]], [[MonthCode]]: CreateMonthCode(isoDate.[[Month]], false), [[Day]]: isoDate.[[Day]], [[DayOfWeek]]: ISODayOfWeek(isoDate), [[DayOfYear]]: ISODayOfYear(isoDate), [[WeekOfYear]]: ISOWeekOfYear(isoDate), [[DaysInWeek]]: 7, [[DaysInMonth]]: ISODaysInMonth(isoDate.[[Year]], isoDate.[[Month]]), [[DaysInYear]]: daysInYear, [[MonthsInYear]]: 12, [[InLeapYear]]: inLeapYear  }.
  2. Return NonISOCalendarISOToDate(calendar, isoDate).

22.3.3.10 NonISOCalendarISOToDate ( calendar, isoDate )

The implementation-defined abstract operation NonISOCalendarISOToDate takes arguments calendar (a known calendar type but not "iso8601") and isoDate (an ISO Date Record) and returns a Calendar Date Record. It performs implementation-defined processing to find the date corresponding to isoDate in the context of the calendar identified by calendar and returns a Calendar Date Record representing that calendar date, with its fields filled in according to their descriptions in Table 64.

22.3.3.11 CalendarExtraFields ( calendar, fields )

The implementation-defined abstract operation CalendarExtraFields takes arguments calendar (a known calendar type) and fields (a List of calendar property keys) and returns a List of calendar property keys. It characterizes calendar-specific fields that are relevant for the provided fields in the calendar identified by calendar. It performs the following steps when called:

  1. If calendar is "iso8601", return a new empty List.
  2. Return an implementation-defined List of calendar property keys that are relevant for the provided fields in the calendar identified by calendar. For example, if calendar reckons time in eras and fields contains "year", return « "era", "eraYear" ».

22.3.3.12 CalendarFieldKeysToIgnore ( calendar, fields )

The abstract operation CalendarFieldKeysToIgnore takes arguments calendar (a known calendar type) and fields (a Calendar Fields Record) and returns a List of calendar property keys. It determines which fields could potentially conflict with any of the non-empty fields named in fields, for the calendar identified by calendar. A field always potentially conflicts with at least itself. It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. Let ignoredFields be a new empty Set.
    2. If fields.[[Era]] is not empty, add "era" to ignoredFields.
    3. If fields.[[EraYear]] is not empty, add "eraYear" to ignoredFields.
    4. If fields.[[Year]] is not empty, add "year" to ignoredFields.
    5. If fields.[[Month]] is not empty or fields.[[MonthCode]] is not empty, add "month" and "monthCode" to ignoredFields.
    6. If fields.[[Day]] is not empty, add "day" to ignoredFields.
    7. If fields.[[Hour]] is not empty, add "hour" to ignoredFields.
    8. If fields.[[Minute]] is not empty, add "minute" to ignoredFields.
    9. If fields.[[Second]] is not empty, add "second" to ignoredFields.
    10. If fields.[[Millisecond]] is not empty, add "millisecond" to ignoredFields.
    11. If fields.[[Microsecond]] is not empty, add "microsecond" to ignoredFields.
    12. If fields.[[Nanosecond]] is not empty, add "nanosecond" to ignoredFields.
    13. Return the List of ignoredFields' elements.
  2. Return NonISOFieldKeysToIgnore(calendar, fields).

22.3.3.13 NonISOFieldKeysToIgnore ( calendar, fields )

The implementation-defined abstract operation NonISOFieldKeysToIgnore takes arguments calendar (a known calendar type but not "iso8601") and fields (a Calendar Fields Record) and returns a List of calendar property keys. It performs implementation-defined processing to determine which fields could potentially conflict with any of the non-empty fields of fields, for the calendar identified by calendar. A field always potentially conflicts with 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 in such a way that the result is free of ambiguity or conflicts.

For example, given a calendar that uses eras, such as "gregory", any one of fields.[[Year]], fields.[[Era]], or fields.[[EraYear]] being non-empty 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", a possible implementation might produce the following results when calendar is "gregory":

Table 66: Example results of NonISOFieldKeysToIgnore
Non-empty Fields 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 fields.[[Day]], fields.[[Month]], or fields.[[MonthCode]] are non-empty (not only fields.[[Year]], fields.[[Era]], or fields.[[EraYear]], as in the example above) because it's possible that changing the day or month would cause a conflict with the era.

22.3.3.14 CalendarResolveFields ( calendar, fields, type )

The abstract operation CalendarResolveFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and type (date, year-month, or month-day) and returns either a normal completion containing unused or a throw completion. It validates that fields (which describes a date or partial date in the 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 fields and removing redundant fields (for example, merging [[Era]] and [[EraYear]] into [[Year]]). It performs the following steps when called:

  1. If calendar is "iso8601", then
    1. Let needsYear be false.
    2. If type is either date or year-month, set needsYear to true.
    3. Let needsDay be false.
    4. If type is either date or month-day, set needsDay to true.
    5. If needsYear is true and fields.[[Year]] is empty, throw a TypeError exception.
    6. If needsDay is true and fields.[[Day]] is empty, throw a TypeError exception.
    7. If fields.[[Month]] is empty and fields.[[MonthCode]] is empty, throw a TypeError exception.
    8. If fields.[[MonthCode]] is not empty, then
      1. Let parsedMonthCode be ! ParseMonthCode(fields.[[MonthCode]]).
      2. If parsedMonthCode.[[IsLeapMonth]] is true, throw a RangeError exception.
      3. Let month be parsedMonthCode.[[MonthNumber]].
      4. If month > 12, throw a RangeError exception.
      5. If fields.[[Month]] is not empty and fields.[[Month]]month, throw a RangeError exception.
      6. Set fields.[[Month]] to month.
  2. Else,
    1. Perform ? NonISOResolveFields(calendar, fields, type).
  3. Return unused.

22.3.3.15 NonISOResolveFields ( calendar, fields, type )

The implementation-defined abstract operation NonISOResolveFields takes arguments calendar (a known calendar type but not "iso8601"), fields (a Calendar Fields Record), 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 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 fields and removing redundant fields (for example, merging [[Era]] and [[EraYear]] into [[Year]]).

The operation throws a TypeError exception if the non-empty fields of fields are insufficient to identify a unique instance of type in the calendar (e.g., when at least one field in each combination capable of determining some part of its data is empty) or a RangeError exception if the fields are sufficient but their values are internally inconsistent within the calendar (e.g., when fields such as [[Month]] and [[MonthCode]] have conflicting non-empty values). For example:

  • If type is either date or month-day, “day” in the calendar has an interpretation similar to ISO 8601, and fields.[[Day]] is empty.
  • If fields.[[MonthCode]] identifies a month code that is not valid in any year of the calendar.
  • If fields.[[Month]] and fields.[[MonthCode]] are both empty or neither value is empty but they do not identify the same month.
  • If type is month-day, fields.[[MonthCode]] is empty, and a specific year cannot be determined from fields.
  • If the calendar supports the usual partitioning of years into eras with their own year counting as represented by “year”, “era”, and “era year” (as in the Gregorian or traditional Japanese calendars) and any of the following cases apply:
    • type is date or year-month and each of fields.[[Year]], fields.[[Era]], and fields.[[EraYear]] is empty.
    • fields.[[Era]] is empty but fields.[[EraYear]] is not.
    • fields.[[EraYear]] is empty but fields.[[Era]] is not.
    • None of the three values are empty but fields.[[Era]] and fields.[[EraYear]] do not together identify the same year as fields.[[Year]].

In some cases, verifying the internal consistency of two fields requires the data from other fields, such as checking fields.[[MonthCode]] "M06" against fields.[[Month]] 7 in the Hebrew calendar (which are consistent if and only if fields identifies a year that includes leap month Adar I).

Note 1

When the fields of fields are inconsistent with respect to a non-empty fields.[[Era]], it is recommended that fields.[[Era]] and fields.[[EraYear]] be updated to resolve the inconsistency by lenient interpretation of out-of-bounds values (rather than throwing a RangeError), which is particularly useful for consistent interpretation of dates in calendars with regnal eras.

  • In the Gregorian calendar, a zero or negative fields.[[EraYear]] should be replaced with a positive [[EraYear]] corresponding with extension of the era into its complement and fields.[[Era]] should be updating accordingly (such that Common Era [[EraYear]] 0 is updated to Before Common Era [[EraYear]] 1, Before Common Era [[EraYear]] -1 is updated to Common Era [[EraYear]] 2, etc.).
  • In the Japanese calendar, when fields.[[Era]] is not empty and the date represented by fields is not within the bounds of that era, fields.[[Era]] should be updated to the appropriate containing era for that date (for example, because the transition from Heisei era [[EraYear]] 31 to Reiwa era [[EraYear]] 1 took place on May 1 of [[Year]] 2019, Heisei era [[EraYear]] 32 should be updated to Reiwa era [[EraYear]] 2, Reiwa era [[EraYear]] 1 [[Month]] 1 should be updated to Heisei era [[EraYear]] 31 [[Month]] 1, etc.).
Note 2
When type is month-day and fields.[[Month]] is not empty, it is recommended that all calendars other than the ISO 8601 calendar require a disambiguating year (e.g., either fields.[[Year]] or fields.[[Era]] and fields.[[EraYear]]) to avoid a TypeError, regardless of whether or not fields.[[MonthCode]] is empty. The ISO 8601 calendar allows fields.[[Year]] to be empty in this case because it is a special default calendar that is permanently stable for automated processing.

22.3.3.16 CalendarDateFromFields ( calendar, fields, overflow )

The abstract operation CalendarDateFromFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It converts a calendar date in the reckoning of calendar, if it is uniquely determined by fields, into an ISO Date Record. It performs the following steps when called:

  1. Perform ? CalendarResolveFields(calendar, fields, date).
  2. Let result be ? CalendarDateToISO(calendar, fields, overflow).
  3. If ISODateWithinLimits(result) is false, throw a RangeError exception.
  4. Return result.

22.3.3.17 CalendarYearMonthFromFields ( calendar, fields, overflow )

The abstract operation CalendarYearMonthFromFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It converts a calendar month in the reckoning of calendar, if it is uniquely determined by fields, into an ISO Date Record representing the first day of that month. It performs the following steps when called:

  1. Set fields.[[Day]] to 1.
  2. Perform ? CalendarResolveFields(calendar, fields, year-month).
  3. Let result be ? CalendarDateToISO(calendar, fields, overflow).
  4. If ISOYearMonthWithinLimits(result) is false, throw a RangeError exception.
  5. Return result.

22.3.3.18 CalendarMonthDayFromFields ( calendar, fields, overflow )

The abstract operation CalendarMonthDayFromFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an ISO Date Record or a throw completion. It converts a calendar month-day in the reckoning of calendar, if it is uniquely determined by fields, into an ISO Date Record representing that day in an appropriate reference year. It performs the following steps when called:

  1. Perform ? CalendarResolveFields(calendar, fields, month-day).
  2. Let result be ? CalendarMonthDayToISOReferenceDate(calendar, fields, overflow).
  3. Assert: ISODateWithinLimits(result) is true.
  4. Return result.
Note
The ISODateWithinLimits assertion holds because Step 1.e of CalendarMonthDayToISOReferenceDate or NonISOMonthDayToISOReferenceDate returns an ISO Date Record with a reference year that falls within the representable range.

22.3.4 Date Duration Records

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

Note
See the note in 22.15.4 regarding implementation storage requirements for these fields.

Date Duration Records have the fields listed in Table 67.

Table 67: Date 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.

22.3.4.1 AdjustDateDurationRecord ( dateDuration, days [ , weeks [ , months ] ] )

The abstract operation AdjustDateDurationRecord takes arguments dateDuration (a Date Duration Record) and days (an integer) and optional arguments weeks (an integer) and months (an integer) and returns either a normal completion containing a Date Duration Record or a throw completion. It creates a new Date Duration Record that is a copy of dateDuration, with one or more fields replaced with new values. It performs the following steps when called:

  1. If weeks is not present, set weeks to dateDuration.[[Weeks]].
  2. If months is not present, set months to dateDuration.[[Months]].
  3. Return ? CreateDateDurationRecord(dateDuration.[[Years]], months, weeks, days).

22.3.4.2 CreateDateDurationRecord ( years, months, weeks, days )

The abstract operation CreateDateDurationRecord takes arguments years (an integer), months (an integer), weeks (an integer), and days (an integer) and returns either a normal completion containing a Date Duration Record or a throw completion. 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 Date Duration Record { [[Years]]: (𝔽(years)), [[Months]]: (𝔽(months)), [[Weeks]]: (𝔽(weeks)), [[Days]]: (𝔽(days))  }.

22.3.4.3 DateDurationDays ( dateDuration, plainRelativeTo )

The abstract operation DateDurationDays takes arguments dateDuration (a Date Duration Record) and plainRelativeTo (a Temporal.PlainDate) and returns either a normal completion containing an integer or a throw completion. It converts the calendar units of a duration into a number of days, and returns the result. It performs the following steps when called:

  1. Let yearsMonthsWeeksDuration be ! AdjustDateDurationRecord(dateDuration, 0).
  2. If DateDurationSign(yearsMonthsWeeksDuration) = 0, return dateDuration.[[Days]].
  3. Let isoDateTo be ? CalendarDateAdd(plainRelativeTo.[[Calendar]], plainRelativeTo.[[ISODate]], yearsMonthsWeeksDuration, "constrain").
  4. Let epochDaysFrom be ISODateToEpochDays(plainRelativeTo.[[ISODate]].[[Year]], plainRelativeTo.[[ISODate]].[[Month]], plainRelativeTo.[[ISODate]].[[Day]]).
  5. Let epochDaysTo be ISODateToEpochDays(isoDateTo.[[Year]], isoDateTo.[[Month]], isoDateTo.[[Day]]).
  6. Let yearsMonthsWeeksInDays be epochDaysTo - epochDaysFrom.
  7. Return dateDuration.[[Days]] + yearsMonthsWeeksInDays.

22.3.4.4 DateDurationSign ( dateDuration )

The abstract operation DateDurationSign takes argument dateDuration (a Date Duration Record) and returns -1, 0, or 1. It returns 1 if the most significant non-zero field in the dateDuration argument is positive, and -1 if the most significant non-zero field is negative. If all of dateDuration's fields are zero, it returns 0. It performs the following steps when called:

  1. If dateDuration.[[Years]] < 0, return -1.
  2. If dateDuration.[[Years]] > 0, return 1.
  3. If dateDuration.[[Months]] < 0, return -1.
  4. If dateDuration.[[Months]] > 0, return 1.
  5. If dateDuration.[[Weeks]] < 0, return -1.
  6. If dateDuration.[[Weeks]] > 0, return 1.
  7. If dateDuration.[[Days]] < 0, return -1.
  8. If dateDuration.[[Days]] > 0, return 1.
  9. Return 0.

22.3.4.5 ZeroDateDuration ( )

The abstract operation ZeroDateDuration takes no arguments and returns a Date Duration Record. The returned Record represents a duration with length 0. It performs the following steps when called:

  1. Return ! CreateDateDurationRecord(0, 0, 0, 0).

22.3.5 Epoch Days Operations

22.3.5.1 ValidateISODaysRange ( isoDate )

The abstract operation ValidateISODaysRange takes argument isoDate (an ISO Date Record) and returns either a normal completion containing unused or a throw completion. It checks that the given date is within the range of 108 days from the epoch. It performs the following steps when called:

  1. If ISODateToEpochDays(isoDate.[[Year]], isoDate.[[Month]], isoDate.[[Day]]) is not in the inclusive interval from -108 to 108, throw a RangeError exception.
  2. Return unused.
Note
This operation ensures that GetUTCEpochNanoseconds is not called with numbers that are too large. It is distinct from ISODateWithinLimits.

22.3.5.2 EpochDaysToEpochMilliseconds ( day, time )

The abstract operation EpochDaysToEpochMilliseconds takes arguments day (an integer) and time (an integer) and returns an integer. It calculates a number of milliseconds as in MakeDate, using mathematical values. It performs the following steps when called:

  1. Return day × MillisecondsPerDay + time.

22.3.5.3 ISODateToEpochDays ( year, month, day )

The abstract operation ISODateToEpochDays takes arguments year (an integer), month (an integer), and day (an integer) and returns an integer. It calculates a number of days as in MakeDay, using mathematical values. It performs the following steps when called:

  1. Let resolvedYear be year + floor((month - 1) / 12).
  2. Let resolvedMonth be ((month - 1) modulo 12) + 1.
  3. Let shiftedYear be resolvedYear.
  4. Let shiftedMonth be resolvedMonth - 3.
  5. If shiftedMonth < 0, then
    1. Set shiftedYear to shiftedYear - 1.
    2. Set shiftedMonth to shiftedMonth + 12.
  6. Assert: shiftedMonth is in the inclusive interval from 0 to 11.
  7. Let cycle be floor(shiftedYear / 400).
  8. Let yearOfCycle be shiftedYear modulo 400.
  9. Assert: yearOfCycle is in the inclusive interval from 0 to 399.
  10. Let dayOfYear be truncate((153 × shiftedMonth + 2) / 5) + day - 1.
  11. Assert: dayOfYear ≥ 0.
  12. Assert: If day is in the inclusive interval from 1 to ISODaysInMonth(resolvedYear, resolvedMonth), dayOfYear ≤ 365.
  13. Let dayOfCycle be yearOfCycle × 365 + truncate(yearOfCycle / 4) - truncate(yearOfCycle / 100) + dayOfYear.
  14. Assert: dayOfCycle ≥ 0.
  15. Assert: If day is in the inclusive interval from 1 to ISODaysInMonth(resolvedYear, resolvedMonth), dayOfCycle ≤ 146096.
  16. Return cycle × 146097 + dayOfCycle - 719468.
Note

This algorithm is adapted from Hinnant, H. (2021), chrono-Compatible Low-Level Date Algorithms. Values of month outside the inclusive interval from 1 to 12 are handled by steps 1 and 2 to satisfy the preconditions of the algorithm. The validity of the algorithm is not affected by values of day outside the inclusive interval from 1 to ISODaysInMonth(resolvedYear, resolvedMonth), as the days are simply added to the total.

22.3.6 Epoch Nanoseconds and Range

An epoch nanoseconds count is an integer that represents an instant in time to nanosecond precision, as stored in the [[EpochNanoseconds]] internal slot of Temporal.Instant and Temporal.ZonedDateTime objects. It supports the same range as a time value but expressed in nanoseconds, from MinEpochNanoseconds to MaxEpochNanoseconds. There is no nanosecond equivalent of the time value NaN; there is no representation for no specific instant.

The exact moment of midnight at the beginning of 1 January 1970 UTC is represented by the value 0. The maximum value is MaxEpochNanoseconds, and the minimum value is MinEpochNanoseconds.

22.3.6.1 AddEpochNanoseconds ( epochNanoseconds, timeDuration )

The abstract operation AddEpochNanoseconds takes arguments epochNanoseconds (an epoch nanoseconds count) and timeDuration (a time duration) and returns either a normal completion containing an epoch nanoseconds count or a throw completion. It adds a time duration to an epoch nanoseconds count. It performs the following steps when called:

  1. Let result be AddTimeDurationToEpochNanoseconds(timeDuration, epochNanoseconds).
  2. If IsWithinEpochNanosecondsInterval(result) is false, throw a RangeError exception.
  3. Return result.

22.3.6.2 CompareEpochNanoseconds ( xEpochNanoseconds, yEpochNanoseconds )

The abstract operation CompareEpochNanoseconds takes arguments xEpochNanoseconds (an epoch nanoseconds count) and yEpochNanoseconds (an epoch nanoseconds count) and returns -1, 0, or 1. A return value of 0 means xEpochNanoseconds and yEpochNanoseconds are equal, 1 means xEpochNanoseconds comes after yEpochNanoseconds, and -1 means yEpochNanoseconds comes after xEpochNanoseconds. It performs the following steps when called:

  1. If xEpochNanoseconds > yEpochNanoseconds, return 1.
  2. If xEpochNanoseconds < yEpochNanoseconds, return -1.
  3. Return 0.

22.3.6.3 DifferenceEpochNanoseconds ( epochNanosecondsFrom, epochNanosecondsTwo, roundingIncrement, smallestUnit, roundingMode )

The abstract operation DifferenceEpochNanoseconds takes arguments epochNanosecondsFrom (an epoch nanoseconds count), epochNanosecondsTwo (an epoch nanoseconds count), roundingIncrement (a positive integer), smallestUnit (a time unit), and roundingMode (a rounding mode) and returns an Internal Duration Record. It computes the difference between two epoch nanoseconds counts epochNanosecondsFrom and epochNanosecondsTo, and rounds the result according to the parameters roundingIncrement, smallestUnit, and roundingMode. It performs the following steps when called:

  1. Let timeDuration be TimeDurationFromEpochNanosecondsDifference(epochNanosecondsFrom, epochNanosecondsTo).
  2. Set timeDuration to ! RoundTimeDuration(timeDuration, roundingIncrement, smallestUnit, roundingMode).
  3. Return CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration).

22.3.6.4 IsWithinEpochNanosecondsInterval ( epochNanoseconds )

The abstract operation IsWithinEpochNanosecondsInterval takes argument epochNanoseconds (an integer) and returns a Boolean. It returns true if its argument is within the allowed range for an epoch nanoseconds count, and false otherwise. It performs the following steps when called:

  1. If epochNanoseconds is not in the inclusive interval from MinEpochNanoseconds to MaxEpochNanoseconds, return false; else return true.

22.3.6.5 RoundEpochNanoseconds ( epochNanoseconds, increment, unit, roundingMode )

The abstract operation RoundEpochNanoseconds takes arguments epochNanoseconds (an epoch nanoseconds count), increment (a positive integer), unit (a time unit), and roundingMode (a rounding mode) and returns an epoch nanoseconds count. It rounds a an epoch nanoseconds count to the given rounding increment. It performs the following steps when called:

  1. Let incrementNanoseconds be increment × TemporalUnitLength(unit).
  2. Return RoundNumberToIncrementAsIfPositive(epochNanoseconds, incrementNanoseconds, roundingMode).

22.3.7 Internal Duration Records

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

Internal Duration Records have the fields listed in Table 68.

Table 68: Internal Duration Record Fields
Field Name Value Meaning
[[Date]] a Date Duration Record The date portion of the duration.
[[Time]] a time duration The time portion of the duration.

22.3.7.1 CombineDateAndTimeDuration ( dateDuration, timeDuration )

The abstract operation CombineDateAndTimeDuration takes arguments dateDuration (a Date Duration Record) and timeDuration (a time duration) and returns an Internal Duration Record. It performs the following steps when called:

  1. Let dateSign be DateDurationSign(dateDuration).
  2. Let timeSign be TimeDurationSign(timeDuration).
  3. Assert: If dateSign ≠ 0 and timeSign ≠ 0, dateSign = timeSign.
  4. Return the Internal Duration Record { [[Date]]: dateDuration, [[Time]]: timeDuration  }.

22.3.7.2 InternalDurationSign ( internalDuration )

The abstract operation InternalDurationSign takes argument internalDuration (an Internal Duration Record) and returns -1, 0, or 1. It returns 1 if the most significant non-zero field in the internalDuration argument is positive, and -1 if the most significant non-zero field is negative. If all of internalDuration's fields are zero, it returns 0. It performs the following steps when called:

  1. Let dateSign be DateDurationSign(internalDuration.[[Date]]).
  2. If dateSign ≠ 0, return dateSign.
  3. Return TimeDurationSign(internalDuration.[[Time]]).

22.3.7.3 ToInternalDurationRecord ( duration )

The abstract operation ToInternalDurationRecord takes argument duration (a Temporal.Duration) and returns an Internal Duration Record. It converts duration into its internal form, for use in duration calculations that may involve time zones. The duration's days are kept separate and not converted into the [[Time]] field. It performs the following steps when called:

  1. Let dateDuration be ! CreateDateDurationRecord(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]]).
  2. Let timeDuration be ! TimeDurationFromComponents(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  3. Return CombineDateAndTimeDuration(dateDuration, timeDuration).

22.3.7.4 ToInternalDurationRecordWith24HourDays ( duration )

The abstract operation ToInternalDurationRecordWith24HourDays takes argument duration (a Temporal.Duration) and returns an Internal Duration Record. It converts duration into its internal form, for use in duration calculations that do not involve time zones. The duration's days are assumed to be uniformly 24 hours. The [[Days]] field of the Date Duration Record in the [[Date]] field of the returned Internal Duration Record is set to 0, and the [[Time]] field of the returned Internal Duration Record includes the days. It performs the following steps when called:

  1. Let timeDuration be ! TimeDurationFromComponents(duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  2. Set timeDuration to ! Add24HourDaysToTimeDuration(timeDuration, duration.[[Days]]).
  3. Let dateDuration be ! CreateDateDurationRecord(duration.[[Years]], duration.[[Months]], duration.[[Weeks]], 0).
  4. Return CombineDateAndTimeDuration(dateDuration, timeDuration).

22.3.8 The ISO 8601 Calendar

The only calendar type that a conforming ECMA-262 implementation is required to support is the ISO 8601 calendar. This section contains definitions specific to calendrical calculations in the ISO 8601 calendar.

22.3.8.1 CompareSurpasses ( sign, year, monthOrMonthCode, day, target )

The abstract operation CompareSurpasses takes arguments sign (-1 or 1), year (an integer), monthOrMonthCode (either an integer or a month code), day (an integer), and target (a Calendar Date Record) and returns a Boolean. The return value indicates whether the ISO 8601 calendar date formed by year, monthOrMonthCode, and day, which need not exist, surpasses target in the direction denoted by sign. It performs the following steps when called:

  1. If yeartarget.[[Year]], then
    1. If sign × (year - target.[[Year]]) > 0, return true.
  2. Else if monthOrMonthCode is a month code and monthOrMonthCode is not target.[[MonthCode]], then
    1. If sign = 1 and monthOrMonthCode is lexicographically ordered after target.[[MonthCode]], return true.
    2. If sign = -1 and target.[[MonthCode]] is lexicographically ordered after monthOrMonthCode, return true.
  3. Else if monthOrMonthCode is an integer and monthOrMonthCodetarget.[[Month]], then
    1. If sign × (monthOrMonthCode - target.[[Month]]) > 0, return true.
  4. Else if daytarget.[[Day]], then
    1. If sign × (day - target.[[Day]]) > 0, return true.
  5. Return false.

22.3.8.2 ISODateSurpasses ( sign, baseDate, years, months, weeks, days, isoDateTo )

The abstract operation ISODateSurpasses takes arguments sign (-1 or 1), baseDate (an ISO Date Record), years (an integer), months (an integer), weeks (an integer), days (an integer), and isoDateTo (an ISO Date Record) and returns a Boolean. The return value indicates whether the date isoDateFrom, the result of adding the duration denoted by years, months, weeks, and days to baseDate, surpasses isoDateTo in the direction denoted by sign. If weeks and days are both zero, then isoDateFrom need not exist (for example, it could be February 30). 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 parts be CalendarISOToDate("iso8601", baseDate).
  2. Let target be CalendarISOToDate("iso8601", isoDateTo).
  3. Let y0 be parts.[[Year]] + years.
  4. If CompareSurpasses(sign, y0, parts.[[MonthCode]], parts.[[Day]], target) is true, return true.
  5. If months = 0, weeks = 0, and days = 0, return false.
  6. Let m0 be parts.[[Month]] + months.
  7. Let monthsAdded be BalanceISOYearMonth(y0, m0).
  8. If CompareSurpasses(sign, monthsAdded.[[Year]], monthsAdded.[[Month]], parts.[[Day]], target) is true, return true.
  9. If weeks = 0 and days = 0, return false.
  10. Let regulatedDate be ! RegulateISODate(monthsAdded.[[Year]], monthsAdded.[[Month]], parts.[[Day]], "constrain").
  11. Let daysInWeek be 7.
  12. Let balancedDate be AddDaysToISODate(regulatedDate, daysInWeek × weeks + days).
  13. Return CompareSurpasses(sign, balancedDate.[[Year]], balancedDate.[[Month]], balancedDate.[[Day]], target).
Note

This operation intentionally uses an overflow of "constrain" in step 10. As a result, this operation does not have the same meaning as Temporal.PlainDate.compare (22.11.2.3). It is only intended to be used inside CalendarDateUntil.

22.3.8.3 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 one of 1, 3, 5, 7, 8, 10, or 12, return 31.
  2. If month is one of 4, 6, 9, or 11, return 30.
  3. Assert: month = 2.
  4. Return 28 + InLeapYear(TimeFromYear(year)).

22.3.8.4 Year-Week Records

The Year-Week Record specification type is returned by the week number calculation in ISOWeekOfYear, and the corresponding calculations for other calendars if applicable.

It consists of the 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 the calendar year by up to 1 in either direction). The week calendar year is relative to the first day of a calendar-specific “epoch year”, as in the Calendar Date Record's [[Year]] field, not relative to an era as in [[EraYear]].

Both fields of the Year-Week Record are empty for calendars that do not have a well-defined week numbering system.

Year-Week Records have the fields listed in table Table 69.

Table 69: Year-Week Record Fields
Field Name Value Meaning
[[Week]] a positive integer or empty The calendar week of year, if applicable.
[[Year]] an integer or empty The week calendar year, if applicable.

22.3.8.5 ISOWeekOfYear ( isoDate )

The abstract operation ISOWeekOfYear takes argument isoDate (an ISO Date Record) 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 and week calendar year. It performs the following steps when called:

  1. Let year be isoDate.[[Year]].
  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 ISODayOfYear(isoDate).
  9. Let dayOfWeek be ISODayOfWeek(isoDate).
  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 jan1st be ! CreateISODateRecord(year, 1, 1).
    3. Let dayOfJan1st be ISODayOfWeek(jan1st).
    4. If dayOfJan1st = friday, then
      1. Return the Year-Week Record { [[Week]]: maxWeekNumber, [[Year]]: year - 1 }.
    5. If dayOfJan1st = saturday, and InLeapYear(TimeFromYear(year - 1)) = 1, then
      1. Return the Year-Week Record { [[Week]]: maxWeekNumber, [[Year]]: year - 1 }.
    6. Return the Year-Week Record { [[Week]]: maxWeekNumber - 1, [[Year]]: year - 1 }.
  12. If week = maxWeekNumber, then
    1. If InLeapYear(TimeFromYear(year)) = 0, let daysInYear be 365; else let daysInYear be 366.
    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 (ISO 8601-1, Section 3.1.1.23), 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).

22.3.8.6 ISODayOfYear ( isoDate )

The abstract operation ISODayOfYear takes argument isoDate (an ISO Date Record) 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. Let epochDays be ISODateToEpochDays(isoDate.[[Year]], isoDate.[[Month]], isoDate.[[Day]]).
  2. Return DayWithinYear(𝔽(EpochDaysToEpochMilliseconds(epochDays, 0))) + 1.

22.3.8.7 ISODayOfWeek ( isoDate )

The abstract operation ISODayOfWeek takes argument isoDate (an ISO Date Record) 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. Let epochDays be ISODateToEpochDays(isoDate.[[Year]], isoDate.[[Month]], isoDate.[[Day]]).
  2. Let dayOfWeek be WeekDay(𝔽(EpochDaysToEpochMilliseconds(epochDays, 0))).
  3. If dayOfWeek = 0, return 7.
  4. Return dayOfWeek.

22.3.9 ISO Date Records

An ISO Date Record is a Record used to represent a calendar date that exists 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. For any ISO Date Record d, IsValidISODate(d.[[Year]], d.[[Month]], d.[[Day]]) must return true.

ISO Date Records have the fields listed in Table 70.

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

22.3.9.1 AddDaysToISODate ( isoDate, days )

The abstract operation AddDaysToISODate takes arguments isoDate (an ISO Date Record) and days (an integer) and returns an ISO Date Record. It adds days to isoDate resulting in an ISO Date Record, by overflowing out-of-range month or day values into the next-highest unit. This date may be outside the range given by ISODateWithinLimits. It performs the following steps when called:

  1. Let epochDays be ISODateToEpochDays(isoDate.[[Year]], isoDate.[[Month]], isoDate.[[Day]]) + days.
  2. Let epochMilliseconds be EpochDaysToEpochMilliseconds(epochDays, 0).
  3. Return ! CreateISODateRecord(YearFromTime(𝔽(epochMilliseconds)), MonthFromTime(𝔽(epochMilliseconds)) + 1, DateFromTime(𝔽(epochMilliseconds))).

22.3.9.2 CompareISODate ( xISODate, yISODate )

The abstract operation CompareISODate takes arguments xISODate (an ISO Date Record) and yISODate (an ISO Date Record) and returns -1, 0, or 1. It performs a comparison of the two dates denoted by xISODate and yISODate according to ISO 8601 calendar arithmetic. A return value of 0 means xISODate and yISODate are equal, 1 means xISODate comes after yISODate, and -1 means yISODate comes after xISODate. It performs the following steps when called:

  1. If xISODate.[[Year]] > yISODate.[[Year]], return 1.
  2. If xISODate.[[Year]] < yISODate.[[Year]], return -1.
  3. If xISODate.[[Month]] > yISODate.[[Month]], return 1.
  4. If xISODate.[[Month]] < yISODate.[[Month]], return -1.
  5. If xISODate.[[Day]] > yISODate.[[Day]], return 1.
  6. If xISODate.[[Day]] < yISODate.[[Day]], return -1.
  7. Return 0.

22.3.9.3 CreateISODateRecord ( year, month, day )

The abstract operation CreateISODateRecord takes arguments year (an integer), month (an integer in the inclusive interval from 1 to 12), and day (an integer in the inclusive interval from 1 to 31) and returns either a normal completion containing an ISO Date Record or a throw completion. It performs the following steps when called:

  1. If IsValidISODate(year, month, day) is false, throw a RangeError exception.
  2. Return the ISO Date Record { [[Year]]: year, [[Month]]: month, [[Day]]: day }.

22.3.9.4 ISODateToFields ( calendar, isoDate, type )

The abstract operation ISODateToFields takes arguments calendar (a known calendar type), isoDate (an ISO Date Record), and type (date, year-month, or month-day) and returns a Calendar Fields Record. It performs the following steps when called:

  1. Let fields be the Calendar Fields Record { [[Era]]: empty, [[EraYear]]: empty, [[Year]]: empty, [[Month]]: empty, [[MonthCode]]: empty, [[Day]]: empty, [[Hour]]: empty, [[Minute]]: empty, [[Second]]: empty, [[Millisecond]]: empty, [[Microsecond]]: empty, [[Nanosecond]]: empty, [[OffsetString]]: empty, [[TimeZone]]: empty  }.
  2. Let calendarDate be CalendarISOToDate(calendar, isoDate).
  3. Set fields.[[MonthCode]] to calendarDate.[[MonthCode]].
  4. If type is either month-day or date, then
    1. Set fields.[[Day]] to calendarDate.[[Day]].
  5. If type is either year-month or date, then
    1. Set fields.[[Year]] to calendarDate.[[Year]].
  6. Return fields.

22.3.9.5 ISODateWithinLimits ( isoDate )

The abstract operation ISODateWithinLimits takes argument isoDate (an ISO Date Record) and returns a Boolean. It returns true if the date in the ISO 8601 calendar given by the argument is within the representable range of Temporal.PlainDate, and false otherwise. This operation is used primarily to validate the data being stored in the internal slots of Temporal.PlainDate and Temporal.PlainMonthDay objects.

Note

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

It performs the following steps when called:

  1. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: NoonTimeRecord() }.
  2. Return ISODateTimeWithinLimits(isoDateTime).

22.3.9.6 IsValidISODate ( year, month, day )

The abstract operation IsValidISODate takes arguments year (an integer), month (an integer), and day (an integer) and returns a Boolean. It returns true if its arguments form a date that exists 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 is not in the inclusive interval from 1 to 12, return false.
  2. Let daysInMonth be ISODaysInMonth(year, month).
  3. If day is not in the inclusive interval from 1 to daysInMonth, return false; else return true.

22.3.9.7 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 a throw completion. It performs the overflow correction specified by overflow on the values year, month, and day, in order to arrive at an ISO Date Record. If an ISO Date Record cannot be created from year, month, and day because the date formed by those values does not exist, the month and day are clamped to their respective valid ranges in the result if overflow is "constrain"; if it is "reject", an exception is thrown. 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. Assert: overflow is "reject".
  3. Return ? CreateISODateRecord(year, month, day).

22.3.10 ISO Date-Time Records

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

An ISO Date-Time Record x is said to be earlier than another ISO Date-Time Record y if CompareISODateTime(x, y) = -1. Likewise, x is later than y if CompareISODateTime(x, y) = 1.

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

Table 71: ISO Date-Time Record Fields
Field Name Value Meaning
[[ISODate]] an ISO Date Record The date in the ISO 8601 calendar.
[[Time]] a Time Record The time. The [[Days]] field is ignored.

22.3.10.1 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 epochDays be ISODateToEpochDays(year, month, day) + balancedTime.[[Days]].
  3. Let epochMilliseconds be EpochDaysToEpochMilliseconds(epochDays, 0).
  4. Let balancedDate be ! CreateISODateRecord(YearFromTime(𝔽(epochMilliseconds)), MonthFromTime(𝔽(epochMilliseconds)) + 1, DateFromTime(𝔽(epochMilliseconds))).
  5. Return the ISO Date-Time Record { [[ISODate]]: balancedDate, [[Time]]: balancedTime }.

22.3.10.2 CompareISODateTime ( xISODateTime, yISODateTime )

The abstract operation CompareISODateTime takes arguments xISODateTime (an ISO Date-Time Record) and yISODateTime (an ISO Date-Time Record) and returns -1, 0, or 1. It performs a comparison of two date-times according to ISO 8601 calendar arithmetic. A return value of 0 means xISODateTime and yISODateTime are equal, 1 means xISODateTime comes after yISODateTime, and -1 means yISODateTime comes after xISODateTime. It performs the following steps when called:

  1. Let dateResult be CompareISODate(xISODateTime.[[ISODate]], yISODateTime.[[ISODate]]).
  2. If dateResult ≠ 0, return dateResult.
  3. Return CompareTimeRecord(xISODateTime.[[Time]], yISODateTime.[[Time]]).

22.3.10.3 DifferenceISODateTime ( xISODateTime, yISODateTime, calendar, largestUnit )

The abstract operation DifferenceISODateTime takes arguments xISODateTime (an ISO Date-Time Record), yISODateTime (an ISO Date-Time Record), calendar (a known calendar type), and largestUnit (a Temporal unit) and returns an Internal Duration Record. The returned Internal 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. It performs the following steps when called:

  1. Assert: ISODateTimeWithinLimits(xISODateTime) is true.
  2. Assert: ISODateTimeWithinLimits(yISODateTime) is true.
  3. Let timeDuration be DifferenceTime(xISODateTime.[[Time]], yISODateTime.[[Time]]).
  4. Let timeSign be TimeDurationSign(timeDuration).
  5. Let dateSign be CompareISODate(xISODateTime.[[ISODate]], yISODateTime.[[ISODate]]).
  6. Let adjustedDate be yISODateTime.[[ISODate]].
  7. If timeSign = dateSign, then
    1. Set adjustedDate to AddDaysToISODate(adjustedDate, timeSign).
    2. Set timeDuration to ! Add24HourDaysToTimeDuration(timeDuration, -timeSign).
  8. Let dateLargestUnit be LargerOfTwoTemporalUnits("day", largestUnit).
  9. Let dateDifference be CalendarDateUntil(calendar, xISODateTime.[[ISODate]], adjustedDate, dateLargestUnit).
  10. If largestUnit is not dateLargestUnit, then
    1. Set timeDuration to ! Add24HourDaysToTimeDuration(timeDuration, dateDifference.[[Days]]).
    2. Set dateDifference.[[Days]] to 0.
  11. Return CombineDateAndTimeDuration(dateDifference, timeDuration).

22.3.10.4 ISODateTimeWithinLimits ( isoDateTime )

The abstract operation ISODateTimeWithinLimits takes argument isoDateTime (an ISO Date-Time Record) and returns a Boolean. It returns 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. This operation is used primarily to validate the data being stored in the internal slots of Temporal.PlainDateTime objects. It performs the following steps when called:

  1. If ISODateToEpochDays(isoDateTime.[[ISODate]].[[Year]], isoDateTime.[[ISODate]].[[Month]], isoDateTime.[[ISODate]].[[Day]]) is not in the inclusive interval from -108 to 108, return false.
  2. Let epochNanoseconds be GetUTCEpochNanoseconds(isoDateTime).
  3. If epochNanoseconds is not in the interval from MinEpochNanoseconds - NanosecondsPerDay (exclusive) to MaxEpochNanoseconds + NanosecondsPerDay (exclusive), return false.
  4. Return true.

22.3.10.5 RoundISODateTime ( isoDateTime, increment, unit, roundingMode )

The abstract operation RoundISODateTime takes arguments isoDateTime (an ISO Date-Time Record), increment (a positive integer), unit (either a time unit or "day"), and roundingMode (a rounding mode) 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(isoDateTime) is true.
  2. Let roundedTime be RoundTime(isoDateTime.[[Time]], increment, unit, roundingMode).
  3. Let balanceResult be AddDaysToISODate(isoDateTime.[[ISODate]], roundedTime.[[Days]]).
  4. Return the ISO Date-Time Record { [[ISODate]]: balanceResult, [[Time]]: roundedTime }.

22.3.10.6 TimeValueToISODateTimeRecord ( tv )

The abstract operation TimeValueToISODateTimeRecord takes argument tv (a finite time value) and returns an ISO Date-Time Record. It converts a time value into an ISO Date-Time Record. It performs the following steps when called:

  1. Let isoDate be ! CreateISODateRecord(YearFromTime(tv), MonthFromTime(tv) + 1, DateFromTime(tv)).
  2. Let time be ! CreateTimeRecord(HourFromTime(tv), MinuteFromTime(tv), SecondFromTime(tv), MillisecondFromTime(tv), 0, 0).
  3. Return the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: time }.

22.3.11 Month Codes

Lunisolar calendars may insert leap months into certain years, in order to reconcile the discrepancy between lunar cycles and the solar year. For this reason, a particular month may not have the same ordinal number every year if a leap month is inserted before it.

A month code is a String that refers uniquely to a particular month, even one that is not present every year. Month codes are lexicographically ordered according to the notional order of months in the year, even though not all may be present in any given year. They conform to the following string format:

The month code for a month that is not a leap month at 1-based ordinal position index in a common year of the calendar (i.e., a year that is not a leap year) is the string-concatenation of "M" and ToZeroPaddedDecimalString(index, 2). The month code for a leap month inserted after a month at 1-based ordinal position index in a common year of the calendar, is the string-concatenation of "M", ToZeroPaddedDecimalString(index, 2), and "L".

The month codes in the ISO 8601 calendar, which does not have leap months, are "M01" for January through "M12" for December.

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". Theoretically, in a calendar with a leap month at the start of some years, the month code of that month would be "M00L".

22.3.11.1 CreateMonthCode ( monthNumber, isLeapMonth )

The abstract operation CreateMonthCode takes arguments monthNumber (an integer in the inclusive interval from 0 to 99) and isLeapMonth (a Boolean) and returns a month code. It creates a month code with the given month number and leap month flag.

It performs the following steps when called:

  1. Assert: If isLeapMonth is false, monthNumber > 0.
  2. Let numberPart be ToZeroPaddedDecimalString(monthNumber, 2).
  3. If isLeapMonth is true, then
    1. Return the string-concatenation of the code unit 0x004D (LATIN CAPITAL LETTER M), numberPart, and the code unit 0x004C (LATIN CAPITAL LETTER L).
  4. Return the string-concatenation of the code unit 0x004D (LATIN CAPITAL LETTER M) and numberPart.

22.3.11.2 ParseMonthCode ( argument )

The abstract operation ParseMonthCode takes argument argument (an ECMAScript language value) and returns either a normal completion containing a Record with fields [[MonthNumber]] (an integer) and [[IsLeapMonth]] (a Boolean) or a throw completion. It converts argument to a month code and parses it into its parts, or throws a TypeError if conversion to String fails, or throws a RangeError if the result is not a syntactically valid month code. The month code is not guaranteed to be correct in the context of any particular calendar; for example, some calendars do not have leap months.

It performs the following steps when called:

  1. Let monthCode be ? ToPrimitive(argument, string).
  2. If monthCode is not a String, throw a TypeError exception.
  3. If ParseText(monthCode, MonthCode) is not a Parse Node, throw a RangeError exception.
  4. Let isLeapMonth be false.
  5. If the length of monthCode = 4, then
    1. Assert: The fourth code unit of monthCode is 0x004C (LATIN CAPITAL LETTER L).
    2. Set isLeapMonth to true.
  6. Let monthCodeDigits be the substring of monthCode from 1 to 3.
  7. Let monthNumber be (StringToNumber(monthCodeDigits)).
  8. Return the Record { [[MonthNumber]]: monthNumber, [[IsLeapMonth]]: isLeapMonth }.
MonthCode ::: M00L M0 NonZeroDigit Lopt M NonZeroDigit DecimalDigit Lopt

22.3.12 Operations for Reading Options

This section defines abstract operations for reading the properties of options Objects passed to Temporal functions. For example, GetTemporalOverflowOption accesses the "overflow" property of an Object, ensures that it is one of the allowed values "constrain" or "reject", and returns one of the corresponding Enum specification types "constrain" or "reject".

22.3.12.1 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 Temporal units), fallbackSmallestUnit (a Temporal unit), and smallestLargestDefaultUnit (a Temporal unit) and returns either a normal completion containing a Record with fields [[SmallestUnit]] (a Temporal unit), [[LargestUnit]] (a Temporal unit), [[RoundingMode]] (a rounding mode), and [[RoundingIncrement]] (an integer in the inclusive interval from 1 to 109), or a throw completion. It reads unit and rounding options needed by difference operations. It performs the following steps when called:

  1. Let largestUnit be ? GetTemporalUnitValuedOption(options, "largestUnit", optional).
  2. Let roundingIncrement be ? GetRoundingIncrementOption(options).
  3. Let roundingMode be ? GetRoundingModeOption(options, "trunc").
  4. Let smallestUnit be ? GetTemporalUnitValuedOption(options, "smallestUnit", optional).
  5. Perform ? ValidateTemporalUnitValue(largestUnit, unitGroup, « "auto" »).
  6. If largestUnit is no-unit, then
    1. Set largestUnit to "auto".
  7. If disallowedUnits contains largestUnit, throw a RangeError exception.
  8. Perform ? ValidateTemporalUnitValue(smallestUnit, unitGroup).
  9. If smallestUnit is no-unit, then
    1. Set smallestUnit to fallbackSmallestUnit.
  10. If disallowedUnits contains smallestUnit, throw a RangeError exception.
  11. Let defaultLargestUnit be LargerOfTwoTemporalUnits(smallestLargestDefaultUnit, smallestUnit).
  12. If largestUnit is "auto", set largestUnit to defaultLargestUnit.
  13. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
  14. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  15. If maximum is not no-maximum, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  16. If operation is since, then
    1. Set roundingMode to NegateRoundingMode(roundingMode).
  17. Return the Record { [[SmallestUnit]]: smallestUnit, [[LargestUnit]]: largestUnit, [[RoundingMode]]: roundingMode, [[RoundingIncrement]]: roundingIncrement,  }.

22.3.12.2 GetDirectionOption ( options )

The abstract operation GetDirectionOption takes argument options (an Object) and returns either a normal completion containing either "next" or "previous", or a throw completion. It fetches and validates the "direction" property from options, throwing if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "direction").
  2. If value is undefined, throw a RangeError exception.
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not either "next"or "previous", throw a RangeError exception.
  5. Return stringValue.

22.3.12.3 GetRoundingIncrementOption ( options )

The abstract operation GetRoundingIncrementOption takes argument options (an Object) and returns either a normal completion containing a positive integer in the inclusive interval from 1 to 109, or a throw completion. It fetches and validates the "roundingIncrement" property from options, returning 1 if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "roundingIncrement").
  2. If value is undefined, return 1.
  3. Return ? SnapToInteger(value, truncate, 1, 109).

22.3.12.4 GetRoundingModeOption ( options, fallback )

The abstract operation GetRoundingModeOption takes arguments options (an Object) and fallback (a rounding mode) and returns either a normal completion containing a rounding mode, or a throw completion. It fetches and validates the "roundingMode" property from options, returning fallback if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "roundingMode").
  2. If value is undefined, return fallback.
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not a rounding mode, throw a RangeError exception.
  5. Return stringValue.

22.3.12.5 GetTemporalDisambiguationOption ( options )

The abstract operation GetTemporalDisambiguationOption takes argument options (an Object) 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 "compatible" if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "disambiguation").
  2. If value is undefined, return "compatible".
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not one of "compatible", "earlier", "later", or "reject", throw a RangeError exception.
  5. Return stringValue.

22.3.12.6 GetTemporalFractionalSecondDigitsOption ( options )

The abstract operation GetTemporalFractionalSecondDigitsOption takes argument options (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 fetches and validates the "fractionalSecondDigits" property from options, returning auto if absent. It performs the following steps when called:

  1. Let digitsValue be ? Get(options, "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 not finite, throw a RangeError exception.
  5. Let digitCount be floor((digitsValue)).
  6. If digitCount is not in the inclusive interval from 0 to 9, throw a RangeError exception.
  7. Return digitCount.

22.3.12.7 GetTemporalOffsetOption ( options, fallback )

The abstract operation GetTemporalOffsetOption takes arguments options (an Object) 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 if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "offset").
  2. If value is undefined, return fallback.
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not one of "prefer", "use", "ignore", or "reject", throw a RangeError exception.
  5. Return stringValue.

22.3.12.8 GetTemporalOverflowOption ( options )

The abstract operation GetTemporalOverflowOption takes argument options (an Object) 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 "constrain" if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "overflow").
  2. If value is undefined, return "constrain".
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not one of "constrain" or "reject", throw a RangeError exception.
  5. Return stringValue.

22.3.12.9 GetTemporalRelativeToOption ( options )

The abstract operation GetTemporalRelativeToOption takes argument options (an Object) and returns either a normal completion containing a Record with fields [[PlainRelativeTo]] (a Temporal.PlainDate or empty) and [[ZonedRelativeTo]] (a Temporal.ZonedDateTime or empty), 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 empty. 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. It performs the following steps when called:

  1. Let value be ? Get(options, "relativeTo").
  2. If value is undefined, return the Record { [[PlainRelativeTo]]: empty, [[ZonedRelativeTo]]: empty }.
  3. Let offsetBehaviour be option.
  4. Let matchBehaviour be match-exactly.
  5. If value is an Object, then
    1. If value has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return the Record { [[PlainRelativeTo]]: empty, [[ZonedRelativeTo]]: value }.
    2. If value has an [[InitializedTemporalDate]] internal slot, then
      1. Return the Record { [[PlainRelativeTo]]: value, [[ZonedRelativeTo]]: empty }.
    3. If value has an [[InitializedTemporalDateTime]] internal slot, then
      1. Let plainDate be ! CreateTemporalDate(value.[[ISODateTime]].[[ISODate]], value.[[Calendar]]).
      2. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: empty }.
    4. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(value).
    5. Let fields be ? PrepareCalendarFields(calendar, value, date-fields, time-fields-with-time-zone-and-offset, no-required-fields).
    6. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, "constrain").
    7. Let timeZone be fields.[[TimeZone]].
    8. Let offsetString be fields.[[OffsetString]].
    9. If offsetString is empty, then
      1. Set offsetBehaviour to wall.
    10. Let isoDate be result.[[ISODate]].
    11. Let time be result.[[Time]].
  6. Else,
    1. If value is not a String, throw a TypeError exception.
    2. Let result be ? ParseISODateTime(value, any-date-time).
    3. Let offsetString be result.[[TimeZone]].[[OffsetString]].
    4. Let annotation be result.[[TimeZone]].[[TimeZoneAnnotation]].
    5. If annotation is empty, then
      1. Let timeZone be empty.
    6. Else,
      1. Let timeZone be ? ToTemporalTimeZoneIdentifier(annotation).
      2. If result.[[TimeZone]].[[Z]] is true, then
        1. Set offsetBehaviour to exact.
      3. Else if offsetString is empty, then
        1. Set offsetBehaviour to wall.
      4. Set matchBehaviour to match-minutes.
      5. If offsetString is not empty, then
        1. Let offsetParseResult be ParseText(offsetString, UTCOffset[+SubMinutePrecision]).
        2. Assert: offsetParseResult is a Parse Node.
        3. If offsetParseResult contains a Second Parse Node, set matchBehaviour to match-exactly.
    7. Let calendar be result.[[Calendar]].
    8. If calendar is empty, set calendar to "iso8601".
    9. Set calendar to ? CanonicalizeCalendar(calendar).
    10. Let isoDate be ! CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]).
    11. Let time be result.[[Time]].
  7. If timeZone is empty, then
    1. Let plainDate be ? CreateTemporalDate(isoDate, calendar).
    2. Return the Record { [[PlainRelativeTo]]: plainDate, [[ZonedRelativeTo]]: empty }.
  8. If offsetBehaviour is option, then
    1. Assert: offsetString is a String.
    2. Let offsetNanoseconds be ! ParseDateTimeUTCOffset(offsetString).
  9. Else,
    1. Let offsetNanoseconds be 0.
  10. Let epochNanoseconds be ? InterpretISODateTimeOffset(isoDate, time, offsetBehaviour, offsetNanoseconds, timeZone, "compatible", "reject", matchBehaviour).
  11. Let zonedRelativeTo be ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).
  12. Return the Record { [[PlainRelativeTo]]: empty, [[ZonedRelativeTo]]: zonedRelativeTo }.

22.3.12.10 GetTemporalShowCalendarNameOption ( options )

The abstract operation GetTemporalShowCalendarNameOption takes argument options (an Object) and returns either a normal completion containing either "auto", "always", "never", or "critical", or a throw completion. It fetches and validates the "calendarName" property from options, returning "auto" if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "calendarName").
  2. If value is undefined, return "auto".
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not one of "always", "never", "critical", or "auto", throw a RangeError exception.
  5. Return stringValue.

22.3.12.11 GetTemporalShowOffsetOption ( options )

The abstract operation GetTemporalShowOffsetOption takes argument options (an Object) and returns either a normal completion containing either "auto" or "never", or a throw completion. It fetches and validates the "offset" property from options, returning "auto" if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "offset").
  2. If value is undefined, return "auto".
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not either "never" or "auto", throw a RangeError exception.
  5. Return stringValue.

22.3.12.12 GetTemporalShowTimeZoneNameOption ( options )

The abstract operation GetTemporalShowTimeZoneNameOption takes argument options (an Object) and returns either a normal completion containing either "auto", "never", or "critical", or a throw completion. It fetches and validates the "timeZoneName" property from options, returning "auto" if absent. It performs the following steps when called:

  1. Let value be ? Get(options, "timeZoneName").
  2. If value is undefined, return "auto".
  3. Let stringValue be ? ToString(value).
  4. If stringValue is not one of "never", "critical", or "auto", throw a RangeError exception.
  5. Return stringValue.

22.3.12.13 GetTemporalUnitValuedOption ( options, key, default )

The abstract operation GetTemporalUnitValuedOption takes arguments options (an Object), key (a property key), and default (optional or required) and returns either a normal completion containing either a Temporal unit, no-unit, or "auto", or a throw completion. It attempts to read a Temporal unit from the specified property of options.

Both singular and plural unit names are accepted, but only the singular form is used internally.

  1. Let value be ? Get(options, key).
  2. If value is undefined, then
    1. If default is required, throw a RangeError exception.
    2. Return no-unit.
  3. Let stringValue be ? ToString(value).
  4. If stringValue is "auto", return "auto".
  5. If stringValue is either "year" or "years", return "year".
  6. If stringValue is either "month" or "months", return "month".
  7. If stringValue is either "week" or "weeks", return "week".
  8. If stringValue is either "day" or "days", return "day".
  9. If stringValue is either "hour" or "hours", return "hour".
  10. If stringValue is either "minute" or "minutes", return "minute".
  11. If stringValue is either "second" or "seconds", return "second".
  12. If stringValue is either "milllisecond" or "millliseconds", return "milllisecond".
  13. If stringValue is either "microsecond" or "microseconds", return "microsecond".
  14. If stringValue is either "nanosecond" or "nanoseconds", return "nanosecond".
  15. Throw a RangeError exception.

22.3.13 Rounding Modes and Increments

This section contains definitions pertaining to rounding increments and rounding modes. Several Temporal Objects provide the capability of rounding a quantity to a given increment, following different rounding rules.

A rounding mode is one of the values in the “Rounding Mode” column of Table 72. An unsigned rounding mode is one of infinity, zero, half-infinity, half-zero, or half-even.

Table 72: Rounding modes
Rounding Mode 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”.

22.3.13.1 ApplyUnsignedRoundingMode ( quantity, lowerBound, upperBound, unsignedRoundingMode )

The abstract operation ApplyUnsignedRoundingMode takes arguments quantity (a mathematical value), lowerBound (a mathematical value), upperBound (a mathematical value), and unsignedRoundingMode (an unsigned rounding mode) and returns a mathematical value. It considers quantity, bounded below by lowerBound and above by upperBound, and returns either lowerBound or upperBound according to unsignedRoundingMode. It performs the following steps when called:

  1. If quantity = lowerBound, return lowerBound.
  2. Assert: lowerBound < quantity < upperBound.
  3. If unsignedRoundingMode is zero, return lowerBound.
  4. If unsignedRoundingMode is infinity, return upperBound.
  5. Let distanceToLower be quantitylowerBound.
  6. Let distanceToUpper be upperBoundquantity.
  7. If distanceToLower < distanceToUpper, return lowerBound.
  8. If distanceToUpper < distanceToLower, return upperBound.
  9. Assert: distanceToLower is equal to distanceToUpper.
  10. If unsignedRoundingMode is half-zero, return lowerBound.
  11. If unsignedRoundingMode is half-infinity, return upperBound.
  12. Assert: unsignedRoundingMode is half-even.
  13. Let cardinality be (lowerBound / (upperBoundlowerBound)) modulo 2.
  14. If cardinality = 0, return lowerBound.
  15. Return upperBound.

22.3.13.2 GetUnsignedRoundingMode ( roundingMode, sign )

The abstract operation GetUnsignedRoundingMode takes arguments roundingMode (a rounding mode) and sign (negative or positive) and returns an unsigned rounding mode. It returns the unsigned rounding mode that should be applied to the absolute value of a number to produce the same result as if roundingMode 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. If roundingMode is "ceil", then
    1. If sign is positive, return infinity.
    2. Return zero.
  2. If roundingMode is "floor", then
    1. If sign is positive, return zero.
    2. Return infinity.
  3. If roundingMode is "expand", return infinity.
  4. If roundingMode is "trunc", return zero.
  5. If roundingMode is "halfCeil", then
    1. If sign is positive, return half-infinity.
    2. Return half-zero.
  6. If roundingMode is "halfFloor", then
    1. If sign is positive, return half-zero.
    2. Return half-infinity.
  7. If roundingMode is "halfExpand", return half-infinity.
  8. If roundingMode is "halfTrunc", return half-zero.
  9. Assert: roundingMode is "halfEven".
  10. Return half-even.

22.3.13.3 MaximumTemporalDurationRoundingIncrement ( unit )

The abstract operation MaximumTemporalDurationRoundingIncrement takes argument unit (a Temporal unit) and returns 24, 60, 1000, or no-maximum. Given a Temporal unit passed as input to methods that perform duration rounding calculations such as Temporal.Duration.prototype.round (22.15.3.20) or Temporal.PlainDate.prototype.until (22.11.3.25), it returns the maximum rounding increment for that unit, or no-maximum if there is no maximum. It performs the following steps when called:

  1. If unit is "hour", return 24.
  2. If unit is either "minute" or "second", return 60.
  3. If unit is one of "millisecond", "microsecond", or "nanosecond", return 1000.
  4. Return no-maximum.

22.3.13.4 NegateRoundingMode ( roundingMode )

The abstract operation NegateRoundingMode takes argument roundingMode (a rounding mode) and returns a rounding mode. 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.

22.3.13.5 RoundNumberToIncrement ( quantity, increment, roundingMode )

The abstract operation RoundNumberToIncrement takes arguments quantity (a mathematical value), increment (a positive integer), and roundingMode (a rounding mode) and returns an integer. It rounds quantity to the nearest multiple of increment, up or down according to roundingMode. It performs the following steps when called:

  1. Let quotient be quantity / increment.
  2. Let sign be positive.
  3. If quotient < 0, then
    1. Set sign to negative.
    2. Set quotient to -quotient.
  4. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, sign).
  5. Let lowerBound be floor(quotient).
  6. Let upperBound be ceiling(quotient).
  7. Let rounded be ApplyUnsignedRoundingMode(quotient, lowerBound, upperBound, unsignedRoundingMode).
  8. If sign is negative, set rounded to -rounded.
  9. Return rounded × increment.

22.3.13.6 RoundNumberToIncrementAsIfPositive ( quantity, increment, roundingMode )

The abstract operation RoundNumberToIncrementAsIfPositive takes arguments quantity (a mathematical value), increment (a positive integer), and roundingMode (a rounding mode) and returns an integer. It rounds quantity to the nearest multiple of increment, up or down according to roundingMode, but always as if quantity 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 quantity / increment.
  2. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, positive).
  3. Let lowerBound be floor(quotient).
  4. Let upperBound be ceiling(quotient).
  5. Let rounded be ApplyUnsignedRoundingMode(quotient, lowerBound, upperBound, unsignedRoundingMode).
  6. Return rounded × increment.

22.3.13.7 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 checks whether increment evenly divides dividend, throwing a RangeError if it does not. 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, throw a RangeError exception.
  5. Return unused.

22.3.14 Time Durations

A time duration is an integer in the inclusive interval from -MaxTimeDuration to MaxTimeDuration, where MaxTimeDuration = 253 × NanosecondsPerSecond - 1 = 9,007,199,254,740,991,999,999,999 It represents the portion of a duration calculation that deals with time units, but as a combined value of total nanoseconds.

22.3.14.1 Add24HourDaysToTimeDuration ( timeDuration, days )

The abstract operation Add24HourDaysToTimeDuration takes arguments timeDuration (a time duration) and days (an integer) and returns either a normal completion containing a time duration or a throw completion. It returns a time duration that is the sum of timeDuration and the number of 24-hour days indicated by days, throwing an error if the result is not within the range of a time duration. This operation is not used in time zone arithmetic such as Temporal.Duration.prototype.round (22.15.3.20) with a Temporal.ZonedDateTime instance as the relativeTo parameter, since those days may not be 24 hours long. It performs the following steps when called:

  1. Let result be timeDuration + days × NanosecondsPerDay.
  2. If result is not a time duration, throw a RangeError exception.
  3. Return result.

22.3.14.2 AddTimeDuration ( xTimeDuration, yTimeDuration )

The abstract operation AddTimeDuration takes arguments xTimeDuration (a time duration) and yTimeDuration (a time duration) and returns either a normal completion containing a time duration or a throw completion. It returns a time duration that is the sum of xTimeDuration and yTimeDuration, throwing an error if the result is not within the range of a time duration. It performs the following steps when called:

  1. Let result be xTimeDuration + yTimeDuration.
  2. If result is not a time duration, throw a RangeError exception.
  3. Return result.

22.3.14.3 AddTimeDurationToEpochNanoseconds ( timeDuration, epochNanoseconds )

The abstract operation AddTimeDurationToEpochNanoseconds takes arguments timeDuration (a time duration) and epochNanoseconds (an epoch nanoseconds count) and returns an integer. It adds a time duration to an epoch nanoseconds count and returns a new exact time, which is not required to be within the inclusive interval from MinEpochNanoseconds to MaxEpochNanoseconds. It performs the following steps when called:

  1. Return timeDuration + epochNanoseconds.

22.3.14.4 RoundTimeDuration ( timeDuration, increment, unit, roundingMode )

The abstract operation RoundTimeDuration takes arguments timeDuration (a time duration), increment (a positive integer), unit (a time unit), and roundingMode (a rounding mode) and returns either a normal completion containing a time duration, or a throw completion. It rounds a timeDuration according to the rounding parameters unit, increment, and roundingMode, and returns the time duration result. It performs the following steps when called:

  1. Return ? RoundTimeDurationToIncrement(timeDuration, TemporalUnitLength(unit) × increment, roundingMode).

22.3.14.5 RoundTimeDurationToIncrement ( timeDuration, increment, roundingMode )

The abstract operation RoundTimeDurationToIncrement takes arguments timeDuration (a time duration), increment (a positive integer), and roundingMode (a rounding mode) and returns either a normal completion containing a time duration or a throw completion. It rounds the total number of nanoseconds in the time duration timeDuration to the nearest multiple of increment, up or down according to roundingMode. It performs the following steps when called:

  1. Let rounded be RoundNumberToIncrement(timeDuration, increment, roundingMode).
  2. If rounded is not a time duration, throw a RangeError exception.
  3. Return rounded.

22.3.14.6 TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, microseconds, nanoseconds )

The abstract operation TimeDurationFromComponents takes arguments hours (an integer), minutes (an integer), seconds (an integer), milliseconds (an integer), microseconds (an integer), and nanoseconds (an integer) and returns either a normal completion containing a time duration, or a throw completion. From the given units, it computes a time duration consisting of total nanoseconds. The time duration can be stored losslessly in two 64-bit floating point numbers consisting of truncate(nanoseconds / NanosecondsPerSecond) and remainder(nanoseconds, NanosecondsPerSecond). Alternatively, nanoseconds 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. If nanoseconds is not a time duration, throw a RangeError exception.
  7. Return nanoseconds.

22.3.14.7 TimeDurationFromEpochNanosecondsDifference ( epochNanosecondsFrom, epochNanosecondsTo )

The abstract operation TimeDurationFromEpochNanosecondsDifference takes arguments epochNanosecondsFrom (an epoch nanoseconds count) and epochNanosecondsTo (an epoch nanoseconds count) and returns a time duration. The returned time duration is the difference between two epoch nanoseconds counts, which must be within the range of a time duration. It performs the following steps when called:

  1. Let result be epochNanosecondsTo - epochNanosecondsFrom.
  2. Assert: result is a time duration.
  3. Return result.

22.3.14.8 TimeDurationSign ( timeDuration )

The abstract operation TimeDurationSign takes argument timeDuration (a time duration) 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 timeDuration < 0, return -1.
  2. If timeDuration > 0, return 1.
  3. Return 0.

22.3.14.9 TotalTimeDuration ( timeDuration, unit )

The abstract operation TotalTimeDuration takes arguments timeDuration (a time duration) and unit (either a time unit or "day") and returns a mathematical value. It returns the total number of unit in duration. It performs the following steps when called:

  1. Return timeDuration / TemporalUnitLength(unit).
Note
This operation cannot be implemented directly using floating-point arithmetic when 𝔽(timeDuration) 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.

22.3.15 Time Records

A Time Record is a Record 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.

Most uses of Time Records ignore the [[Days]] field. The [[Days]] field is only used to indicate an overflow number of days when performing arithmetic in BalanceTime and RoundTime.

Time Records have the fields listed in Table 73.

Table 73: Time Record Fields
Field Name Value Meaning
[[Days]] an integer A number of days resulting from an overflow when the Time Record is the result of an arithmetic operation.
[[Hour]] an integer in the inclusive interval from 0 to 23 The number of the hour.
[[Minute]] an integer in the inclusive interval from 0 to 59 The number of the minute.
[[Second]] an integer in the inclusive interval from 0 to 59 The number of the second.
[[Millisecond]] an integer in the inclusive interval from 0 to 999 The number of the millisecond.
[[Microsecond]] an integer in the inclusive interval from 0 to 999 The number of the microsecond.
[[Nanosecond]] an integer in the inclusive interval from 0 to 999 The number of the nanosecond.

22.3.15.1 AddTime ( time, timeDuration )

The abstract operation AddTime takes arguments time (a Time Record) and timeDuration (a time duration) and returns a Time Record. It performs the following steps when called:

  1. Return BalanceTime(time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], time.[[Microsecond]], time.[[Nanosecond]] + timeDuration).

22.3.15.2 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 deltaDays be floor(hour / 24).
  12. Set hour to hour modulo 24.
  13. Return ! CreateTimeRecord(hour, minute, second, millisecond, microsecond, nanosecond, deltaDays).

22.3.15.3 CompareTimeRecord ( xTime, yTime )

The abstract operation CompareTimeRecord takes arguments xTime (a Time Record) and yTime (a Time Record) and returns -1, 0, or 1. It compares the two given times, returning -1 if yTime comes later in the day than xTime, 1 if xTime comes later in the day than yTime, and 0 if they are the same. It performs the following steps when called:

  1. If xTime.[[Hour]] > yTime.[[Hour]], return 1.
  2. If xTime.[[Hour]] < yTime.[[Hour]], return -1.
  3. If xTime.[[Minute]] > yTime.[[Minute]], return 1.
  4. If xTime.[[Minute]] < yTime.[[Minute]], return -1.
  5. If xTime.[[Second]] > yTime.[[Second]], return 1.
  6. If xTime.[[Second]] < yTime.[[Second]], return -1.
  7. If xTime.[[Millisecond]] > yTime.[[Millisecond]], return 1.
  8. If xTime.[[Millisecond]] < yTime.[[Millisecond]], return -1.
  9. If xTime.[[Microsecond]] > yTime.[[Microsecond]], return 1.
  10. If xTime.[[Microsecond]] < yTime.[[Microsecond]], return -1.
  11. If xTime.[[Nanosecond]] > yTime.[[Nanosecond]], return 1.
  12. If xTime.[[Nanosecond]] < yTime.[[Nanosecond]], return -1.
  13. Return 0.

22.3.15.4 CreateTimeRecord ( hour, minute, second, millisecond, microsecond, nanosecond [ , deltaDays ] )

The abstract operation CreateTimeRecord takes arguments 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 deltaDays (an integer) and returns either a normal completion containing a Time Record or a throw completion. The deltaDays parameter indicates an overflow number of days when the Time Record represents the result of an arithmetic operation. In all other cases it is 0. It performs the following steps when called:

  1. If deltaDays is not present, set deltaDays to 0.
  2. If IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
  3. Return the Time Record { [[Days]]: deltaDays, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }.

22.3.15.5 DifferenceTime ( timeFrom, timeTo )

The abstract operation DifferenceTime takes arguments timeFrom (a Time Record) and timeTo (a Time Record) and returns a time duration. It returns 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 timeTo.[[Hour]] - timeFrom.[[Hour]].
  2. Let minutes be timeTo.[[Minute]] - timeFrom.[[Minute]].
  3. Let seconds be timeTo.[[Second]] - timeFrom.[[Second]].
  4. Let milliseconds be timeTo.[[Millisecond]] - timeFrom.[[Millisecond]].
  5. Let microseconds be timeTo.[[Microsecond]] - timeFrom.[[Microsecond]].
  6. Let nanoseconds be timeTo.[[Nanosecond]] - timeFrom.[[Nanosecond]].
  7. Let timeDuration be ! TimeDurationFromComponents(hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
  8. Assert: timeDuration is in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive).
  9. Return timeDuration.

22.3.15.6 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. It returns 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 is not in the inclusive interval from 0 to 23, return false.
  2. If minute is not in the inclusive interval from 0 to 59, return false.
  3. If second is not in the inclusive interval from 0 to 59, return false.
  4. If millisecond is not in the inclusive interval from 0 to 999, return false.
  5. If microsecond is not in the inclusive interval from 0 to 999, return false.
  6. If nanosecond is not in the inclusive interval from 0 to 999, return false.
  7. Return true.

22.3.15.7 MidnightTimeRecord ( )

The abstract operation MidnightTimeRecord takes no arguments and returns a Time Record. The returned Record denotes the wall-clock time of midnight. It performs the following steps when called:

  1. Return the Time Record { [[Days]]: 0, [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0  }.

22.3.15.8 NoonTimeRecord ( )

The abstract operation NoonTimeRecord takes no arguments and returns a Time Record. The returned Record denotes the wall-clock time of noon. It performs the following steps when called:

  1. Return the Time Record { [[Days]]: 0, [[Hour]]: 12, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0  }.

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

The abstract operation RegulateTime takes arguments hour (an integer), minute (an integer), second (an integer), millisecond (an integer), microsecond (an integer), nanosecond (an integer), and overflow ("constrain" or "reject") and returns either a normal completion containing a Time Record or a throw completion. It applies the correction given by overflow to the given time. If overflow is "constrain", out-of-range values are clamped. If overflow is "reject", a RangeError is thrown if any values are out of range. It performs the following steps when called:

  1. If overflow is "constrain", then
    1. Set hour to the result of clamping hour between 0 and 23.
    2. Set minute to the result of clamping minute between 0 and 59.
    3. Set second to the result of clamping second between 0 and 59.
    4. Set millisecond to the result of clamping millisecond between 0 and 999.
    5. Set microsecond to the result of clamping microsecond between 0 and 999.
    6. Set nanosecond to the result of clamping nanosecond between 0 and 999.
    7. Return ! CreateTimeRecord(hour, minute, second, millisecond, microsecond,nanosecond).
  2. Assert: overflow is "reject".
  3. Return ? CreateTimeRecord(hour, minute, second, millisecond, microsecond,nanosecond).

22.3.15.10 RoundTime ( time, increment, unit, roundingMode )

The abstract operation RoundTime takes arguments time (a Time Record), increment (a positive integer), unit (either a time unit or "day"), and roundingMode (a rounding mode) and returns a Time Record. It rounds a time to the given increment. It performs the following steps when called:

  1. Let quantity be 0.
  2. If unit is either "day" or "hour", then
    1. Set quantity to time.[[Hour]] × NanosecondsPerHour.
  3. If unit is one of "day", "hour", or "minute", then
    1. Set quantity to quantity + time.[[Minute]] × NanosecondsPerMinute.
  4. If unit is one of "day", "hour", "minute", or "second", then
    1. Set quantity to quantity + time.[[Second]] × NanosecondsPerSecond.
  5. If unit is one of "day", "hour", "minute", "second", or "millisecond", then
    1. Set quantity to quantity + time.[[Millisecond]] × NanosecondsPerMillisecond.
  6. If unit is one of "day", "hour", "minute", "second", "millisecond", or "microsecond", then
    1. Set quantity to quantity + time.[[Microsecond]] × NanosecondsPerMicrosecond.
  7. Set quantity to quantity + time.[[Nanosecond]].
  8. Let unitLength be TemporalUnitLength(unit).
  9. Let result be RoundNumberToIncrement(quantity, increment × unitLength, roundingMode) / unitLength.
  10. If unit is "day", return ! CreateTimeRecord(0, 0, 0, 0, 0, 0, result).
  11. If unit is "hour", return BalanceTime(result, 0, 0, 0, 0, 0).
  12. If unit is "minute", return BalanceTime(time.[[Hour]], result, 0, 0, 0, 0).
  13. If unit is "second", return BalanceTime(time.[[Hour]], time.[[Minute]], result, 0, 0, 0).
  14. If unit is "millisecond", return BalanceTime(time.[[Hour]], time.[[Minute]], time.[[Second]], result, 0, 0).
  15. If unit is "microsecond", return BalanceTime(time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], result, 0).
  16. Assert: unit is "nanosecond".
  17. Return BalanceTime(time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], time.[[Microsecond]], result).

22.3.15.11 TimeRecordToString ( time, precision )

The abstract operation TimeRecordToString takes arguments time (a Time Record) and precision (either an integer in the inclusive interval from 0 to 9, minute, or auto) and returns a String. It formats the given time as an ISO 8601 string, to the precision specified by precision. It performs the following steps when called:

  1. Let subSecondNanoseconds be time.[[Millisecond]] × NanosecondsPerMillisecond + time.[[Microsecond]] × NanosecondsPerMicrosecond + time.[[Nanosecond]].
  2. Return FormatTimeString(time.[[Hour]], time.[[Minute]], time.[[Second]], subSecondNanoseconds, precision).

22.3.15.12 Partial Time Records

A partial Time Record is a Record used to represent input used for constructing a Temporal.PlainTime object (such as input passed to Temporal.PlainTime.prototype.with, 22.12.3.11), in which it is not required that all the fields be present or in the correct interval.

Partial Time Records have the fields listed in Table 74. Additionally, partial Time Records must have at least one field that is not empty.

Table 74: Partial Time Record Fields
Field Name Value Meaning
[[Hour]] an integer or empty The number of the hour, if present.
[[Minute]] an integer or empty The number of the minute, if present.
[[Second]] an integer or empty The number of the second, if present.
[[Millisecond]] an integer or empty The number of the millisecond, if present.
[[Microsecond]] an integer or empty The number of the microsecond, if present.
[[Nanosecond]] an integer or empty The number of the nanosecond, if present.

22.3.15.13 ToPartialTimeRecord ( temporalTimeLike, completeness )

The abstract operation ToPartialTimeRecord takes arguments temporalTimeLike (an Object) and completeness (partial or complete) and returns either a normal completion containing a partial Time Record or a throw completion. It performs the following steps when called:

  1. If completeness is complete, then
    1. Let result be the partial Time Record { [[Hour]]: 0, [[Minute]]: 0, [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: 0  }.
  2. Else,
    1. Let result be the partial Time Record { [[Hour]]: empty, [[Minute]]: empty, [[Second]]: empty, [[Millisecond]]: empty, [[Microsecond]]: empty, [[Nanosecond]]: empty  }.
  3. Let anyPresent be false.
  4. Let hour be ? Get(temporalTimeLike, "hour").
  5. If hour is not undefined, then
    1. Set result.[[Hour]] to ? SnapToInteger(hour, truncate).
    2. Set anyPresent to true.
  6. Let microsecond be ? Get(temporalTimeLike, "microsecond").
  7. If microsecond is not undefined, then
    1. Set result.[[Microsecond]] to ? SnapToInteger(microsecond, truncate).
    2. Set anyPresent to true.
  8. Let millisecond be ? Get(temporalTimeLike, "millisecond").
  9. If millisecond is not undefined, then
    1. Set result.[[Millisecond]] to ? SnapToInteger(millisecond, truncate).
    2. Set anyPresent to true.
  10. Let minute be ? Get(temporalTimeLike, "minute").
  11. If minute is not undefined, then
    1. Set result.[[Minute]] to ? SnapToInteger(minute, truncate).
    2. Set anyPresent to true.
  12. Let nanosecond be ? Get(temporalTimeLike, "nanosecond").
  13. If nanosecond is not undefined, then
    1. Set result.[[Nanosecond]] to ? SnapToInteger(nanosecond, truncate).
    2. Set anyPresent to true.
  14. Let second be ? Get(temporalTimeLike, "second").
  15. If second is not undefined, then
    1. Set result.[[Second]] to ? SnapToInteger(second, truncate).
    2. Set anyPresent to true.
  16. If anyPresent is false, throw a TypeError exception.
  17. Return result.

22.3.15.14 ToTimeRecordOrMidnight ( item )

The abstract operation ToTimeRecordOrMidnight takes argument item (an ECMAScript language value) and returns either a normal completion containing a Time Record or a throw completion. Converts item to a Time Record if possible, considering undefined to be the same as midnight, and throws otherwise. It performs the following steps when called:

  1. If item is undefined, return MidnightTimeRecord().
  2. Let plainTime be ? ToTemporalTime(item).
  3. Return plainTime.[[Time]].

22.3.16 Units

Time is reckoned using multiple units. A Temporal unit is one of "year", "month", "week", "day", "hour", "minute", "second", "millisecond", "microsecond", or "nanosecond". A calendar unit is one of "year", "month", or "week". A date unit is either a calendar unit or "day", and a time unit is one of "hour", "minute", "second", "millisecond", "microsecond", or "nanosecond".

22.3.16.1 DefaultTemporalLargestUnit ( duration )

The abstract operation DefaultTemporalLargestUnit takes argument duration (a Temporal.Duration) and returns a Temporal unit. It implements the logic used in the Temporal.Duration.prototype.round method (22.15.3.20) and elsewhere, where the largestUnit option, if not given explicitly, is set to the largest-magnitude non-zero unit, or "nanosecond" for a zero-length duration. It performs the following steps when called:

  1. If duration.[[Years]] ≠ 0, return "year".
  2. If duration.[[Months]] ≠ 0, return "month".
  3. If duration.[[Weeks]] ≠ 0, return "week".
  4. If duration.[[Days]] ≠ 0, return "day".
  5. If duration.[[Hours]] ≠ 0, return "hour".
  6. If duration.[[Minutes]] ≠ 0, return "minute".
  7. If duration.[[Seconds]] ≠ 0, return "second".
  8. If duration.[[Milliseconds]] ≠ 0, return "millisecond".
  9. If duration.[[Microseconds]] ≠ 0, return "microsecond".
  10. Return "nanosecond".

22.3.16.2 LargerOfTwoTemporalUnits ( xUnit, yUnit )

The abstract operation LargerOfTwoTemporalUnits takes arguments xUnit (a Temporal unit) and yUnit (a Temporal unit) and returns a Temporal unit. Given two Temporal units, it returns the larger of the two units. It performs the following steps when called:

  1. If xUnit is "year" or yUnit is "year", return "year".
  2. If xUnit is "month" or yUnit is "month", return "month".
  3. If xUnit is "week" or yUnit is "week", return "week".
  4. If xUnit is "day" or yUnit is "day", return "day".
  5. If xUnit is "hour" or yUnit is "hour", return "hour".
  6. If xUnit is "minute" or yUnit is "minute", return "minute".
  7. If xUnit is "second" or yUnit is "second", return "second".
  8. If xUnit is "millisecond" or yUnit is "millisecond", return "millisecond".
  9. If xUnit is "microsecond" or yUnit is "microsecond", return "microsecond".
  10. Return "nanosecond".

22.3.16.3 TemporalUnitLength ( unit )

The abstract operation TemporalUnitLength takes argument unit (a time unit or "day") and returns a positive integer. It returns the length of unit in nanoseconds. It performs the following steps when called:

  1. If unit is "day", return NanosecondsPerDay.
  2. If unit is "hour", return NanosecondsPerHour.
  3. If unit is "minute", return NanosecondsPerMinute.
  4. If unit is "second", return NanosecondsPerSecond.
  5. If unit is "millisecond", return NanosecondsPerMillisecond.
  6. If unit is "microsecond", return NanosecondsPerMicrosecond.
  7. Assert: unit is "nanosecond".
  8. Return 1.
Note
The length of the "day" unit is considered to be NanosecondsPerDay. Note that changes in the UTC offset of a time zone may result in longer or shorter days, so care should be taken when using this value in the context of Temporal.ZonedDateTime arithmetic.

22.3.16.4 ValidateTemporalUnitValue ( value, unitGroup [ , extraValues ] )

The abstract operation ValidateTemporalUnitValue takes arguments value (either a Temporal unit, no-unit, or "auto") and unitGroup (date, time, or datetime) and optional argument extraValues (a List of either Temporal units or "auto") and returns either a normal completion containing unused or a throw completion. It validates that the result of GetTemporalUnitValuedOption is covered by the union of unitGroup, extraValues, and « no-unit ». It performs the following steps when called:

  1. If value is no-unit, return unused.
  2. If extraValues is present and extraValues contains value, return unused.
  3. If value is a date unit and unitGroup is either date or datetime, return unused.
  4. If value is a time unit and unitGroup is either time or datetime, return unused.
  5. Throw a RangeError exception.

22.3.17 IsPartialTemporalObject ( value )

The abstract operation IsPartialTemporalObject takes argument value (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 plain or zoned Temporal types' with() methods (22.11.3.23, 22.10.3.25, 22.14.3.6, 22.12.3.11, 22.13.3.13, 22.9.3.31): it must be an Object, it must not be an instance of one of those 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. NOTE: The following step accepts Temporal.Duration and Temporal.Instant, but rejects all other Temporal types.
  3. If value has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, return false.
  4. Let calendarProperty be ? Get(value, "calendar").
  5. If calendarProperty is not undefined, return false.
  6. Let timeZoneProperty be ? Get(value, "timeZone").
  7. If timeZoneProperty is not undefined, return false.
  8. Return true.

22.4 Parsing ISO 8601 / RFC 9557 Strings

Several operations in this section are intended to parse strings representing a date, a time, a duration, or a combined date and time. For the purposes of these operations, a valid ISO 8601 / RFC 9557 string is defined as a String that can be generated by one of the goal elements of the following grammar.

22.4.1 ISO 8601 / RFC 9557 Grammar

This grammar is adapted from the ABNF grammar of the ISO 8601 date-time format that is given in appendix A of RFC 3339, augmented with the grammar of annotations in section 4.1 of RFC 9557.

RFC 9557 and ISO 8601 are similar, but ISO 8601 defines a number of optional deviations that are allowed “by agreement between the communicating parties”. The following is a list of deviations supported by this grammar:

  • 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.
  • 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 ISO 8601 as requiring mutual agreement between communicating parties, is disallowed.

In addition to the above deviations, any number of conforming RFC 9557 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.

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 DateSeparator[Extended] ::: [+Extended] - [~Extended] [empty] 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 ASCIISign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit

Note the prohibition on negative zero in 22.4.1.3.

DateMonth ::: 0 NonZeroDigit 10 11 12 DateDay ::: 0 NonZeroDigit 1 DecimalDigit 2 DecimalDigit 30 31 DateSpecYearMonth ::: DateYear DateSeparator[+Extended] DateMonth DateYear DateSeparator[~Extended] DateMonth DateSpecMonthDay ::: --opt DateMonth DateSeparator[+Extended] DateDay --opt DateMonth DateSeparator[~Extended] DateDay

Note the prohibition on invalid combinations of month and day in 22.4.1.3.

DateSpec[Extended] ::: DateYear DateSeparator[?Extended] DateMonth DateSeparator[?Extended] DateDay

Note the prohibition on invalid combinations of month and day in 22.4.1.3.

Date ::: DateSpec[+Extended] DateSpec[~Extended] TimeSecond ::: Second 60 UTCOffset[SubMinutePrecision] ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[?SubMinutePrecision, +Extended] ASCIISign Hour HourSubcomponents[?SubMinutePrecision, ~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[SubMinutePrecision, Extended] ::: TimeSeparator[?Extended] Minute [+SubMinutePrecision] TimeSeparator[?Extended] Minute TimeSeparator[?Extended] Second TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] Minute ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit Second ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . , DateTimeUTCOffset[Z] ::: [+Z] UTCDesignator UTCOffset[+SubMinutePrecision] TZLeadingChar ::: Alpha . _ TZChar ::: TZLeadingChar DecimalDigit - + TimeZoneIANANameComponent ::: TZLeadingChar TimeZoneIANANameComponent TZChar TimeZoneIANAName ::: TimeZoneIANANameComponent TimeZoneIANAName / TimeZoneIANANameComponent TimeZoneIdentifier ::: UTCOffset[~SubMinutePrecision] TimeZoneIANAName NormalizedUTCOffset ::: ASCIISign Hour TimeSeparator[+Extended] Minute but not -00:00 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[Extended] ::: Hour Hour TimeSeparator[?Extended] Minute Hour TimeSeparator[?Extended] Minute TimeSeparator[?Extended] TimeSecond TemporalDecimalFractionopt Time ::: TimeSpec[+Extended] TimeSpec[~Extended] DateTime[Z, TimeRequired] ::: [~TimeRequired] Date Date DateTimeSeparator Time DateTimeUTCOffset[?Z]opt AnnotatedTime ::: TimeDesignator Time DateTimeUTCOffset[~Z]opt TimeZoneAnnotationopt Annotationsopt Time DateTimeUTCOffset[~Z]opt TimeZoneAnnotationopt Annotationsopt

Note the disambiguation between the second alternative without TimeDesignator, and DateSpecMonthDay/DateSpecYearMonth in 22.4.1.3.

AnnotatedDateTime[Zoned, TimeRequired] ::: [~Zoned] DateTime[~Z, ?TimeRequired] TimeZoneAnnotationopt Annotationsopt [+Zoned] DateTime[+Z, ?TimeRequired] TimeZoneAnnotation Annotationsopt DurationSecondsPart ::: DecimalDigits[~Sep] TemporalDecimalFractionopt SecondsDesignator DurationMinutesPart ::: DecimalDigits[~Sep] TemporalDecimalFraction MinutesDesignator DecimalDigits[~Sep] MinutesDesignator DurationSecondsPartopt DurationHoursPart ::: DecimalDigits[~Sep] TemporalDecimalFraction HoursDesignator DecimalDigits[~Sep] HoursDesignator DurationMinutesPart DecimalDigits[~Sep] HoursDesignator DurationSecondsPartopt DurationTime ::: TimeDesignator DurationHoursPart TimeDesignator DurationMinutesPart TimeDesignator DurationSecondsPart DurationDaysPart ::: DecimalDigits[~Sep] DaysDesignator DurationWeeksPart ::: DecimalDigits[~Sep] WeeksDesignator DurationDaysPartopt DurationMonthsPart ::: DecimalDigits[~Sep] MonthsDesignator DurationWeeksPart DecimalDigits[~Sep] MonthsDesignator DurationDaysPartopt DurationYearsPart ::: DecimalDigits[~Sep] YearsDesignator DurationMonthsPart DecimalDigits[~Sep] YearsDesignator DurationWeeksPart DecimalDigits[~Sep] YearsDesignator DurationDaysPartopt DurationDate ::: DurationYearsPart DurationTimeopt DurationMonthsPart DurationTimeopt DurationWeeksPart DurationTimeopt DurationDaysPart DurationTimeopt TemporalInstantString ::: Date DateTimeSeparator Time DateTimeUTCOffset[+Z] TimeZoneAnnotationopt Annotationsopt TemporalDateTimeString[Zoned] ::: AnnotatedDateTime[?Zoned, ~TimeRequired] TemporalDurationString ::: ASCIISignopt DurationDesignator DurationDate ASCIISignopt DurationDesignator DurationTime TemporalMonthDayString ::: DateSpecMonthDay TimeZoneAnnotationopt Annotationsopt AnnotatedDateTime[~Zoned, ~TimeRequired] TemporalTimeString ::: AnnotatedTime AnnotatedDateTime[~Zoned, +TimeRequired] TemporalYearMonthString ::: DateSpecYearMonth TimeZoneAnnotationopt Annotationsopt AnnotatedDateTime[~Zoned, ~TimeRequired]

Grammar symbols not explicitly defined above (NonZeroDigit, DecimalDigit, DecimalDigits) have the definitions used in the Lexical Grammar for numeric literals (12.9.3).

22.4.1.1 Static Semantics: IsValidMonthDay

The syntax-directed operation IsValidMonthDay takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

DateSpec[Extended] ::: DateYear DateSeparator[?Extended] DateMonth DateSeparator[?Extended] DateDay DateSpecMonthDay ::: --opt DateMonth DateSeparator[+Extended] DateDay --opt DateMonth DateSeparator[~Extended] DateDay
  1. If DateDay is "31" and DateMonth is "02", "04", "06", "09", "11", return false.
  2. If DateMonth is "02" and DateDay is "30", return false.
  3. Return true.

22.4.1.2 Static Semantics: IsValidDate

The syntax-directed operation IsValidDate takes no arguments and returns a Boolean. It is defined piecewise over the following productions:

DateSpec[Extended] ::: DateYear DateSeparator[?Extended] DateMonth DateSeparator[?Extended] DateDay
  1. If IsValidMonthDay of DateSpec is false, return false.
  2. Let year be (StringToNumber(CodePointsToString(DateYear))).
  3. If DateMonth is "02" and DateDay is "29" and InLeapYear(TimeFromYear(year)) = 0, return false.
  4. Return true.

22.4.1.3 Static Semantics: Early Errors

AnnotatedTime ::: Time DateTimeUTCOffset[~Z]opt TimeZoneAnnotationopt Annotationsopt DateSpec[Extended] ::: DateYear DateSeparator[?Extended] DateMonth DateSeparator[?Extended] DateDay DateSpecMonthDay ::: --opt DateMonth DateSeparator[+Extended] DateDay --opt DateMonth DateSeparator[~Extended] DateDay DateYear ::: ASCIISign DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit
  • It is a Syntax Error if DateYear is "-000000".

22.4.2 RFC 9557 Time Zone Parse Records

A RFC 9557 Time Zone Parse Record is a Record used to represent the result of parsing the representation of the time zone in an ISO 8601 / RFC 9557 string.

RFC 9557 Time Zone Parse Records have the fields listed in Table 75.

Table 75: RFC 9557 Time Zone Parse Record Fields
Field Name Value Meaning
[[Z]] a Boolean Whether the string contained the Z UTC designator.
[[OffsetString]] a String or empty The UTC offset from the string, or empty if none was present.
[[TimeZoneAnnotation]] a String or empty The time zone annotation from the string, or empty if none was present.

22.4.3 Time Zone Identifier Parse Records

A Time Zone Identifier Parse Record is a Record used to represent the result of parsing a time zone identifier either as an offset time zone or named time zone.

Time Zone Identifier Parse Records have the fields listed in Table 76.

The two fields are mutually exclusive. One of them always has the value empty.

Table 76: Time Zone Identifier Parse Record Fields
Field Name Value Meaning
[[Name]] a String or empty The time zone's name (not necessarily an available named time zone identifier), or empty if the time zone is an offset time zone.
[[OffsetMinutes]] an integer in the inclusive interval from -1439 to 1439, or empty The time zone's UTC offset expressed as a number of minutes, or empty if the time zone is a named time zone.

22.4.4 ISO Date-Time Parse Records

An ISO Date-Time Parse Record is a Record used to represent the result of parsing an ISO 8601 / RFC 9557 string.

For any ISO Date-Time Parse Record r, IsValidISODate(r.[[Year]], r.[[Month]], r.[[Day]]) must return true, or, if r.[[Year]] is empty, IsValidISODate(1972, r.[[Month]], r.[[Day]]) must return true. It is not necessary for the represented date and time to be within the range given by ISODateTimeWithinLimits.

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

Table 77: ISO Date-Time Parse Record Fields
Field Name Value Meaning
[[Year]] an integer or empty The year in the ISO 8601 calendar, or empty if the string's format was that of TemporalMonthDayString and the year was omitted.
[[Month]] an integer in the inclusive interval from 1 to 12 The number of the month in the ISO 8601 calendar.
[[Day]] an integer in the inclusive interval from 1 to 31 The number of the day of the month in the ISO 8601 calendar.
[[Time]] either a Time Record with [[Days]] value 0, or start-of-day The time of day, or start-of-day if the time was omitted from the string.
[[TimeZone]] an RFC 9557 Time Zone Parse Record A representation of how the time zone was expressed in the string.
[[Calendar]] a calendar type or empty The calendar type from the string, or empty if none was present.

22.4.5 ParseISODateTime ( isoString, allowedFormats )

The abstract operation ParseISODateTime takes arguments isoString (a String) and allowedFormats (all, any-date-time, zoned-date-time, plain-date-time, instant, time, year-month, or month-day) and returns either a normal completion containing an ISO Date-Time Parse Record or a throw completion. It parses the argument as an ISO 8601 / RFC 9557 string and returns a Record representing each date and time component as a distinct field. It performs the following steps when called:

  1. Let parseResult be empty.
  2. Let calendar be empty.
  3. Let yearAbsent be false.
  4. If allowedFormats is all, then
    1. Let goalSymbols be « TemporalDateTimeString[+Zoned], TemporalDateTimeString[~Zoned], TemporalInstantString, TemporalTimeString, TemporalMonthDayString, TemporalYearMonthString ».
  5. Else if allowedFormats is any-date-time, then
    1. Let goalSymbols be « TemporalDateTimeString[+Zoned], TemporalDateTimeString[~Zoned] ».
  6. Else if allowedFormats is zoned-date-time, then
    1. Let goalSymbols be « TemporalDateTimeString[+Zoned] ».
  7. Else if allowedFormats is plain-date-time, then
    1. Let goalSymbols be « TemporalDateTimeString[~Zoned] ».
  8. Else if allowedFormats is instant, then
    1. Let goalSymbols be « TemporalInstantString ».
  9. Else if allowedFormats is time, then
    1. Let goalSymbols be « TemporalTimeString ».
  10. Else if allowedFormats is year-month, then
    1. Let goalSymbols be « TemporalYearMonthString ».
  11. Else if allowedFormats is month-day, then
    1. Let goalSymbols be « TemporalMonthDayString ».
  12. For each goal symbol goal of goalSymbols, do
    1. If parseResult is not a Parse Node, then
      1. Set parseResult to ParseText(isoString, goal).
      2. If parseResult is a Parse Node, then
        1. Let calendarWasCritical be false.
        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", then
            1. If calendar is empty, then
              1. Set calendar to CodePointsToString(value).
              2. 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.
          4. Else,
            1. If annotation contains an AnnotationCriticalFlag Parse Node, throw a RangeError exception.
        3. If parseResult does not contain an AnnotatedDateTime Parse Node and goal is TemporalYearMonthString or TemporalMonthDayString, then
          1. If calendar is not empty and the ASCII-lowercase of calendar is not "iso8601", throw a RangeError exception.
          2. If goal is TemporalMonthDayString, set yearAbsent to true.
  13. If parseResult is not a Parse Node, throw a RangeError exception.
  14. 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.
  15. Let each of year, month, and day be the source text matched by the respective DateYear, DateMonth, and DateDay Parse Node contained within parseResult, or an empty sequence of code points if not present.
  16. If a Time Parse Node is contained within parseResult, then
    1. Let parsedTime be the Time contained within parseResult.
    2. Let each of hour, minute, second, and fSeconds be the source text matched by the respective Hour, Minute, TimeSecond, and TemporalDecimalFraction Parse Node contained within parsedTime, or an empty sequence of code points if not present.
  17. Else,
    1. Let each of hour, minute, second, and fSeconds be an empty sequence of code points.
  18. Let yearMV be (StringToNumber(CodePointsToString(year))).
  19. If month is empty, then
    1. Let monthMV be 1.
  20. Else,
    1. Let monthMV be (StringToNumber(CodePointsToString(month))).
  21. If day is empty, then
    1. Let dayMV be 1.
  22. Else,
    1. Let dayMV be (StringToNumber(CodePointsToString(day))).
  23. If hour is empty, then
    1. Let hourMV be 0.
  24. Else,
    1. Let hourMV be (StringToNumber(CodePointsToString(hour))).
  25. If minute is empty, then
    1. Let minuteMV be 0.
  26. Else,
    1. Let minuteMV be (StringToNumber(CodePointsToString(minute))).
  27. If second is empty, then
    1. Let secondMV be 0.
  28. Else,
    1. Let secondMV be (StringToNumber(CodePointsToString(second))).
    2. If secondMV = 60, then
      1. Set secondMV to 59.
  29. 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 (StringToNumber(millisecond)).
    7. Let microsecondMV be (StringToNumber(microsecond)).
    8. Let nanosecondMV be (StringToNumber(nanosecond)).
  30. Else,
    1. Let millisecondMV be 0.
    2. Let microsecondMV be 0.
    3. Let nanosecondMV be 0.
  31. Assert: IsValidISODate(yearMV, monthMV, dayMV) is true.
  32. If hour is empty, then
    1. Let time be start-of-day.
  33. Else,
    1. Let time be ! CreateTimeRecord(hourMV, minuteMV, secondMV, millisecondMV, microsecondMV, nanosecondMV).
  34. Let timeZoneResult be RFC 9557 Time Zone Parse Record { [[Z]]: false, [[OffsetString]]: empty, [[TimeZoneAnnotation]]: empty }.
  35. 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).
  36. If parseResult contains a UTCDesignator Parse Node, then
    1. Set timeZoneResult.[[Z]] to true.
  37. Else if parseResult contains a UTCOffset[+SubMinutePrecision] Parse Node, then
    1. Let offset be the source text matched by the UTCOffset[+SubMinutePrecision] Parse Node contained within parseResult.
    2. Set timeZoneResult.[[OffsetString]] to CodePointsToString(offset).
  38. If yearAbsent is true, let yearReturn be empty; else let yearReturn be yearMV.
  39. Return the ISO Date-Time Parse Record { [[Year]]: yearReturn, [[Month]]: monthMV, [[Day]]: dayMV, [[Time]]: time, [[TimeZone]]: timeZoneResult, [[Calendar]]: calendar  }.

22.4.6 ParseTemporalCalendarString ( string )

The abstract operation ParseTemporalCalendarString takes argument string (a String) and returns either a normal completion containing a calendar type or a throw completion. It parses the argument either as an ISO 8601 / RFC 9557 string or bare calendar type, and returns the calendar type. The returned string is syntactically a valid calendar type, but not necessarily a known calendar type. It performs the following steps when called:

  1. Let parseResult be Completion(ParseISODateTime(string, all)).
  2. If parseResult is a normal completion, then
    1. Let calendar be parseResult.[[Value]].[[Calendar]].
    2. If calendar is empty, return "iso8601".
    3. Return calendar.
  3. Set parseResult to ParseText(string, AnnotationValue).
  4. If parseResult is not a Parse Node, throw a RangeError exception.
  5. Return string.

22.4.7 ParseTemporalDurationString ( isoString )

The abstract operation ParseTemporalDurationString takes argument isoString (a String) and returns either a normal completion containing a Temporal.Duration or a throw completion. It parses the argument as an ISO 8601 duration string.

Note
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(isoString, TemporalDurationString).
  2. If duration is not a Parse Node, throw a RangeError exception.
  3. Let sign be the source text matched by the ASCIISign Parse Node contained within duration, or an empty sequence of code points if not present.
  4. If duration contains a DurationYearsPart Parse Node, then
    1. Let yearsNode be that DurationYearsPart Parse Node contained within duration.
    2. Let years be the source text matched by the DecimalDigits Parse Node contained within yearsNode.
  5. Else,
    1. Let years be an empty sequence of code points.
  6. If duration contains a DurationMonthsPart Parse Node, then
    1. Let monthsNode be the DurationMonthsPart Parse Node contained within duration.
    2. Let months be the source text matched by the DecimalDigits Parse Node contained within monthsNode.
  7. Else,
    1. Let months be an empty sequence of code points.
  8. If duration contains a DurationWeeksPart Parse Node, then
    1. Let weeksNode be the DurationWeeksPart Parse Node contained within duration.
    2. Let weeks be the source text matched by the DecimalDigits Parse Node contained within weeksNode.
  9. Else,
    1. Let weeks be an empty sequence of code points.
  10. If duration contains a DurationDaysPart Parse Node, then
    1. Let daysNode be the DurationDaysPart Parse Node contained within duration.
    2. Let days be the source text matched by the DecimalDigits Parse Node contained within daysNode.
  11. Else,
    1. Let days be an empty sequence of code points.
  12. If duration contains a DurationHoursPart Parse Node, then
    1. Let hoursNode be the DurationHoursPart Parse Node contained within duration.
    2. Let hours be the source text matched by the DecimalDigits Parse Node contained within hoursNode.
    3. Let fHours be the source text matched by the TemporalDecimalFraction Parse Node contained within hoursNode, or an empty sequence of code points if not present.
  13. Else,
    1. Let hours be an empty sequence of code points.
    2. Let fHours be an empty sequence of code points.
  14. If duration contains a DurationMinutesPart Parse Node, then
    1. Let minutesNode be the DurationMinutesPart Parse Node contained within duration.
    2. Let minutes be the source text matched by the DecimalDigits Parse Node contained within minutesNode.
    3. Let fMinutes be the source text matched by the TemporalDecimalFraction Parse Node contained within minutesNode, or an empty sequence of code points if not present.
  15. Else,
    1. Let minutes be an empty sequence of code points.
    2. Let fMinutes be an empty sequence of code points.
  16. If duration contains a DurationSecondsPart Parse Node, then
    1. Let secondsNode be the DurationSecondsPart Parse Node contained within duration.
    2. Let seconds be the source text matched by the DecimalDigits Parse Node contained within secondsNode.
    3. Let fSeconds be the source text matched by the TemporalDecimalFraction Parse Node contained within secondsNode, or an empty sequence of code points if not present.
  17. Else,
    1. Let seconds be an empty sequence of code points.
    2. Let fSeconds be an empty sequence of code points.
  18. Let yearsMV be ? SnapToInteger(CodePointsToString(years), truncate).
  19. Let monthsMV be ? SnapToInteger(CodePointsToString(months), truncate).
  20. Let weeksMV be ? SnapToInteger(CodePointsToString(weeks), truncate).
  21. Let daysMV be ? SnapToInteger(CodePointsToString(days), truncate).
  22. Let hoursMV be ? SnapToInteger(CodePointsToString(hours), truncate).
  23. 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 ? SnapToInteger(fHoursDigits, truncate) / 10fHoursScale × 60.
  24. Else,
    1. Let minutesMV be ? SnapToInteger(CodePointsToString(minutes), truncate).
  25. 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 ? SnapToInteger(fMinutesDigits, truncate) / 10fMinutesScale × 60.
  26. Else if seconds is not empty, then
    1. Let secondsMV be ? SnapToInteger(CodePointsToString(seconds), truncate).
  27. Else,
    1. Let secondsMV be remainder(minutesMV, 1) × 60.
  28. 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 ? SnapToInteger(fSecondsDigits, truncate) / 10fSecondsScale × 1000.
  29. Else,
    1. Let millisecondsMV be remainder(secondsMV, 1) × 1000.
  30. Let microsecondsMV be remainder(millisecondsMV, 1) × 1000.
  31. Let nanosecondsMV be remainder(microsecondsMV, 1) × 1000.
  32. If sign contains the code point U+002D (HYPHEN-MINUS), then
    1. Let factor be -1.
  33. Else,
    1. Let factor be 1.
  34. Set yearsMV to yearsMV × factor.
  35. Set monthsMV to monthsMV × factor.
  36. Set weeksMV to weeksMV × factor.
  37. Set daysMV to daysMV × factor.
  38. Set hoursMV to hoursMV × factor.
  39. Set minutesMV to floor(minutesMV) × factor.
  40. Set secondsMV to floor(secondsMV) × factor.
  41. Set millisecondsMV to floor(millisecondsMV) × factor.
  42. Set microsecondsMV to floor(microsecondsMV) × factor.
  43. Set nanosecondsMV to floor(nanosecondsMV) × factor.
  44. Return ? CreateTemporalDuration(yearsMV, monthsMV, weeksMV, daysMV, hoursMV, minutesMV, secondsMV, millisecondsMV, microsecondsMV, nanosecondsMV).

22.4.8 ParseTemporalTimeZoneString ( timeZoneString )

The abstract operation ParseTemporalTimeZoneString takes argument timeZoneString (a String) and returns either a normal completion containing a Time Zone Identifier Parse Record, or a throw completion. It parses the argument as either a time zone identifier or an ISO 8601 / RFC 9557 string. In the latter case, the returned Time Zone Identifier Parse Record refers to the time zone in string's time zone annotation if present, or refers to UTC if the string contains a Z designator, or else refers to an offset time zone matching the string's numeric UTC offset if present. It performs the following steps when called:

  1. Let parseResult be ParseText(timeZoneString, TimeZoneIdentifier).
  2. If parseResult is a Parse Node, return ! ParseTimeZoneIdentifier(timeZoneString).
  3. Let result be ? ParseISODateTime(timeZoneString, all).
  4. Let timeZoneResult be result.[[TimeZone]].
  5. If timeZoneResult.[[TimeZoneAnnotation]] is not empty, return ! ParseTimeZoneIdentifier(timeZoneResult.[[TimeZoneAnnotation]]).
  6. If timeZoneResult.[[Z]] is true, return ! ParseTimeZoneIdentifier("UTC").
  7. If timeZoneResult.[[OffsetString]] is not empty, return ? ParseTimeZoneIdentifier(timeZoneResult.[[OffsetString]]).
  8. Throw a RangeError exception.

22.4.9 ParseTimeZoneIdentifier ( identifier )

The abstract operation ParseTimeZoneIdentifier takes argument identifier (a String) and returns either a normal completion containing a Time Zone Identifier Parse Record, or a throw completion. It parses identifier to determine whether it identifies an offset time zone or named time zone. If identifier is syntactically invalid, a RangeError will be thrown. It performs the following steps when called:

  1. Let parseResult be ParseText(identifier, TimeZoneIdentifier).
  2. If parseResult is not a Parse Node, 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 Time Zone Identifier Parse Record { [[Name]]: CodePointsToString(name), [[OffsetMinutes]]: empty }.
  4. Assert: parseResult contains a UTCOffset[~SubMinutePrecision] Parse Node.
  5. Let offset be the source text matched by the UTCOffset[~SubMinutePrecision] Parse Node contained within parseResult.
  6. Let offsetNanoseconds be ! ParseDateTimeUTCOffset(CodePointsToString(offset)).
  7. Let offsetMinutes be offsetNanoseconds / NanosecondsPerMinute.
  8. Return the Time Zone Identifier Parse Record { [[Name]]: empty, [[OffsetMinutes]]: offsetMinutes }.

22.5 Formatting RFC 9557 Strings

This section contains abstract operations used for serializing data into various partial RFC 9557 string formats.

22.5.1 FormatCalendarAnnotation ( id, showCalendar )

The abstract operation FormatCalendarAnnotation takes arguments id (a known calendar type) and showCalendar ("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 / RFC 9557 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 "]".

22.5.2 FormatDateTimeUTCOffsetRounded ( offsetNanoseconds )

The abstract operation FormatDateTimeUTCOffsetRounded takes argument offsetNanoseconds (an integer in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive)) 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, NanosecondsPerMinute, "halfExpand").
  2. Let offsetMinutes be offsetNanoseconds / NanosecondsPerMinute.
  3. Return FormatOffsetTimeZoneIdentifier(offsetMinutes).

22.5.3 FormatFractionalSeconds ( subSecondNanoseconds, precision )

The abstract operation FormatFractionalSeconds takes arguments subSecondNanoseconds (an integer in the inclusive interval from 0 to 999999999) and precision (either an integer in the inclusive interval from 0 to 9 or auto) and returns a String. If precision = 0, or precision is auto and subSecondNanoseconds = 0, 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 = 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 = 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.

22.5.4 FormatISODateTime ( isoDateTime, calendar, precision, showCalendar )

The abstract operation FormatISODateTime takes arguments isoDateTime (an ISO Date-Time Record), calendar (a known calendar type), precision (either an integer in the inclusive interval from 0 to 9, minute, or auto), and showCalendar ("auto", "always", "never", or "critical") and returns a String. It formats an ISO Date-Time Record into an ISO 8601 / RFC 9557 string, to the precision specified by precision. It performs the following steps when called:

  1. Let yearString be PadISOYear(isoDateTime.[[ISODate]].[[Year]]).
  2. Let monthString be ToZeroPaddedDecimalString(isoDateTime.[[ISODate]].[[Month]], 2).
  3. Let dayString be ToZeroPaddedDecimalString(isoDateTime.[[ISODate]].[[Day]], 2).
  4. Let subSecondNanoseconds be isoDateTime.[[Time]].[[Millisecond]] × NanosecondsPerMillisecond + isoDateTime.[[Time]].[[Microsecond]] × NanosecondsPerMicrosecond + isoDateTime.[[Time]].[[Nanosecond]].
  5. Let timeString be FormatTimeString(isoDateTime.[[Time]].[[Hour]], isoDateTime.[[Time]].[[Minute]], isoDateTime.[[Time]].[[Second]], subSecondNanoseconds, precision).
  6. Let calendarString be FormatCalendarAnnotation(calendar, showCalendar).
  7. 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.

22.5.5 FormatOffsetTimeZoneIdentifier ( offsetMinutes [ , style ] )

The abstract operation FormatOffsetTimeZoneIdentifier takes argument offsetMinutes (an integer in the inclusive interval from -1439 to 1439) and optional argument style (separated or unseparated) and returns an offset time zone identifier. 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 and the return value identifier can be parsed with ParseText(identifier, NormalizedUTCOffset). 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); else 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.

22.5.6 FormatTimeString ( hour, minute, second, subSecondNanoseconds, precision [ , style ] )

The abstract operation FormatTimeString takes arguments 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), subSecondNanoseconds (an integer in the inclusive interval from 0 to 999999999), and precision (either an integer in the inclusive interval from 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 = 0, or subSecondNanoseconds = 0 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; else 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.

22.5.7 FormatUTCOffsetNanoseconds ( offsetNanoseconds )

The abstract operation FormatUTCOffsetNanoseconds takes argument offsetNanoseconds (an integer in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive)) 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); else let sign be the code unit 0x002D (HYPHEN-MINUS).
  2. Let absoluteNanoseconds be abs(offsetNanoseconds).
  3. Let hour be floor(absoluteNanoseconds / NanosecondsPerHour).
  4. Let minute be floor(absoluteNanoseconds / NanosecondsPerMinute) modulo 60.
  5. Let second be floor(absoluteNanoseconds / NanosecondsPerSecond) modulo 60.
  6. Let subSecondNanoseconds be absoluteNanoseconds modulo NanosecondsPerSecond.
  7. If second = 0 and subSecondNanoseconds = 0, let precision be minute; else let precision be auto.
  8. Let timeString be FormatTimeString(hour, minute, second, subSecondNanoseconds, precision).
  9. Return the string-concatenation of sign and timeString.

22.5.8 PadISOYear ( isoYear )

The abstract operation PadISOYear takes argument isoYear (an integer) and returns a String. It returns a String representation of isoYear suitable for inclusion in an ISO 8601 string, either in 4-digit format or 6-digit format with sign. It performs the following steps when called:

  1. If isoYear ≥ 0 and isoYear ≤ 9999, return ToZeroPaddedDecimalString(isoYear, 4).
  2. If isoYear > 0, let yearSign be "+"; else let yearSign be "-".
  3. Let digitsString be ToZeroPaddedDecimalString(abs(isoYear), 6).
  4. Return the string-concatenation of yearSign and digitsString.

22.5.9 ToSecondsStringPrecisionRecord ( smallestUnit, fractionalDigitCount )

The abstract operation ToSecondsStringPrecisionRecord takes arguments smallestUnit ("minute", "second", "millisecond", "microsecond", "nanosecond", or no-unit) and fractionalDigitCount (either an integer in the inclusive interval from 0 to 9 or auto) and returns a Record with fields [[Precision]] (either an integer in the inclusive interval from 0 to 9, minute, or auto), [[Unit]] (one of "minute", "second", "millisecond", "microsecond", or "nanosecond"), and [[Increment]] (one of 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 no-unit) fractionalDigitCount digits after the decimal point in the seconds. Its [[Precision]] field is either that count of digits, the value auto signifying that there should be no insignificant trailing zeroes, or the value 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", return the Record { [[Precision]]: minute, [[Unit]]: "minute", [[Increment]]: 1  }.
  2. If smallestUnit is "second", return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1  }.
  3. If smallestUnit is "millisecond", return the Record { [[Precision]]: 3, [[Unit]]: "millisecond", [[Increment]]: 1  }.
  4. If smallestUnit is "microsecond", return the Record { [[Precision]]: 6, [[Unit]]: "microsecond", [[Increment]]: 1  }.
  5. If smallestUnit is "nanosecond", return the Record { [[Precision]]: 9, [[Unit]]: "nanosecond", [[Increment]]: 1  }.
  6. Assert: smallestUnit is no-unit.
  7. If fractionalDigitCount is auto, return the Record { [[Precision]]: auto, [[Unit]]: "nanosecond", [[Increment]]: 1  }.
  8. If fractionalDigitCount = 0, return the Record { [[Precision]]: 0, [[Unit]]: "second", [[Increment]]: 1  }.
  9. If fractionalDigitCount is in the inclusive interval from 1 to 3, return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "millisecond", [[Increment]]: 103 - fractionalDigitCount  }.
  10. If fractionalDigitCount is in the inclusive interval from 4 to 6, return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "microsecond", [[Increment]]: 106 - fractionalDigitCount  }.
  11. Assert: fractionalDigitCount is in the inclusive interval from 7 to 9.
  12. Return the Record { [[Precision]]: fractionalDigitCount, [[Unit]]: "nanosecond", [[Increment]]: 109 - fractionalDigitCount  }.

22.6 The Temporal Object

The Temporal object:

  • is %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.

22.6.1 Value Properties of the Temporal Object

22.6.1.1 Temporal [ %Symbol.toStringTag% ]

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

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

22.6.2 Constructor Properties of the Temporal Object

22.6.2.1 Temporal.Duration ( . . . )

See 22.15.

22.6.2.2 Temporal.Instant ( . . . )

See 22.8.

22.6.2.3 Temporal.PlainDate ( . . . )

See 22.11.

22.6.2.4 Temporal.PlainDateTime ( . . . )

See 22.10.

22.6.2.5 Temporal.PlainMonthDay ( . . . )

See 22.14.

22.6.2.6 Temporal.PlainTime ( . . . )

See 22.12.

22.6.2.7 Temporal.PlainYearMonth ( . . . )

See 22.13.

22.6.2.8 Temporal.ZonedDateTime ( . . . )

See 22.9.

22.6.3 Other Properties of the Temporal Object

22.6.3.1 Temporal.Now

See 22.7.

22.7 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.

22.7.1 Value Properties of the Temporal.Now Object

22.7.1.1 Temporal.Now [ %Symbol.toStringTag% ]

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

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

22.7.2 Function Properties of the Temporal.Now Object

22.7.2.1 Temporal.Now.timeZoneId ( )

This function performs the following steps when called:

  1. Return SystemTimeZoneIdentifier().

22.7.2.2 Temporal.Now.instant ( )

This function performs the following steps when called:

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

22.7.2.3 Temporal.Now.plainDateTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
  2. Return ! CreateTemporalDateTime(isoDateTime, "iso8601").

22.7.2.4 Temporal.Now.zonedDateTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. If temporalTimeZoneLike is undefined, then
    1. Let timeZone be SystemTimeZoneIdentifier().
  2. Else,
    1. Let timeZone be ? ToTemporalTimeZoneIdentifier(temporalTimeZoneLike).
  3. Let epochNanoseconds be SystemUTCEpochNanoseconds().
  4. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, "iso8601").

22.7.2.5 Temporal.Now.plainDateISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
  2. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], "iso8601").

22.7.2.6 Temporal.Now.plainTimeISO ( [ temporalTimeZoneLike ] )

This function performs the following steps when called:

  1. Let isoDateTime be ? SystemDateTime(temporalTimeZoneLike).
  2. Return ! CreateTemporalTime(isoDateTime.[[Time]]).

22.7.3 Abstract Operations for the Temporal.Now Object

22.7.3.1 SystemDateTime ( temporalTimeZoneLike )

The abstract operation SystemDateTime takes argument temporalTimeZoneLike (an ECMAScript language value) and returns either a normal completion containing an ISO Date-Time Record or a throw completion. It performs the following steps when called:

  1. If temporalTimeZoneLike is undefined, then
    1. Let timeZone be SystemTimeZoneIdentifier().
  2. Else,
    1. Let timeZone be ? ToTemporalTimeZoneIdentifier(temporalTimeZoneLike).
  3. Let epochNanoseconds be SystemUTCEpochNanoseconds().
  4. Return GetISODateTimeFor(timeZone, epochNanoseconds).

22.7.3.2 SystemUTCEpochNanoseconds ( )

The abstract operation SystemUTCEpochNanoseconds takes no arguments and returns an epoch nanoseconds count. It performs the following steps when called:

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

22.8 Temporal.Instant Objects

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

22.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.

22.8.1.1 Temporal.Instant ( epochNanoseconds )

This function performs the following steps when called:

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

22.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:

22.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 }.

22.8.2.2 Temporal.Instant.from ( item )

This function performs the following steps when called:

  1. Return ? ToTemporalInstant(item).

22.8.2.3 Temporal.Instant.fromEpochMilliseconds ( epochMilliseconds )

This function performs the following steps when called:

  1. Let epochMillisecondsMV be ? SnapToInteger(epochMilliseconds, reject, MinEpochNanoseconds / NanosecondsPerMillisecond, MaxEpochNanoseconds / NanosecondsPerMillisecond).
  2. Return ! CreateTemporalInstant(epochMillisecondsMV × NanosecondsPerMillisecond).

22.8.2.4 Temporal.Instant.fromEpochNanoseconds ( epochNanoseconds )

This function performs the following steps when called:

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

22.8.2.5 Temporal.Instant.compare ( xInstant, yInstant )

This function performs the following steps when called:

  1. Set xInstant to ? ToTemporalInstant(xInstant).
  2. Set yInstant to ? ToTemporalInstant(yInstant).
  3. Return 𝔽(CompareEpochNanoseconds(xInstant.[[EpochNanoseconds]], yInstant.[[EpochNanoseconds]])).

22.8.3 Properties of the Temporal.Instant Prototype Object

The Temporal.Instant prototype object

22.8.3.1 Temporal.Instant.prototype.constructor

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

22.8.3.2 Temporal.Instant.prototype[ %Symbol.toStringTag% ]

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

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

22.8.3.3 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 epochMilliseconds be floor(instant.[[EpochNanoseconds]] / NanosecondsPerMillisecond).
  4. Return 𝔽(epochMilliseconds).

22.8.3.4 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. Return (instant.[[EpochNanoseconds]]).

22.8.3.5 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 ? AddDurationToInstant(add, instant, temporalDurationLike).

22.8.3.6 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 ? AddDurationToInstant(subtract, instant, temporalDurationLike).

22.8.3.7 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).

22.8.3.8 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).

22.8.3.9 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, throw a TypeError exception.
  4. If roundTo is a 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 roundingIncrement be ? GetRoundingIncrementOption(roundTo).
  7. Let roundingMode be ? GetRoundingModeOption(roundTo, "halfExpand").
  8. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
  9. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  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 MillisecondsPerDay.
  14. Else if smallestUnit is "microsecond", then
    1. Let maximum be 103 × MillisecondsPerDay.
  15. Else,
    1. Assert: smallestUnit is "nanosecond".
    2. Let maximum be NanosecondsPerDay.
  16. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, true).
  17. Let roundedNanoseconds be RoundEpochNanoseconds(instant.[[EpochNanoseconds]], roundingIncrement, smallestUnit, roundingMode).
  18. Return ! CreateTemporalInstant(roundedNanoseconds).

22.8.3.10 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.[[EpochNanoseconds]]other.[[EpochNanoseconds]], return false.
  5. Return true.

22.8.3.11 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. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
  5. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, "trunc").
  6. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", optional).
  7. Let timeZone be ? Get(resolvedOptions, "timeZone").
  8. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  9. If smallestUnit is "hour", throw a RangeError exception.
  10. If timeZone is not undefined, then
    1. Set timeZone to ? ToTemporalTimeZoneIdentifier(timeZone).
  11. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  12. Let roundedNanoseconds be RoundEpochNanoseconds(instant.[[EpochNanoseconds]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  13. Let roundedInstant be ! CreateTemporalInstant(roundedNanoseconds).
  14. Return TemporalInstantToString(roundedInstant, timeZone, precision.[[Precision]]).

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

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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).

22.8.3.13 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).

22.8.3.14 Temporal.Instant.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as instant1 > instant2 would fall back to being equivalent to instant1.toString() > instant2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.Instant.compare (22.8.2.5), Temporal.Instant.prototype.equals (22.8.3.10), and/or Temporal.Instant.prototype.toString (22.8.3.11).

22.8.3.15 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 ? ToTemporalTimeZoneIdentifier(timeZone).
  4. Return ! CreateTemporalZonedDateTime(instant.[[EpochNanoseconds]], timeZone, "iso8601").

22.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 78.

Table 78: 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.
[[EpochNanoseconds]] An epoch nanoseconds count representing the exact time of this Temporal.Instant instance.

22.8.5 Abstract Operations for Temporal.Instant Objects

22.8.5.1 CreateTemporalInstant ( epochNanoseconds [ , newTarget ] )

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

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

22.8.5.2 ToTemporalInstant ( item )

The abstract operation ToTemporalInstant takes argument item (an ECMAScript language value) and returns either a normal completion containing a Temporal.Instant or a throw completion. Converts item to a new Temporal.Instant instance if possible, and throws otherwise. It performs the following steps when called:

  1. If item is an Object, then
    1. If item has an [[InitializedTemporalInstant]] or [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Return ! CreateTemporalInstant(item.[[EpochNanoseconds]]).
    2. NOTE: This use of ToPrimitive allows Instant-like objects to be converted.
    3. Set item to ? ToPrimitive(item, string).
  2. If item is not a String, throw a TypeError exception.
  3. Let parsed be ? ParseISODateTime(item, instant).
  4. Assert: Either parsed.[[TimeZone]].[[OffsetString]] is not empty or parsed.[[TimeZone]].[[Z]] is true, but not both.
  5. If parsed.[[TimeZone]].[[Z]] is true, let offsetNanoseconds be 0; else let offsetNanoseconds be ! ParseDateTimeUTCOffset(parsed.[[TimeZone]].[[OffsetString]]).
  6. Let time be parsed.[[Time]].
  7. Assert: time is not start-of-day.
  8. Let balanced be BalanceISODateTime(parsed.[[Year]], parsed.[[Month]], parsed.[[Day]], time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], time.[[Microsecond]], time.[[Nanosecond]] - offsetNanoseconds).
  9. Perform ? ValidateISODaysRange(balanced.[[ISODate]]).
  10. Let epochNanoseconds be GetUTCEpochNanoseconds(balanced).
  11. If IsWithinEpochNanosecondsInterval(epochNanoseconds) is false, throw a RangeError exception.
  12. Return ! CreateTemporalInstant(epochNanoseconds).

22.8.5.3 TemporalInstantToString ( instant, timeZone, precision )

The abstract operation TemporalInstantToString takes arguments instant (a Temporal.Instant), timeZone (either an available time zone identifier or undefined), and precision (either an integer in the inclusive interval from 0 to 9, minute, or auto) and returns a String. It formats instant as an ISO 8601 / RFC 9557 string, to the precision specified by precision, using the UTC offset of timeZone, or Z if timeZone is undefined. It performs the following steps when called:

  1. Let outputTimeZone be timeZone.
  2. If outputTimeZone is undefined, set outputTimeZone to "UTC".
  3. Let epochNanoseconds be instant.[[EpochNanoseconds]].
  4. Let isoDateTime be GetISODateTimeFor(outputTimeZone, epochNanoseconds).
  5. Let dateTimeString be FormatISODateTime(isoDateTime, "iso8601", precision, "never").
  6. If timeZone is undefined, then
    1. Let timeZoneString be "Z".
  7. Else,
    1. Let offsetNanoseconds be GetOffsetNanosecondsFor(outputTimeZone, epochNanoseconds).
    2. Let timeZoneString be FormatDateTimeUTCOffsetRounded(offsetNanoseconds).
  8. Return the string-concatenation of dateTimeString and timeZoneString.

22.8.5.4 AddDurationToInstant ( operation, instant, temporalDurationLike )

The abstract operation AddDurationToInstant 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 a throw completion. It adds/subtracts temporalDurationLike to/from instant. It performs the following steps when called:

  1. Let duration be ? ToTemporalDuration(temporalDurationLike).
  2. If operation is subtract, set duration to CreateNegatedTemporalDuration(duration).
  3. Let largestUnit be DefaultTemporalLargestUnit(duration).
  4. If largestUnit is a date unit, throw a RangeError exception.
  5. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
  6. Let epochNanoseconds be ? AddEpochNanoseconds(instant.[[EpochNanoseconds]], internalDuration.[[Time]]).
  7. Return ! CreateTemporalInstant(epochNanoseconds).

22.8.5.5 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 a throw 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. Set other to ? ToTemporalInstant(other).
  2. Let resolvedOptions be ? GetOptionsObject(options).
  3. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », "nanosecond", "second").
  4. Let internalDuration be DifferenceEpochNanoseconds(instant.[[EpochNanoseconds]], other.[[EpochNanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  5. Let result be ! TemporalDurationFromInternal(internalDuration, settings.[[LargestUnit]]).
  6. If operation is since, set result to CreateNegatedTemporalDuration(result).
  7. Return result.

22.9 Temporal.ZonedDateTime Objects

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

22.9.1 The Temporal.ZonedDateTime Constructor

The Temporal.ZonedDateTime constructor:

22.9.1.1 Temporal.ZonedDateTime ( epochNanoseconds, timeZone [ , calendar ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Set epochNanoseconds to (? ToBigInt(epochNanoseconds)).
  3. If IsWithinEpochNanosecondsInterval(epochNanoseconds) is false, throw a RangeError exception.
  4. If timeZone is not a String, throw a TypeError exception.
  5. Let timeZoneParse be ? ParseTimeZoneIdentifier(timeZone).
  6. If timeZoneParse.[[OffsetMinutes]] is empty, then
    1. Assert: timeZoneParse.[[Name]] is not empty.
    2. Let identifierRecord be GetAvailableNamedTimeZoneIdentifier(timeZoneParse.[[Name]]).
    3. If identifierRecord is empty, throw a RangeError exception.
    4. Set timeZone to identifierRecord.[[Identifier]].
  7. Else,
    1. Set timeZone to FormatOffsetTimeZoneIdentifier(timeZoneParse.[[OffsetMinutes]]).
  8. If calendar is undefined, set calendar to "iso8601".
  9. If calendar is not a String, throw a TypeError exception.
  10. Set calendar to ? CanonicalizeCalendar(calendar).
  11. Return ? CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar, NewTarget).

22.9.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:

22.9.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalZonedDateTime(item, options).

22.9.2.3 Temporal.ZonedDateTime.compare ( xZonedDateTime, yZonedDateTime )

This function performs the following steps when called:

  1. Set xZonedDateTime to ? ToTemporalZonedDateTime(xZonedDateTime).
  2. Set yZonedDateTime to ? ToTemporalZonedDateTime(yZonedDateTime).
  3. Return 𝔽(CompareEpochNanoseconds(xZonedDateTime.[[EpochNanoseconds]], yZonedDateTime.[[EpochNanoseconds]])).

22.9.3 Properties of the Temporal.ZonedDateTime Prototype Object

The Temporal.ZonedDateTime prototype object

Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

22.9.3.1 Temporal.ZonedDateTime.prototype.constructor

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

22.9.3.2 Temporal.ZonedDateTime.prototype[ %Symbol.toStringTag% ]

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

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

22.9.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 zonedDateTime.[[Calendar]].

22.9.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 zonedDateTime.[[TimeZone]].

22.9.3.5 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Let result be CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[Era]].
  5. If result is empty, return undefined.
  6. Return result.

22.9.3.6 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Let result be CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[EraYear]].
  5. If result is empty, return undefined.
  6. Return 𝔽(result).

22.9.3.7 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[Year]]).

22.9.3.8 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[Month]]).

22.9.3.9 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[MonthCode]].

22.9.3.10 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[Day]]).

22.9.3.11 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Hour]]).

22.9.3.12 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Minute]]).

22.9.3.13 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Second]]).

22.9.3.14 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Millisecond]]).

22.9.3.15 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Microsecond]]).

22.9.3.16 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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(isoDateTime.[[Time]].[[Nanosecond]]).

22.9.3.17 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 epochMilliseconds be floor(zonedDateTime.[[EpochNanoseconds]] / NanosecondsPerMillisecond).
  4. Return 𝔽(epochMilliseconds).

22.9.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.[[EpochNanoseconds]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[DayOfWeek]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[DayOfYear]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Let result be CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[WeekOfYear]].[[Week]].
  5. If result is empty, return undefined.
  6. Return 𝔽(result).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Let result be CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[WeekOfYear]].[[Year]].
  5. If result is empty, return undefined.
  6. Return 𝔽(result).

22.9.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 timeZone be zonedDateTime.[[TimeZone]].
  4. Let isoDateTime be GetISODateTimeFor(timeZone, zonedDateTime.[[EpochNanoseconds]]).
  5. Let today be isoDateTime.[[ISODate]].
  6. Let tomorrow be AddDaysToISODate(today, 1).
  7. Let todayEpochNanoseconds be ? GetStartOfDay(timeZone, today).
  8. Let tomorrowEpochNanoseconds be ? GetStartOfDay(timeZone, tomorrow).
  9. Let diff be TimeDurationFromEpochNanosecondsDifference(todayEpochNanoseconds, tomorrowEpochNanoseconds).
  10. Return 𝔽(TotalTimeDuration(diff, "hour")).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[DaysInWeek]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[DaysInMonth]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[DaysInYear]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return 𝔽(CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[MonthsInYear]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return CalendarISOToDate(zonedDateTime.[[Calendar]], isoDateTime.[[ISODate]]).[[InLeapYear]].

22.9.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. Return 𝔽(GetOffsetNanosecondsFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]])).

22.9.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 offsetNanoseconds be GetOffsetNanosecondsFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return FormatUTCOffsetNanoseconds(offsetNanoseconds).

22.9.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 epochNanoseconds be zonedDateTime.[[EpochNanoseconds]].
  5. Let timeZone be zonedDateTime.[[TimeZone]].
  6. Let calendar be zonedDateTime.[[Calendar]].
  7. Let offsetNanoseconds be GetOffsetNanosecondsFor(timeZone, epochNanoseconds).
  8. Let isoDateTime be GetISODateTimeFor(timeZone, epochNanoseconds).
  9. Let fields be ISODateToFields(calendar, isoDateTime.[[ISODate]], date).
  10. Set fields.[[Hour]] to isoDateTime.[[Time]].[[Hour]].
  11. Set fields.[[Minute]] to isoDateTime.[[Time]].[[Minute]].
  12. Set fields.[[Second]] to isoDateTime.[[Time]].[[Second]].
  13. Set fields.[[Millisecond]] to isoDateTime.[[Time]].[[Millisecond]].
  14. Set fields.[[Microsecond]] to isoDateTime.[[Time]].[[Microsecond]].
  15. Set fields.[[Nanosecond]] to isoDateTime.[[Time]].[[Nanosecond]].
  16. Set fields.[[OffsetString]] to FormatUTCOffsetNanoseconds(offsetNanoseconds).
  17. Let partialZonedDateTime be ? PrepareCalendarFields(calendar, temporalZonedDateTimeLike, date-fields, time-fields-with-offset, partial).
  18. Set fields to CalendarMergeFields(calendar, fields, partialZonedDateTime).
  19. Let resolvedOptions be ? GetOptionsObject(options).
  20. Let disambiguation be ? GetTemporalDisambiguationOption(resolvedOptions).
  21. Let offset be ? GetTemporalOffsetOption(resolvedOptions, "prefer").
  22. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  23. Let dateTimeResult be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
  24. Let newOffsetNanoseconds be ! ParseDateTimeUTCOffset(fields.[[OffsetString]]).
  25. Let newEpochNanoseconds be ? InterpretISODateTimeOffset(dateTimeResult.[[ISODate]], dateTimeResult.[[Time]], option, newOffsetNanoseconds, timeZone, disambiguation, offset, match-exactly).
  26. Return ! CreateTemporalZonedDateTime(newEpochNanoseconds, timeZone, calendar).

22.9.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. Let timeZone be zonedDateTime.[[TimeZone]].
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let isoDateTime be GetISODateTimeFor(timeZone, zonedDateTime.[[EpochNanoseconds]]).
  6. If plainTimeLike is undefined, then
    1. Let epochNanoseconds be ? GetStartOfDay(timeZone, isoDateTime.[[ISODate]]).
  7. Else,
    1. Let plainTime be ? ToTemporalTime(plainTimeLike).
    2. Let resultISODateTime be the ISO Date-Time Record { [[ISODate]]: isoDateTime.[[ISODate]], [[Time]]: plainTime.[[Time]] }.
    3. Let epochNanoseconds be ? GetEpochNanosecondsFor(timeZone, resultISODateTime, "compatible").
  8. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

22.9.3.33 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 ? ToTemporalTimeZoneIdentifier(timeZoneLike).
  4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[EpochNanoseconds]], timeZone, zonedDateTime.[[Calendar]]).

22.9.3.34 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 ? ToTemporalCalendarIdentifier(calendarLike).
  4. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[EpochNanoseconds]], zonedDateTime.[[TimeZone]], calendar).

22.9.3.35 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 ? AddDurationToZonedDateTime(add, zonedDateTime, temporalDurationLike, options).

22.9.3.36 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 ? AddDurationToZonedDateTime(subtract, zonedDateTime, temporalDurationLike, options).

22.9.3.37 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).

22.9.3.38 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).

22.9.3.39 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, throw a TypeError exception.
  4. If roundTo is a 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 roundingIncrement be ? GetRoundingIncrementOption(roundTo).
  7. Let roundingMode be ? GetRoundingModeOption(roundTo, "halfExpand").
  8. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
  9. Perform ? ValidateTemporalUnitValue(smallestUnit, time, « "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 no-maximum.
    3. Let inclusive be false.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, inclusive).
  13. If smallestUnit is "nanosecond" and roundingIncrement = 1, then
    1. Return ! CreateTemporalZonedDateTime(zonedDateTime.[[EpochNanoseconds]], zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]]).
  14. Let thisEpochNanoseconds be zonedDateTime.[[EpochNanoseconds]].
  15. Let timeZone be zonedDateTime.[[TimeZone]].
  16. Let calendar be zonedDateTime.[[Calendar]].
  17. Let isoDateTime be GetISODateTimeFor(timeZone, thisEpochNanoseconds).
  18. If smallestUnit is "day", then
    1. Let dateStart be isoDateTime.[[ISODate]].
    2. Let dateEnd be AddDaysToISODate(dateStart, 1).
    3. Let startNanoseconds be ? GetStartOfDay(timeZone, dateStart).
    4. Assert: thisEpochNanosecondsstartNanoseconds.
    5. Let endNanoseconds be ? GetStartOfDay(timeZone, dateEnd).
    6. Set thisEpochNanoseconds to min(thisEpochNanoseconds, endNanoseconds - 1).
    7. Let dayLengthNanoseconds be endNanoseconds - startNanoseconds.
    8. Let dayProgressNanoseconds be TimeDurationFromEpochNanosecondsDifference(startNanoseconds, thisEpochNanoseconds).
    9. Let roundedDayNanoseconds be ! RoundTimeDurationToIncrement(dayProgressNanoseconds, dayLengthNanoseconds, roundingMode).
    10. Let epochNanoseconds be AddTimeDurationToEpochNanoseconds(roundedDayNanoseconds, startNanoseconds).
  19. Else,
    1. Let roundResult be RoundISODateTime(isoDateTime, roundingIncrement, smallestUnit, roundingMode).
    2. Let offsetNanoseconds be GetOffsetNanosecondsFor(timeZone, thisEpochNanoseconds).
    3. Let epochNanoseconds be ? InterpretISODateTimeOffset(roundResult.[[ISODate]], roundResult.[[Time]], option, offsetNanoseconds, timeZone, "compatible", "prefer", match-exactly).
  20. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

22.9.3.40 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.[[EpochNanoseconds]]other.[[EpochNanoseconds]], return false.
  5. If TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, return false.
  6. If zonedDateTime.[[Calendar]] is not other.[[Calendar]], return false.
  7. Return true.

22.9.3.41 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. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let showCalendar be ? GetTemporalShowCalendarNameOption(resolvedOptions).
  5. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
  6. Let showOffset be ? GetTemporalShowOffsetOption(resolvedOptions).
  7. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, "trunc").
  8. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", optional).
  9. Let showTimeZone be ? GetTemporalShowTimeZoneNameOption(resolvedOptions).
  10. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  11. If smallestUnit is "hour", throw a RangeError exception.
  12. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  13. Return TemporalZonedDateTimeToString(zonedDateTime, precision.[[Precision]], showCalendar, showTimeZone, showOffset, precision.[[Increment]], precision.[[Unit]], roundingMode).

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

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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").

22.9.3.43 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").

22.9.3.44 Temporal.ZonedDateTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as zonedDateTime1 > zonedDateTime2 would fall back to being equivalent to zonedDateTime1.toString() > zonedDateTime2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.ZonedDateTime.compare (22.9.2.3), Temporal.ZonedDateTime.prototype.equals (22.9.3.40), and/or Temporal.ZonedDateTime.prototype.toString (22.9.3.41).

22.9.3.45 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 timeZone be zonedDateTime.[[TimeZone]].
  4. Let calendar be zonedDateTime.[[Calendar]].
  5. Let isoDateTime be GetISODateTimeFor(timeZone, zonedDateTime.[[EpochNanoseconds]]).
  6. Let epochNanoseconds be ? GetStartOfDay(timeZone, isoDateTime.[[ISODate]]).
  7. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

22.9.3.46 Temporal.ZonedDateTime.prototype.getTimeZoneTransition ( directionParam )

This method performs the following steps when called:

  1. Let zonedDateTime be the this value.
  2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
  3. Let timeZone be zonedDateTime.[[TimeZone]].
  4. If directionParam is undefined, throw a TypeError exception.
  5. If directionParam is a String, then
    1. Let paramString be directionParam.
    2. Set directionParam to OrdinaryObjectCreate(null).
    3. Perform ! CreateDataPropertyOrThrow(directionParam, "direction", paramString).
  6. Else,
    1. Set directionParam to ? GetOptionsObject(directionParam).
  7. Let direction be ? GetDirectionOption(directionParam).
  8. If timeZone is an offset time zone identifier, return null.
  9. If direction is "next", then
    1. Let transition be GetNamedTimeZoneNextTransition(timeZone, zonedDateTime.[[EpochNanoseconds]]).
  10. Else,
    1. Assert: direction is "previous".
    2. Let transition be GetNamedTimeZonePreviousTransition(timeZone, zonedDateTime.[[EpochNanoseconds]]).
  11. If transition is null, return null.
  12. Return ! CreateTemporalZonedDateTime(transition, timeZone, zonedDateTime.[[Calendar]]).

22.9.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.[[EpochNanoseconds]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], zonedDateTime.[[Calendar]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return ! CreateTemporalTime(isoDateTime.[[Time]]).

22.9.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 isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
  4. Return ! CreateTemporalDateTime(isoDateTime, zonedDateTime.[[Calendar]]).

22.9.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 79.

Table 79: 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.
[[EpochNanoseconds]] An epoch nanoseconds count representing the exact time of this Temporal.ZonedDateTime instance.
[[TimeZone]] An available time zone identifier.
[[Calendar]] A known calendar type.

22.9.5 Abstract Operations for Temporal.ZonedDateTime Objects

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

The abstract operation CreateTemporalZonedDateTime takes arguments epochNanoseconds (an epoch nanoseconds count), timeZone (an available time zone identifier), and calendar (a known calendar type) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.ZonedDateTime or a throw completion. It creates a Temporal.ZonedDateTime instance and fills the internal slots with valid values. It performs the following steps when called:

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

22.9.5.2 ToTemporalZonedDateTime ( item [ , options ] )

The abstract operation ToTemporalZonedDateTime takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.ZonedDateTime, or a throw completion. 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 hasUTCDesignator be false.
  3. Let matchBehaviour be match-exactly.
  4. If item is an Object, then
    1. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. NOTE: The following steps, and similar ones below, read options and perform independent validation in alphabetical order (GetTemporalDisambiguationOption reads "disambiguation", GetTemporalOffsetOption reads "offset", and GetTemporalOverflowOption reads "overflow").
      2. Let resolvedOptions be ? GetOptionsObject(options).
      3. Perform ? GetTemporalDisambiguationOption(resolvedOptions).
      4. Perform ? GetTemporalOffsetOption(resolvedOptions, "reject").
      5. Perform ? GetTemporalOverflowOption(resolvedOptions).
      6. Return ! CreateTemporalZonedDateTime(item.[[EpochNanoseconds]], item.[[TimeZone]], item.[[Calendar]]).
    2. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(item).
    3. Let fields be ? PrepareCalendarFields(calendar, item, date-fields, time-fields-with-time-zone-and-offset, time-zone).
    4. Let timeZone be fields.[[TimeZone]].
    5. Let offsetString be fields.[[OffsetString]].
    6. Let resolvedOptions be ? GetOptionsObject(options).
    7. Let disambiguation be ? GetTemporalDisambiguationOption(resolvedOptions).
    8. Let offsetOption be ? GetTemporalOffsetOption(resolvedOptions, "reject").
    9. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    10. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
    11. Let isoDate be result.[[ISODate]].
    12. Let time be result.[[Time]].
  5. Else,
    1. If item is not a String, throw a TypeError exception.
    2. Let result be ? ParseISODateTime(item, zoned-date-time).
    3. Let annotation be result.[[TimeZone]].[[TimeZoneAnnotation]].
    4. Assert: annotation is not empty.
    5. Let timeZone be ? ToTemporalTimeZoneIdentifier(annotation).
    6. Let offsetString be result.[[TimeZone]].[[OffsetString]].
    7. If result.[[TimeZone]].[[Z]] is true, then
      1. Set hasUTCDesignator to true.
    8. Let calendar be result.[[Calendar]].
    9. If calendar is empty, set calendar to "iso8601".
    10. Set calendar to ? CanonicalizeCalendar(calendar).
    11. Set matchBehaviour to match-minutes.
    12. If offsetString is not empty, then
      1. Let offsetParseResult be ParseText(offsetString, UTCOffset[+SubMinutePrecision]).
      2. Assert: offsetParseResult is a Parse Node.
      3. If offsetParseResult contains a Second Parse Node, set matchBehaviour to match-exactly.
    13. Let resolvedOptions be ? GetOptionsObject(options).
    14. Let disambiguation be ? GetTemporalDisambiguationOption(resolvedOptions).
    15. Let offsetOption be ? GetTemporalOffsetOption(resolvedOptions, "reject").
    16. Perform ? GetTemporalOverflowOption(resolvedOptions).
    17. Let isoDate be ! CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]).
    18. Let time be result.[[Time]].
  6. If hasUTCDesignator is true, then
    1. Let offsetBehaviour be exact.
  7. Else if offsetString is not a String, then
    1. Let offsetBehaviour be wall.
  8. Else,
    1. Let offsetBehaviour be option.
  9. Let offsetNanoseconds be 0.
  10. If offsetBehaviour is option, then
    1. Set offsetNanoseconds to ! ParseDateTimeUTCOffset(offsetString).
  11. Let epochNanoseconds be ? InterpretISODateTimeOffset(isoDate, time, offsetBehaviour, offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour).
  12. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

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

The abstract operation TemporalZonedDateTimeToString takes arguments zonedDateTime (a Temporal.ZonedDateTime), precision (either an integer in the inclusive interval from 0 to 9, minute, or auto), showCalendar ("auto", "always", "never", or "critical"), showTimeZone ("auto", "never", or "critical"), and showOffset ("auto" or "never") and optional arguments increment (a positive integer), unit (a time unit but not "hour"), and roundingMode (a rounding mode) and returns a String. It returns an ISO 8601 / RFC 9557 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 epochNanoseconds be zonedDateTime.[[EpochNanoseconds]].
  5. Set epochNanoseconds to RoundEpochNanoseconds(epochNanoseconds, increment, unit, roundingMode).
  6. Let timeZone be zonedDateTime.[[TimeZone]].
  7. Let offsetNanoseconds be GetOffsetNanosecondsFor(timeZone, epochNanoseconds).
  8. Let isoDateTime be GetISODateTimeFor(timeZone, epochNanoseconds).
  9. Let dateTimeString be FormatISODateTime(isoDateTime, "iso8601", precision, "never").
  10. If showOffset is "never", then
    1. Let offsetString be the empty String.
  11. Else,
    1. Let offsetString be FormatDateTimeUTCOffsetRounded(offsetNanoseconds).
  12. If showTimeZone is "never", then
    1. Let timeZoneString be the empty String.
  13. Else,
    1. If showTimeZone is "critical", let flag be "!"; else let flag be the empty String.
    2. Let timeZoneString be the string-concatenation of the code unit 0x005B (LEFT SQUARE BRACKET), flag, timeZone, and the code unit 0x005D (RIGHT SQUARE BRACKET).
  14. Let calendarString be FormatCalendarAnnotation(zonedDateTime.[[Calendar]], showCalendar).
  15. Return the string-concatenation of dateTimeString, offsetString, timeZoneString, and calendarString.

22.9.5.4 AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow )

The abstract operation AddZonedDateTime takes arguments epochNanoseconds (an epoch nanoseconds count), timeZone (an available time zone identifier), calendar (a known calendar type), duration (an Internal Duration Record), and overflow ("constrain" or "reject") and returns either a normal completion containing an epoch nanoseconds count or a throw completion. It adds a duration in various units to an epoch nanoseconds count, subject to the rules of the time zone and calendar. 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. It performs the following steps when called:

  1. If DateDurationSign(duration.[[Date]]) = 0, return ? AddEpochNanoseconds(epochNanoseconds, duration.[[Time]]).
  2. Let isoDateTime be GetISODateTimeFor(timeZone, epochNanoseconds).
  3. Let addedDate be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], duration.[[Date]], overflow).
  4. Let intermediateDateTime be the ISO Date-Time Record { [[ISODate]]: addedDate, [[Time]]: isoDateTime.[[Time]] }.
  5. If ISODateTimeWithinLimits(intermediateDateTime) is false, throw a RangeError exception.
  6. Let intermediateNanoseconds be ! GetEpochNanosecondsFor(timeZone, intermediateDateTime, "compatible").
  7. Return ? AddEpochNanoseconds(intermediateNanoseconds, duration.[[Time]]).

22.9.5.5 AddDurationToZonedDateTime ( operation, zonedDateTime, temporalDurationLike, options )

The abstract operation AddDurationToZonedDateTime 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 a throw completion. It adds/subtracts temporalDurationLike to/from zonedDateTime. It performs the following steps when called:

  1. Let duration be ? ToTemporalDuration(temporalDurationLike).
  2. If operation is subtract, set duration to CreateNegatedTemporalDuration(duration).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  5. Let calendar be zonedDateTime.[[Calendar]].
  6. Let timeZone be zonedDateTime.[[TimeZone]].
  7. Let internalDuration be ToInternalDurationRecord(duration).
  8. Let epochNanoseconds be ? AddZonedDateTime(zonedDateTime.[[EpochNanoseconds]], timeZone, calendar, internalDuration, overflow).
  9. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, calendar).

22.9.5.6 DifferenceZonedDateTime ( epochNanosecondsFrom, epochNanosecondsTo, timeZone, calendar, largestUnit )

The abstract operation DifferenceZonedDateTime takes arguments epochNanosecondsFrom (an epoch nanoseconds count), epochNanosecondsTo (an epoch nanoseconds count), timeZone (an available time zone identifier), calendar (a known calendar type), and largestUnit (a Temporal unit) and returns either a normal completion containing an Internal Duration Record, or a throw completion. It computes the difference between two epoch nanoseconds counts, 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. It performs the following steps when called:

  1. If epochNanosecondsFrom = epochNanosecondsTo, return CombineDateAndTimeDuration(ZeroDateDuration(), 0).
  2. Let startDateTime be GetISODateTimeFor(timeZone, epochNanosecondsFrom).
  3. Let endDateTime be GetISODateTimeFor(timeZone, epochNanosecondsTo).
  4. If CompareISODate(startDateTime.[[ISODate]], endDateTime.[[ISODate]]) = 0, then
    1. Let timeDuration be TimeDurationFromEpochNanosecondsDifference(epochNanosecondsFrom, epochNanosecondsTo).
    2. Return CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration).
  5. If epochNanosecondsTo - epochNanosecondsFrom < 0, let sign be 1; else let sign be -1.
  6. If sign = -1, let maxDayCorrection be 2; else let maxDayCorrection be 1.
  7. Let dayCorrection be 0.
  8. Let timeDuration be DifferenceTime(startDateTime.[[Time]], endDateTime.[[Time]]).
  9. If TimeDurationSign(timeDuration) = sign, set dayCorrection to dayCorrection + 1.
  10. Let success be false.
  11. Repeat, while dayCorrectionmaxDayCorrection and success is false,
    1. Let intermediateDate be AddDaysToISODate(endDateTime.[[ISODate]], dayCorrection × sign).
    2. Let intermediateDateTime be the ISO Date-Time Record { [[ISODate]]: intermediateDate, [[Time]]: startDateTime.[[Time]] }.
    3. Let intermediateNanoseconds be ? GetEpochNanosecondsFor(timeZone, intermediateDateTime, "compatible").
    4. Set timeDuration to TimeDurationFromEpochNanosecondsDifference(intermediateNanoseconds, epochNanosecondsTo).
    5. Let timeSign be TimeDurationSign(timeDuration).
    6. If signtimeSign, then
      1. Set success to true.
    7. Set dayCorrection to dayCorrection + 1.
  12. Assert: success is true.
  13. Let dateLargestUnit be LargerOfTwoTemporalUnits(largestUnit, "day").
  14. Let dateDifference be CalendarDateUntil(calendar, startDateTime.[[ISODate]], intermediateDateTime.[[ISODate]], dateLargestUnit).
  15. Return CombineDateAndTimeDuration(dateDifference, timeDuration).

22.9.5.7 DifferenceZonedDateTimeWithRounding ( epochNanosecondsFrom, epochNanosecondsTo, timeZone, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode )

The abstract operation DifferenceZonedDateTimeWithRounding takes arguments epochNanosecondsFrom (an epoch nanoseconds count), epochNanosecondsTo (an epoch nanoseconds count), timeZone (an available time zone identifier), calendar (a known calendar type), largestUnit (a Temporal unit), roundingIncrement (a positive integer), smallestUnit (a Temporal unit), and roundingMode (a rounding mode) and returns either a normal completion containing an Internal Duration Record, or a throw completion. It performs the following steps when called:

  1. If largestUnit is a time unit, return DifferenceEpochNanoseconds(epochNanosecondsFrom, epochNanosecondsTo, roundingIncrement, smallestUnit, roundingMode).
  2. Let difference be ? DifferenceZonedDateTime(epochNanosecondsFrom, epochNanosecondsTo, timeZone, calendar, largestUnit).
  3. If smallestUnit is "nanosecond" and roundingIncrement = 1, return difference.
  4. Let dateTime be GetISODateTimeFor(timeZone, epochNanosecondsFrom).
  5. Return ? RoundRelativeDuration(difference, epochNanosecondsFrom, epochNanosecondsTo, dateTime, timeZone, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).

22.9.5.8 DifferenceZonedDateTimeWithTotal ( epochNanosecondsFrom, epochNanosecondsTo, timeZone, calendar, unit )

The abstract operation DifferenceZonedDateTimeWithTotal takes arguments epochNanosecondsFrom (an epoch nanoseconds count), epochNanosecondsTo (an epoch nanoseconds count), timeZone (an available time zone identifier), calendar (a known calendar type), and unit (a Temporal unit) and returns either a normal completion containing a mathematical value, or a throw completion. It performs the following steps when called:

  1. If unit is a time unit, then
    1. Let difference be TimeDurationFromEpochNanosecondsDifference(epochNanosecondsFrom, epochNanosecondsTo).
    2. Return TotalTimeDuration(difference, unit).
  2. Let difference be ? DifferenceZonedDateTime(epochNanosecondsFrom, epochNanosecondsTo, timeZone, calendar, unit).
  3. Let dateTime be GetISODateTimeFor(timeZone, epochNanosecondsFrom).
  4. Return ? TotalRelativeDuration(difference, epochNanosecondsFrom, epochNanosecondsTo, dateTime, timeZone, calendar, unit).

22.9.5.9 DifferenceTemporalZonedDateTime ( operation, zonedDateTime, other, options )

The abstract operation DifferenceTemporalZonedDateTime takes arguments operation (since or until), 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 a throw 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. Set other to ? ToTemporalZonedDateTime(other).
  2. If zonedDateTime.[[Calendar]] is not other.[[Calendar]], throw a RangeError exception.
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, datetime, « », "nanosecond", "hour").
  5. If settings.[[LargestUnit]] is a time unit, then
    1. Let internalDuration be DifferenceEpochNanoseconds(zonedDateTime.[[EpochNanoseconds]], other.[[EpochNanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
    2. Let result be ! TemporalDurationFromInternal(internalDuration, settings.[[LargestUnit]]).
    3. If operation is since, set result to CreateNegatedTemporalDuration(result).
    4. Return result.
  6. NOTE: To calculate differences in two different time zones, settings.[[LargestUnit]] must be a time unit, because day lengths can vary between time zones due to daylight saving time and other UTC offset shifts.
  7. If TimeZoneEquals(zonedDateTime.[[TimeZone]], other.[[TimeZone]]) is false, throw a RangeError exception.
  8. If zonedDateTime.[[EpochNanoseconds]] = other.[[EpochNanoseconds]], return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  9. Let internalDuration be ? DifferenceZonedDateTimeWithRounding(zonedDateTime.[[EpochNanoseconds]], other.[[EpochNanoseconds]], zonedDateTime.[[TimeZone]], zonedDateTime.[[Calendar]], settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  10. Let result be ! TemporalDurationFromInternal(internalDuration, "hour").
  11. If operation is since, set result to CreateNegatedTemporalDuration(result).
  12. Return result.

22.9.5.10 InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour )

The abstract operation InterpretISODateTimeOffset takes arguments isoDate (an ISO Date Record), time (either a Time Record or start-of-day), offsetBehaviour (option, exact, or wall), offsetNanoseconds (an integer in the interval from -NanosecondsPerDay (exclusive) to NanosecondsPerDay (exclusive)), timeZone (an available time zone identifier), disambiguation ("compatible", "earlier", "later", or "reject"), offsetOption ("prefer", "use", "ignore", or "reject"), and matchBehaviour (match-exactly or match-minutes) and returns either a normal completion containing an epoch nanoseconds count or a throw completion.

It determines the epoch nanoseconds count 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 epoch nanoseconds count, or no possible epoch nanoseconds count, an answer is determined using offsetBehaviour, disambiguation and offsetOption.

As a special case when parsing ISO 8601 / RFC 9557 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. If time is start-of-day, then
    1. Assert: offsetBehaviour is wall.
    2. Assert: offsetNanoseconds = 0.
    3. Return ? GetStartOfDay(timeZone, isoDate).
  2. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: time }.
  3. If offsetBehaviour is wall, or offsetBehaviour is option and offsetOption is "ignore", then
    1. Return ? GetEpochNanosecondsFor(timeZone, isoDateTime, disambiguation).
  4. If offsetBehaviour is exact, or offsetBehaviour is option and offsetOption is "use", then
    1. Let balanced be BalanceISODateTime(isoDate.[[Year]], isoDate.[[Month]], isoDate.[[Day]], time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], time.[[Microsecond]], time.[[Nanosecond]] - offsetNanoseconds).
    2. Perform ? ValidateISODaysRange(balanced.[[ISODate]]).
    3. Let epochNanoseconds be GetUTCEpochNanoseconds(balanced).
    4. If IsWithinEpochNanosecondsInterval(epochNanoseconds) is false, throw a RangeError exception.
    5. Return epochNanoseconds.
  5. Assert: offsetBehaviour is option.
  6. Assert: offsetOption is "prefer" or "reject".
  7. Perform ? ValidateISODaysRange(isoDate).
  8. Let utcEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTime).
  9. Let possibleEpochNanoseconds be ? GetPossibleEpochNanoseconds(timeZone, isoDateTime).
  10. For each element candidate of possibleEpochNanoseconds, do
    1. Let candidateOffset be utcEpochNanoseconds - candidate.
    2. If candidateOffset = offsetNanoseconds, return candidate.
    3. If matchBehaviour is match-minutes, then
      1. Let roundedCandidateNanoseconds be RoundNumberToIncrement(candidateOffset, NanosecondsPerMinute, "halfExpand").
      2. If roundedCandidateNanoseconds = offsetNanoseconds, return candidate.
  11. If offsetOption is "reject", throw a RangeError exception.
  12. Return ? DisambiguatePossibleEpochNanoseconds(possibleEpochNanoseconds, timeZone, isoDateTime, disambiguation).

22.10 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, as well as a calendar type used to interpret those integers in a particular calendar.

Temporal.PlainDateTime objects can represent points in time within 24 hours, exclusive, of the limits of epoch nanoseconds counts. This ensures that a Temporal.Instant object can be converted into a Temporal.PlainDateTime object using any time zone.

22.10.1 The Temporal.PlainDateTime Constructor

The Temporal.PlainDateTime constructor:

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

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Set isoYear to ? SnapToInteger(isoYear, truncate).
  3. Set isoMonth to ? SnapToInteger(isoMonth, truncate).
  4. Set isoDay to ? SnapToInteger(isoDay, truncate).
  5. If hour is undefined, set hour to 0; else set hour to ? SnapToInteger(hour, truncate).
  6. If minute is undefined, set minute to 0; else set minute to ? SnapToInteger(minute, truncate).
  7. If second is undefined, set second to 0; else set second to ? SnapToInteger(second, truncate).
  8. If millisecond is undefined, set millisecond to 0; else set millisecond to ? SnapToInteger(millisecond, truncate).
  9. If microsecond is undefined, set microsecond to 0; else set microsecond to ? SnapToInteger(microsecond, truncate).
  10. If nanosecond is undefined, set nanosecond to 0; else set nanosecond to ? SnapToInteger(nanosecond, truncate).
  11. If calendar is undefined, set calendar to "iso8601".
  12. If calendar is not a String, throw a TypeError exception.
  13. Set calendar to ? CanonicalizeCalendar(calendar).
  14. Let isoDate be ? CreateISODateRecord(isoYear, isoMonth, isoDay).
  15. Let time be ? CreateTimeRecord(hour, minute, second, millisecond, microsecond, nanosecond).
  16. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: time }.
  17. Return ? CreateTemporalDateTime(isoDateTime, calendar, NewTarget).

22.10.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:

22.10.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalDateTime(item, options).

22.10.2.3 Temporal.PlainDateTime.compare ( xPlainDateTime, yPlainDateTime )

This function performs the following steps when called:

  1. Set xPlainDateTime to ? ToTemporalDateTime(xPlainDateTime).
  2. Set yPlainDateTime to ? ToTemporalDateTime(yPlainDateTime).
  3. Return 𝔽(CompareISODateTime(xPlainDateTime.[[ISODateTime]], yPlainDateTime.[[ISODateTime]])).

22.10.3 Properties of the Temporal.PlainDateTime Prototype Object

The Temporal.PlainDateTime prototype object

Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

22.10.3.1 Temporal.PlainDateTime.prototype.constructor

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

22.10.3.2 Temporal.PlainDateTime.prototype[ %Symbol.toStringTag% ]

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

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

22.10.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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return plainDateTime.[[Calendar]].

22.10.3.4 get Temporal.PlainDateTime.prototype.era

Temporal.PlainDateTime.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 result be CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[Era]].
  4. If result is empty, return undefined.
  5. Return result.

22.10.3.5 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 result be CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[EraYear]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.10.3.6 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[Year]]).

22.10.3.7 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[Month]]).

22.10.3.8 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[MonthCode]].

22.10.3.9 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[Day]]).

22.10.3.10 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Hour]]).

22.10.3.11 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Minute]]).

22.10.3.12 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Second]]).

22.10.3.13 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Millisecond]]).

22.10.3.14 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Microsecond]]).

22.10.3.15 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(plainDateTime.[[ISODateTime]].[[Time]].[[Nanosecond]]).

22.10.3.16 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[DayOfWeek]]).

22.10.3.17 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[DayOfYear]]).

22.10.3.18 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let result be CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[WeekOfYear]].[[Week]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.10.3.19 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let result be CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[WeekOfYear]].[[Year]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.10.3.20 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[DaysInWeek]]).

22.10.3.21 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[DaysInMonth]]).

22.10.3.22 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[DaysInYear]]).

22.10.3.23 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return 𝔽(CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[MonthsInYear]]).

22.10.3.24 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return CalendarISOToDate(plainDateTime.[[Calendar]], plainDateTime.[[ISODateTime]].[[ISODate]]).[[InLeapYear]].

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

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. If ? IsPartialTemporalObject(temporalDateTimeLike) is false, throw a TypeError exception.
  4. Let calendar be plainDateTime.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainDateTime.[[ISODateTime]].[[ISODate]], date).
  6. Set fields.[[Hour]] to plainDateTime.[[ISODateTime]].[[Time]].[[Hour]].
  7. Set fields.[[Minute]] to plainDateTime.[[ISODateTime]].[[Time]].[[Minute]].
  8. Set fields.[[Second]] to plainDateTime.[[ISODateTime]].[[Time]].[[Second]].
  9. Set fields.[[Millisecond]] to plainDateTime.[[ISODateTime]].[[Time]].[[Millisecond]].
  10. Set fields.[[Microsecond]] to plainDateTime.[[ISODateTime]].[[Time]].[[Microsecond]].
  11. Set fields.[[Nanosecond]] to plainDateTime.[[ISODateTime]].[[Time]].[[Nanosecond]].
  12. Let partialDateTime be ? PrepareCalendarFields(calendar, temporalDateTimeLike, date-fields, time-fields, partial).
  13. Set fields to CalendarMergeFields(calendar, fields, partialDateTime).
  14. Let resolvedOptions be ? GetOptionsObject(options).
  15. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  16. Let result be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
  17. Return ? CreateTemporalDateTime(result, calendar).

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

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let time be ? ToTimeRecordOrMidnight(plainTimeLike).
  4. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: plainDateTime.[[ISODateTime]].[[ISODate]], [[Time]]: time }.
  5. Return ? CreateTemporalDateTime(isoDateTime, plainDateTime.[[Calendar]]).

22.10.3.27 Temporal.PlainDateTime.prototype.withCalendar ( calendarLike )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let calendar be ? ToTemporalCalendarIdentifier(calendarLike).
  4. Return ! CreateTemporalDateTime(plainDateTime.[[ISODateTime]], calendar).

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

22.10.3.32 Temporal.PlainDateTime.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. If roundTo is undefined, throw a TypeError exception.
  4. If roundTo is a 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 roundingIncrement be ? GetRoundingIncrementOption(roundTo).
  7. Let roundingMode be ? GetRoundingModeOption(roundTo, "halfExpand").
  8. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
  9. Perform ? ValidateTemporalUnitValue(smallestUnit, time, « "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 no-maximum.
    3. Let inclusive be false.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, inclusive).
  13. If smallestUnit is "nanosecond" and roundingIncrement = 1, then
    1. Return ! CreateTemporalDateTime(plainDateTime.[[ISODateTime]], plainDateTime.[[Calendar]]).
  14. Let result be RoundISODateTime(plainDateTime.[[ISODateTime]], roundingIncrement, smallestUnit, roundingMode).
  15. Return ? CreateTemporalDateTime(result, plainDateTime.[[Calendar]]).

22.10.3.33 Temporal.PlainDateTime.prototype.equals ( other )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Set other to ? ToTemporalDateTime(other).
  4. If CompareISODateTime(plainDateTime.[[ISODateTime]], other.[[ISODateTime]]) ≠ 0, return false.
  5. If plainDateTime.[[Calendar]] is not other.[[Calendar]], return false.
  6. Return true.

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

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let showCalendar be ? GetTemporalShowCalendarNameOption(resolvedOptions).
  5. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
  6. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, "trunc").
  7. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", optional).
  8. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  9. If smallestUnit is "hour", throw a RangeError exception.
  10. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  11. Let result be RoundISODateTime(plainDateTime.[[ISODateTime]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  12. If ISODateTimeWithinLimits(result) is false, throw a RangeError exception.
  13. Return FormatISODateTime(result, plainDateTime.[[Calendar]], precision.[[Precision]], showCalendar).

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

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return FormatISODateTime(plainDateTime.[[ISODateTime]], plainDateTime.[[Calendar]], auto, "auto").

22.10.3.36 Temporal.PlainDateTime.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return FormatISODateTime(plainDateTime.[[ISODateTime]], plainDateTime.[[Calendar]], auto, "auto").

22.10.3.37 Temporal.PlainDateTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as plainDateTime1 > plainDateTime2 would fall back to being equivalent to plainDateTime1.toString() > plainDateTime2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.PlainDateTime.compare (22.10.2.3), Temporal.PlainDateTime.prototype.equals (22.10.3.33), and/or Temporal.PlainDateTime.prototype.toString (22.10.3.34).

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

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Let timeZone be ? ToTemporalTimeZoneIdentifier(temporalTimeZoneLike).
  4. Let resolvedOptions be ? GetOptionsObject(options).
  5. Let disambiguation be ? GetTemporalDisambiguationOption(resolvedOptions).
  6. Let epochNanoseconds be ? GetEpochNanosecondsFor(timeZone, plainDateTime.[[ISODateTime]], disambiguation).
  7. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, plainDateTime.[[Calendar]]).

22.10.3.39 Temporal.PlainDateTime.prototype.toPlainDate ( )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return ! CreateTemporalDate(plainDateTime.[[ISODateTime]].[[ISODate]], plainDateTime.[[Calendar]]).

22.10.3.40 Temporal.PlainDateTime.prototype.toPlainTime ( )

This method performs the following steps when called:

  1. Let plainDateTime be the this value.
  2. Perform ? RequireInternalSlot(plainDateTime, [[InitializedTemporalDateTime]]).
  3. Return ! CreateTemporalTime(plainDateTime.[[ISODateTime]].[[Time]]).

22.10.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 80.

Table 80: 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.
[[ISODateTime]] An ISO Date-Time Record.
[[Calendar]] A known calendar type.

22.10.5 Abstract Operations for Temporal.PlainDateTime Objects

22.10.5.1 CreateTemporalDateTime ( isoDateTime, calendar [ , newTarget ] )

The abstract operation CreateTemporalDateTime takes arguments isoDateTime (an ISO Date-Time Record) and calendar (a known calendar type) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainDateTime or a throw completion. It creates a Temporal.PlainDateTime instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If ISODateTimeWithinLimits(isoDateTime) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.PlainDateTime%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDateTime.prototype%", « [[InitializedTemporalDateTime]], [[ISODateTime]], [[Calendar]] »).
  4. Set object.[[ISODateTime]] to isoDateTime.
  5. Set object.[[Calendar]] to calendar.
  6. Return object.

22.10.5.2 ToTemporalDateTime ( item [ , options ] )

The abstract operation ToTemporalDateTime takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainDateTime or a throw completion. 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. If item is an Object, then
    1. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalDateTime(item.[[ISODateTime]], item.[[Calendar]]).
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]).
      2. Let resolvedOptions be ? GetOptionsObject(options).
      3. Perform ? GetTemporalOverflowOption(resolvedOptions).
      4. Return ! CreateTemporalDateTime(isoDateTime, item.[[Calendar]]).
    3. If item has an [[InitializedTemporalDate]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: item.[[ISODate]], [[Time]]: MidnightTimeRecord() }.
      4. Return ? CreateTemporalDateTime(isoDateTime, item.[[Calendar]]).
    4. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(item).
    5. Let fields be ? PrepareCalendarFields(calendar, item, date-fields, time-fields, no-required-fields).
    6. Let resolvedOptions be ? GetOptionsObject(options).
    7. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    8. Let fieldsResult be ? InterpretTemporalDateTimeFields(calendar, fields, overflow).
    9. Return ? CreateTemporalDateTime(fieldsResult, calendar).
  3. If item is not a String, throw a TypeError exception.
  4. Let parseResult be ? ParseISODateTime(item, plain-date-time).
  5. If parseResult.[[Time]] is start-of-day, let time be MidnightTimeRecord(); else let time be parseResult.[[Time]].
  6. Let calendar be parseResult.[[Calendar]].
  7. If calendar is empty, set calendar to "iso8601".
  8. Set calendar to ? CanonicalizeCalendar(calendar).
  9. Let resolvedOptions be ? GetOptionsObject(options).
  10. Perform ? GetTemporalOverflowOption(resolvedOptions).
  11. Let isoDate be ! CreateISODateRecord(parseResult.[[Year]], parseResult.[[Month]], parseResult.[[Day]]).
  12. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: time }.
  13. Return ? CreateTemporalDateTime(isoDateTime, calendar).

22.10.5.3 AddDurationToDateTime ( operation, dateTime, temporalDurationLike, options )

The abstract operation AddDurationToDateTime 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 a throw 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. Let duration be ? ToTemporalDuration(temporalDurationLike).
  2. If operation is subtract, set duration to CreateNegatedTemporalDuration(duration).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  5. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
  6. Let timeResult be AddTime(dateTime.[[ISODateTime]].[[Time]], internalDuration.[[Time]]).
  7. Let dateDuration be ? AdjustDateDurationRecord(internalDuration.[[Date]], timeResult.[[Days]]).
  8. Let addedDate be ? CalendarDateAdd(dateTime.[[Calendar]], dateTime.[[ISODateTime]].[[ISODate]], dateDuration, overflow).
  9. Let result be the ISO Date-Time Record { [[ISODate]]: addedDate, [[Time]]: timeResult }.
  10. Return ? CreateTemporalDateTime(result, dateTime.[[Calendar]]).

22.10.5.4 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 a throw 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. Set other to ? ToTemporalDateTime(other).
  2. If dateTime.[[Calendar]] is not other.[[Calendar]], throw a RangeError exception.
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, datetime, « », "nanosecond", "day").
  5. If CompareISODateTime(dateTime.[[ISODateTime]], other.[[ISODateTime]]) = 0, return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  6. Let internalDuration be ? DifferencePlainDateTimeWithRounding(dateTime.[[ISODateTime]], other.[[ISODateTime]], dateTime.[[Calendar]], settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  7. Let result be ! TemporalDurationFromInternal(internalDuration, settings.[[LargestUnit]]).
  8. If operation is since, set result to CreateNegatedTemporalDuration(result).
  9. Return result.

22.10.5.5 DifferencePlainDateTimeWithRounding ( isoDateTimeFrom, isoDateTimeTo, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode )

The abstract operation DifferencePlainDateTimeWithRounding takes arguments isoDateTimeFrom (an ISO Date-Time Record), isoDateTimeTo (an ISO Date-Time Record), calendar (a known calendar type), largestUnit (a Temporal unit), roundingIncrement (a positive integer), smallestUnit (a Temporal unit), and roundingMode (a rounding mode) and returns either a normal completion containing an Internal Duration Record or a throw completion. It performs the following steps when called:

  1. If CompareISODateTime(isoDateTimeFrom, isoDateTimeTo) = 0, return CombineDateAndTimeDuration(ZeroDateDuration(), 0).
  2. If ISODateTimeWithinLimits(isoDateTimeFrom) is false or ISODateTimeWithinLimits(isoDateTimeTo) is false, throw a RangeError exception.
  3. Let diff be DifferenceISODateTime(isoDateTimeFrom, isoDateTimeTo, calendar, largestUnit).
  4. If smallestUnit is "nanosecond" and roundingIncrement = 1, return diff.
  5. Let originEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeFrom).
  6. Let destEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeTo).
  7. Return ? RoundRelativeDuration(diff, originEpochNanoseconds, destEpochNanoseconds, isoDateTimeFrom, no-time-zone, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).

22.10.5.6 DifferencePlainDateTimeWithTotal ( isoDateTimeFrom, isoDateTimeTo, calendar, unit )

The abstract operation DifferencePlainDateTimeWithTotal takes arguments isoDateTimeFrom (an ISO Date-Time Record), isoDateTimeTo (an ISO Date-Time Record), calendar (a known calendar type), and unit (a Temporal unit) and returns either a normal completion containing a mathematical value or a throw completion. It performs the following steps when called:

  1. If CompareISODateTime(isoDateTimeFrom, isoDateTimeTo) = 0, return 0.
  2. If ISODateTimeWithinLimits(isoDateTimeFrom) is false or ISODateTimeWithinLimits(isoDateTimeTo) is false, throw a RangeError exception.
  3. Let diff be DifferenceISODateTime(isoDateTimeFrom, isoDateTimeTo, calendar, unit).
  4. If unit is "nanosecond", return diff.[[Time]].
  5. Let originEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeFrom).
  6. Let destEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeTo).
  7. Return ? TotalRelativeDuration(diff, originEpochNanoseconds, destEpochNanoseconds, isoDateTimeFrom, no-time-zone, calendar, unit).

22.10.5.7 InterpretTemporalDateTimeFields ( calendar, fields, overflow )

The abstract operation InterpretTemporalDateTimeFields takes arguments calendar (a known calendar type), fields (a Calendar Fields Record), and overflow ("constrain" or "reject") 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. It performs the following steps when called:

  1. Assert: fields.[[Hour]], fields.[[Minute]], fields.[[Second]], fields.[[Millisecond]], fields.[[Microsecond]], and fields.[[Nanosecond]] are not empty.
  2. Let isoDate be ? CalendarDateFromFields(calendar, fields, overflow).
  3. Let time be ? RegulateTime(fields.[[Hour]], fields.[[Minute]], fields.[[Second]], fields.[[Millisecond]], fields.[[Microsecond]], fields.[[Nanosecond]], overflow).
  4. Return the ISO Date-Time Record { [[ISODate]]: isoDate, [[Time]]: time }.

22.11 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 a calendar type used to interpret those integers in a particular calendar.

Temporal.PlainDate objects can represent the date portion of any Temporal.PlainDateTime object. This ensures that a Temporal.PlainDateTime object can always be converted into a Temporal.PlainDate object using any Temporal.PlainTime, but not vice versa.

22.11.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.

22.11.1.1 Temporal.PlainDate ( isoYear, isoMonth, isoDay [ , calendar ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let year be ? SnapToInteger(isoYear, truncate).
  3. Let month be ? SnapToInteger(isoMonth, truncate).
  4. Let day be ? SnapToInteger(isoDay, truncate).
  5. If calendar is undefined, set calendar to "iso8601".
  6. If calendar is not a String, throw a TypeError exception.
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let isoDate be ? CreateISODateRecord(year, month, day).
  9. Return ? CreateTemporalDate(isoDate, calendar, NewTarget).

22.11.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:

22.11.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalDate(item, options).

22.11.2.3 Temporal.PlainDate.compare ( xPlainDate, yPlainDate )

This function performs the following steps when called:

  1. Set xPlainDate to ? ToTemporalDate(xPlainDate).
  2. Set yPlainDate to ? ToTemporalDate(yPlainDate).
  3. Return 𝔽(CompareISODate(xPlainDate.[[ISODate]], yPlainDate.[[ISODate]])).

22.11.3 Properties of the Temporal.PlainDate Prototype Object

The Temporal.PlainDate prototype object

Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

22.11.3.1 Temporal.PlainDate.prototype.constructor

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

22.11.3.2 Temporal.PlainDate.prototype[ %Symbol.toStringTag% ]

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

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

22.11.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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return plainDate.[[Calendar]].

22.11.3.4 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 result be CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[Era]].
  4. If result is empty, return undefined.
  5. Return result.

22.11.3.5 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 result be CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[EraYear]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.11.3.6 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[Year]]).

22.11.3.7 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[Month]]).

22.11.3.8 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[MonthCode]].

22.11.3.9 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[Day]]).

22.11.3.10 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[DayOfWeek]]).

22.11.3.11 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[DayOfYear]]).

22.11.3.12 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let result be CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[WeekOfYear]].[[Week]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.11.3.13 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let result be CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[WeekOfYear]].[[Year]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.11.3.14 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[DaysInWeek]]).

22.11.3.15 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[DaysInMonth]]).

22.11.3.16 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[DaysInYear]]).

22.11.3.17 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return 𝔽(CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[MonthsInYear]]).

22.11.3.18 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return CalendarISOToDate(plainDate.[[Calendar]], plainDate.[[ISODate]]).[[InLeapYear]].

22.11.3.19 Temporal.PlainDate.prototype.toPlainYearMonth ( )

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let calendar be plainDate.[[Calendar]].
  4. Let fields be ISODateToFields(calendar, plainDate.[[ISODate]], date).
  5. Let isoDate be ? CalendarYearMonthFromFields(calendar, fields, "constrain").
  6. Return ! CreateTemporalYearMonth(isoDate, calendar).
  7. NOTE: The call to CalendarYearMonthFromFields is necessary in order to create a PlainYearMonth object with the [[Day]] field of the [[ISODate]] internal slot set correctly.

22.11.3.20 Temporal.PlainDate.prototype.toPlainMonthDay ( )

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let calendar be plainDate.[[Calendar]].
  4. Let fields be ISODateToFields(calendar, plainDate.[[ISODate]], date).
  5. Let isoDate be ? CalendarMonthDayFromFields(calendar, fields, "constrain").
  6. Return ! CreateTemporalMonthDay(isoDate, calendar).
  7. NOTE: The call to CalendarMonthDayFromFields is necessary in order to create a PlainMonthDay object with the [[Year]] field of the [[ISODate]] internal slot set correctly.

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

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return ? AddDurationToDate(add, plainDate, temporalDurationLike, options).

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

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return ? AddDurationToDate(subtract, plainDate, temporalDurationLike, options).

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

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. If ? IsPartialTemporalObject(temporalDateLike) is false, throw a TypeError exception.
  4. Let calendar be plainDate.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainDate.[[ISODate]], date).
  6. Let partialDate be ? PrepareCalendarFields(calendar, temporalDateLike, date-fields, no-non-calendar-fields, partial).
  7. Set fields to CalendarMergeFields(calendar, fields, partialDate).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  10. Let isoDate be ? CalendarDateFromFields(calendar, fields, overflow).
  11. Return ! CreateTemporalDate(isoDate, calendar).

22.11.3.24 Temporal.PlainDate.prototype.withCalendar ( calendarLike )

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let calendar be ? ToTemporalCalendarIdentifier(calendarLike).
  4. Return ! CreateTemporalDate(plainDate.[[ISODate]], calendar).

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

22.11.3.27 Temporal.PlainDate.prototype.equals ( other )

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Set other to ? ToTemporalDate(other).
  4. If CompareISODate(plainDate.[[ISODate]], other.[[ISODate]]) ≠ 0, return false.
  5. If plainDate.[[Calendar]] is not other.[[Calendar]], return false.
  6. Return true.

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

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let time be ? ToTimeRecordOrMidnight(temporalTime).
  4. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: plainDate.[[ISODate]], [[Time]]: time }.
  5. Return ? CreateTemporalDateTime(isoDateTime, plainDate.[[Calendar]]).

22.11.3.29 Temporal.PlainDate.prototype.toZonedDateTime ( item )

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. If item is an Object, then
    1. Let timeZoneLike be ? Get(item, "timeZone").
    2. If timeZoneLike is undefined, then
      1. Let timeZone be ? ToTemporalTimeZoneIdentifier(item).
      2. Let temporalTime be undefined.
    3. Else,
      1. Let timeZone be ? ToTemporalTimeZoneIdentifier(timeZoneLike).
      2. Let temporalTime be ? Get(item, "plainTime").
  4. Else,
    1. Let timeZone be ? ToTemporalTimeZoneIdentifier(item).
    2. Let temporalTime be undefined.
  5. If temporalTime is undefined, then
    1. Let epochNanoseconds be ? GetStartOfDay(timeZone, plainDate.[[ISODate]]).
  6. Else,
    1. Set temporalTime to ? ToTemporalTime(temporalTime).
    2. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: plainDate.[[ISODate]], [[Time]]: temporalTime.[[Time]] }.
    3. If ISODateTimeWithinLimits(isoDateTime) is false, throw a RangeError exception.
    4. Let epochNanoseconds be ? GetEpochNanosecondsFor(timeZone, isoDateTime, "compatible").
  7. Return ! CreateTemporalZonedDateTime(epochNanoseconds, timeZone, plainDate.[[Calendar]]).

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

This method performs the following steps when called:

  1. Let plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let showCalendar be ? GetTemporalShowCalendarNameOption(resolvedOptions).
  5. Return TemporalDateToString(plainDate, showCalendar).

22.11.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 ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 plainDate be the this value.
  2. Perform ? RequireInternalSlot(plainDate, [[InitializedTemporalDate]]).
  3. Return TemporalDateToString(plainDate, "auto").

22.11.3.32 Temporal.PlainDate.prototype.toJSON ( )

This method performs the following steps when called:

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

22.11.3.33 Temporal.PlainDate.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as plainDate1 > plainDate2 would fall back to being equivalent to plainDate1.toString() > plainDate2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.PlainDate.compare (22.11.2.3), Temporal.PlainDate.prototype.equals (22.11.3.27), and/or Temporal.PlainDate.prototype.toString` (22.11.3.30).

22.11.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 81.

Table 81: 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.
[[ISODate]] An ISO Date Record.
[[Calendar]] A known calendar type.

22.11.5 Abstract Operations for Temporal.PlainDate Objects

22.11.5.1 CreateTemporalDate ( isoDate, calendar [ , newTarget ] )

The abstract operation CreateTemporalDate takes arguments isoDate (an ISO Date Record) and calendar (a known calendar type) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainDate or a throw completion. It creates a Temporal.PlainDate instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If ISODateWithinLimits(isoDate) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.PlainDate%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainDate.prototype%", « [[InitializedTemporalDate]], [[ISODate]], [[Calendar]] »).
  4. Set object.[[ISODate]] to isoDate.
  5. Set object.[[Calendar]] to calendar.
  6. Return object.

22.11.5.2 ToTemporalDate ( item [ , options ] )

The abstract operation ToTemporalDate takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainDate or a throw completion. 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 item is an Object, then
    1. If item has an [[InitializedTemporalDate]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalDate(item.[[ISODate]], item.[[Calendar]]).
    2. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]).
      2. Let resolvedOptions be ? GetOptionsObject(options).
      3. Perform ? GetTemporalOverflowOption(resolvedOptions).
      4. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], item.[[Calendar]]).
    3. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalDate(item.[[ISODateTime]].[[ISODate]], item.[[Calendar]]).
    4. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(item).
    5. Let fields be ? PrepareCalendarFields(calendar, item, date-fields, no-non-calendar-fields, no-required-fields).
    6. Let resolvedOptions be ? GetOptionsObject(options).
    7. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    8. Let isoDate be ? CalendarDateFromFields(calendar, fields, overflow).
    9. Return ! CreateTemporalDate(isoDate, calendar).
  3. If item is not a String, throw a TypeError exception.
  4. Let result be ? ParseISODateTime(item, plain-date-time).
  5. Let calendar be result.[[Calendar]].
  6. If calendar is empty, set calendar to "iso8601".
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Perform ? GetTemporalOverflowOption(resolvedOptions).
  10. Let isoDate be ! CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]).
  11. Return ? CreateTemporalDate(isoDate, calendar).

22.11.5.3 TemporalDateToString ( temporalDate, showCalendar )

The abstract operation TemporalDateToString takes arguments temporalDate (a Temporal.PlainDate) and showCalendar ("auto", "always", "never", or "critical") and returns a String. It formats temporalDate to an ISO 8601 / RFC 9557 string. It performs the following steps when called:

  1. Let year be PadISOYear(temporalDate.[[ISODate]].[[Year]]).
  2. Let month be ToZeroPaddedDecimalString(temporalDate.[[ISODate]].[[Month]], 2).
  3. Let day be ToZeroPaddedDecimalString(temporalDate.[[ISODate]].[[Day]], 2).
  4. Let calendar be FormatCalendarAnnotation(temporalDate.[[Calendar]], showCalendar).
  5. Return the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), month, the code unit 0x002D (HYPHEN-MINUS), day, and calendar.

22.11.5.4 AddDurationToDate ( operation, temporalDate, temporalDurationLike, options )

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

  1. Let calendar be temporalDate.[[Calendar]].
  2. Let duration be ? ToTemporalDuration(temporalDurationLike).
  3. If operation is subtract, set duration to CreateNegatedTemporalDuration(duration).
  4. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
  5. Let days be truncate(internalDuration.[[Time]] / NanosecondsPerDay).
  6. Let dateDuration be ! CreateDateDurationRecord(internalDuration.[[Date]].[[Years]], internalDuration.[[Date]].[[Months]], internalDuration.[[Date]].[[Weeks]], days).
  7. Let resolvedOptions be ? GetOptionsObject(options).
  8. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  9. Let result be ? CalendarDateAdd(calendar, temporalDate.[[ISODate]], dateDuration, overflow).
  10. Return ! CreateTemporalDate(result, calendar).

22.11.5.5 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 a throw 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. Set other to ? ToTemporalDate(other).
  2. If temporalDate.[[Calendar]] is not other.[[Calendar]], throw a RangeError exception.
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « », "day", "day").
  5. If CompareISODate(temporalDate.[[ISODate]], other.[[ISODate]]) = 0, then
    1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  6. Let dateDifference be CalendarDateUntil(temporalDate.[[Calendar]], temporalDate.[[ISODate]], other.[[ISODate]], settings.[[LargestUnit]]).
  7. Let duration be CombineDateAndTimeDuration(dateDifference, 0).
  8. If settings.[[SmallestUnit]] is not "day" or settings.[[RoundingIncrement]] ≠ 1, then
    1. Let isoDateTime be ISO Date-Time Record { [[ISODate]]: temporalDate.[[ISODate]], [[Time]]: MidnightTimeRecord() }.
    2. Let originEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTime).
    3. Let isoDateTimeOther be the ISO Date-Time Record { [[ISODate]]: other.[[ISODate]], [[Time]]: MidnightTimeRecord() }.
    4. Let destEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeOther).
    5. Set duration to ? RoundRelativeDuration(duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, no-time-zone, temporalDate.[[Calendar]], settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  9. Let result be ! TemporalDurationFromInternal(duration, "day").
  10. If operation is since, set result to CreateNegatedTemporalDuration(result).
  11. Return result.

22.12 Temporal.PlainTime Objects

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

22.12.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.

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

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If hour is undefined, set hour to 0; else set hour to ? SnapToInteger(hour, truncate).
  3. If minute is undefined, set minute to 0; else set minute to ? SnapToInteger(minute, truncate).
  4. If second is undefined, set second to 0; else set second to ? SnapToInteger(second, truncate).
  5. If millisecond is undefined, set millisecond to 0; else set millisecond to ? SnapToInteger(millisecond, truncate).
  6. If microsecond is undefined, set microsecond to 0; else set microsecond to ? SnapToInteger(microsecond, truncate).
  7. If nanosecond is undefined, set nanosecond to 0; else set nanosecond to ? SnapToInteger(nanosecond, truncate).
  8. Let time be ? CreateTimeRecord(hour, minute, second, millisecond, microsecond, nanosecond).
  9. Return ? CreateTemporalTime(time, NewTarget).

22.12.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:

22.12.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalTime(item, options).

22.12.2.3 Temporal.PlainTime.compare ( xPlainTime, yPlainTime )

This function performs the following steps when called:

  1. Set xPlainTime to ? ToTemporalTime(xPlainTime).
  2. Set yPlainTime to ? ToTemporalTime(yPlainTime).
  3. Return 𝔽(CompareTimeRecord(xPlainTime.[[Time]], yPlainTime.[[Time]])).

22.12.3 Properties of the Temporal.PlainTime Prototype Object

The Temporal.PlainTime prototype object

22.12.3.1 Temporal.PlainTime.prototype.constructor

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

22.12.3.2 Temporal.PlainTime.prototype[ %Symbol.toStringTag% ]

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

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

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Hour]]).

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Minute]]).

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Second]]).

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Millisecond]]).

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Microsecond]]).

22.12.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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return 𝔽(plainTime.[[Time]].[[Nanosecond]]).

22.12.3.9 Temporal.PlainTime.prototype.add ( temporalDurationLike )

This method performs the following steps when called:

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

22.12.3.10 Temporal.PlainTime.prototype.subtract ( temporalDurationLike )

This method performs the following steps when called:

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

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

This method performs the following steps when called:

  1. Let plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. If ? IsPartialTemporalObject(temporalTimeLike) is false, throw a TypeError exception.
  4. Let partialTime be ? ToPartialTimeRecord(temporalTimeLike, partial).
  5. If partialTime.[[Hour]] is not empty, then
    1. Let hour be partialTime.[[Hour]].
  6. Else,
    1. Let hour be plainTime.[[Time]].[[Hour]].
  7. If partialTime.[[Minute]] is not empty, then
    1. Let minute be partialTime.[[Minute]].
  8. Else,
    1. Let minute be plainTime.[[Time]].[[Minute]].
  9. If partialTime.[[Second]] is not empty, then
    1. Let second be partialTime.[[Second]].
  10. Else,
    1. Let second be plainTime.[[Time]].[[Second]].
  11. If partialTime.[[Millisecond]] is not empty, then
    1. Let millisecond be partialTime.[[Millisecond]].
  12. Else,
    1. Let millisecond be plainTime.[[Time]].[[Millisecond]].
  13. If partialTime.[[Microsecond]] is not empty, then
    1. Let microsecond be partialTime.[[Microsecond]].
  14. Else,
    1. Let microsecond be plainTime.[[Time]].[[Microsecond]].
  15. If partialTime.[[Nanosecond]] is not empty, then
    1. Let nanosecond be partialTime.[[Nanosecond]].
  16. Else,
    1. Let nanosecond be plainTime.[[Time]].[[Nanosecond]].
  17. Let resolvedOptions be ? GetOptionsObject(options).
  18. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  19. Let result be ? RegulateTime(hour, minute, second, millisecond, microsecond, nanosecond, overflow).
  20. Return ! CreateTemporalTime(result).

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

22.12.3.14 Temporal.PlainTime.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. If roundTo is undefined, throw a TypeError exception.
  4. If roundTo is a 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 roundingIncrement be ? GetRoundingIncrementOption(roundTo).
  7. Let roundingMode be ? GetRoundingModeOption(roundTo, "halfExpand").
  8. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", required).
  9. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  10. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  11. Assert: maximum is not no-maximum.
  12. Perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  13. Let result be RoundTime(plainTime.[[Time]], roundingIncrement, smallestUnit, roundingMode).
  14. Return ! CreateTemporalTime(result).

22.12.3.15 Temporal.PlainTime.prototype.equals ( other )

This method performs the following steps when called:

  1. Let plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Set other to ? ToTemporalTime(other).
  4. If CompareTimeRecord(plainTime.[[Time]], other.[[Time]]) = 0, return true.
  5. Return false.

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

This method performs the following steps when called:

  1. Let plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
  5. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, "trunc").
  6. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", optional).
  7. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  8. If smallestUnit is "hour", throw a RangeError exception.
  9. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  10. Let roundResult be RoundTime(plainTime.[[Time]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  11. Return TimeRecordToString(roundResult, precision.[[Precision]]).

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

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return TimeRecordToString(plainTime.[[Time]], auto).

22.12.3.18 Temporal.PlainTime.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let plainTime be the this value.
  2. Perform ? RequireInternalSlot(plainTime, [[InitializedTemporalTime]]).
  3. Return TimeRecordToString(plainTime.[[Time]], auto).

22.12.3.19 Temporal.PlainTime.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as plainTime1 > plainTime2 would fall back to being equivalent to plainTime1.toString() > plainTime2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.PlainTime.compare (22.12.2.3), Temporal.PlainTime.prototype.equals (22.12.3.15), and/or Temporal.PlainTime.prototype.toString (22.12.3.16).

22.12.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 82.

Table 82: 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.
[[Time]] A Time Record. The [[Days]] field is ignored.

22.12.5 Abstract Operations for Temporal.PlainTime Objects

22.12.5.1 CreateTemporalTime ( time [ , newTarget ] )

The abstract operation CreateTemporalTime takes argument time (a Time Record) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainTime or a throw 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 newTarget is not present, set newTarget to %Temporal.PlainTime%.
  2. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainTime.prototype%", « [[InitializedTemporalTime]], [[Time]] »).
  3. Set object.[[Time]] to time.
  4. Return object.

22.12.5.2 ToTemporalTime ( item [ , options ] )

The abstract operation ToTemporalTime takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainTime or a throw Completion. Converts item to a new Temporal.PlainTime 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 item is an Object, then
    1. If item has an [[InitializedTemporalTime]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalTime(item.[[Time]]).
    2. If item has an [[InitializedTemporalDateTime]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalTime(item.[[ISODateTime]].[[Time]]).
    3. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
      1. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]).
      2. Let resolvedOptions be ? GetOptionsObject(options).
      3. Perform ? GetTemporalOverflowOption(resolvedOptions).
      4. Return ! CreateTemporalTime(isoDateTime.[[Time]]).
    4. Let result be ? ToPartialTimeRecord(item, complete).
    5. Let resolvedOptions be ? GetOptionsObject(options).
    6. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    7. Set result to ? RegulateTime(result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]], overflow).
  3. Else,
    1. If item is not a String, throw a TypeError exception.
    2. Let parseResult be ? ParseISODateTime(item, time).
    3. Assert: parseResult.[[Time]] is not start-of-day.
    4. Set result to parseResult.[[Time]].
    5. NOTE: A successful parse using time guarantees absence of ambiguity with respect to any ISO 8601 date-only, year-month, or month-day representation.
    6. Let resolvedOptions be ? GetOptionsObject(options).
    7. Perform ? GetTemporalOverflowOption(resolvedOptions).
  4. Return ! CreateTemporalTime(result).

22.12.5.3 AddDurationToTime ( operation, temporalTime, temporalDurationLike )

The abstract operation AddDurationToTime 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 a throw 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. Let duration be ? ToTemporalDuration(temporalDurationLike).
  2. If operation is subtract, set duration to CreateNegatedTemporalDuration(duration).
  3. Let internalDuration be ToInternalDurationRecord(duration).
  4. Let result be AddTime(temporalTime.[[Time]], internalDuration.[[Time]]).
  5. Return ! CreateTemporalTime(result).

22.12.5.4 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 a throw 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. Set other to ? ToTemporalTime(other).
  2. Let resolvedOptions be ? GetOptionsObject(options).
  3. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, time, « », "nanosecond", "hour").
  4. Let timeDuration be DifferenceTime(temporalTime.[[Time]], other.[[Time]]).
  5. Set timeDuration to ! RoundTimeDuration(timeDuration, settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  6. Let duration be CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration).
  7. Let result be ! TemporalDurationFromInternal(duration, settings.[[LargestUnit]]).
  8. If operation is since, set result to CreateNegatedTemporalDuration(result).
  9. Return result.

22.13 Temporal.PlainYearMonth Objects

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

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.

22.13.1 The Temporal.PlainYearMonth Constructor

The Temporal.PlainYearMonth constructor:

22.13.1.1 Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendar [ , referenceISODay ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If referenceISODay is undefined, then
    1. Set referenceISODay to 1𝔽.
  3. Let year be ? SnapToInteger(isoYear, truncate).
  4. Let month be ? SnapToInteger(isoMonth, truncate).
  5. If calendar is undefined, set calendar to "iso8601".
  6. If calendar is not a String, throw a TypeError exception.
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let ref be ? SnapToInteger(referenceISODay, truncate).
  9. Let isoDate be ? CreateISODateRecord(year, month, ref).
  10. Return ? CreateTemporalYearMonth(isoDate, calendar, NewTarget).

22.13.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:

22.13.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalYearMonth(item, options).

22.13.2.3 Temporal.PlainYearMonth.compare ( xPlainYearMonth, yPlainYearMonth )

This function performs the following steps when called:

  1. Set xPlainYearMonth to ? ToTemporalYearMonth(xPlainYearMonth).
  2. Set yPlainYearMonth to ? ToTemporalYearMonth(yPlainYearMonth).
  3. Return 𝔽(CompareISODate(xPlainYearMonth.[[ISODate]], yPlainYearMonth.[[ISODate]])).

22.13.3 Properties of the Temporal.PlainYearMonth Prototype Object

The Temporal.PlainYearMonth prototype object

Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

22.13.3.1 Temporal.PlainYearMonth.prototype.constructor

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

22.13.3.2 Temporal.PlainYearMonth.prototype[ %Symbol.toStringTag% ]

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

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

22.13.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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return plainYearMonth.[[Calendar]].

22.13.3.4 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 result be CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[Era]].
  4. If result is empty, return undefined.
  5. Return result.

22.13.3.5 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 result be CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[EraYear]].
  4. If result is empty, return undefined.
  5. Return 𝔽(result).

22.13.3.6 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return 𝔽(CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[Year]]).

22.13.3.7 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return 𝔽(CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[Month]]).

22.13.3.8 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[MonthCode]].

22.13.3.9 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return 𝔽(CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[DaysInYear]]).

22.13.3.10 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return 𝔽(CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[DaysInMonth]]).

22.13.3.11 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return 𝔽(CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[MonthsInYear]]).

22.13.3.12 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return CalendarISOToDate(plainYearMonth.[[Calendar]], plainYearMonth.[[ISODate]]).[[InLeapYear]].

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

This method performs the following steps when called:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. If ? IsPartialTemporalObject(temporalYearMonthLike) is false, throw a TypeError exception.
  4. Let calendar be plainYearMonth.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainYearMonth.[[ISODate]], year-month).
  6. Let partialYearMonth be ? PrepareCalendarFields(calendar, temporalYearMonthLike, year-month-fields, no-non-calendar-fields, partial).
  7. Set fields to CalendarMergeFields(calendar, fields, partialYearMonth).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  10. Let isoDate be ? CalendarYearMonthFromFields(calendar, fields, overflow).
  11. Return ! CreateTemporalYearMonth(isoDate, calendar).

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

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

This method performs the following steps when called:

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

22.13.3.18 Temporal.PlainYearMonth.prototype.equals ( other )

This method performs the following steps when called:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Set other to ? ToTemporalYearMonth(other).
  4. If CompareISODate(plainYearMonth.[[ISODate]], other.[[ISODate]]) ≠ 0, return false.
  5. If plainYearMonth.[[Calendar]] is not other.[[Calendar]], return false.
  6. Return true.

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

This method performs the following steps when called:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let showCalendar be ? GetTemporalShowCalendarNameOption(resolvedOptions).
  5. Return TemporalYearMonthToString(plainYearMonth, showCalendar).

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

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. Return TemporalYearMonthToString(plainYearMonth, "auto").

22.13.3.21 Temporal.PlainYearMonth.prototype.toJSON ( )

This method performs the following steps when called:

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

22.13.3.22 Temporal.PlainYearMonth.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as plainYearMonth1 > plainYearMonth2 would fall back to being equivalent to plainYearMonth1.toString() > plainYearMonth2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.PlainYearMonth.compare (22.13.2.3), Temporal.PlainYearMonth.prototype.equals (22.13.3.18), and/or Temporal.PlainYearMonth.prototype.toString (22.13.3.19).

22.13.3.23 Temporal.PlainYearMonth.prototype.toPlainDate ( item )

This method performs the following steps when called:

  1. Let plainYearMonth be the this value.
  2. Perform ? RequireInternalSlot(plainYearMonth, [[InitializedTemporalYearMonth]]).
  3. If item is not an Object, throw a TypeError exception.
  4. Let calendar be plainYearMonth.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainYearMonth.[[ISODate]], year-month).
  6. Let inputFields be ? PrepareCalendarFields(calendar, item, only-day, no-non-calendar-fields, no-required-fields).
  7. Let mergedFields be CalendarMergeFields(calendar, fields, inputFields).
  8. Let isoDate be ? CalendarDateFromFields(calendar, mergedFields, "constrain").
  9. Return ! CreateTemporalDate(isoDate, calendar).

22.13.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 83.

Table 83: 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.
[[ISODate]] An ISO Date Record. The [[Day]] field is used by the calendar in the [[Calendar]] slot to disambiguate if the [[Year]] and [[Month]] fields are not sufficient to uniquely identify a year and month in that calendar.
[[Calendar]] A known calendar type.

22.13.5 Abstract Operations for Temporal.PlainYearMonth Objects

22.13.5.1 CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] )

The abstract operation CreateTemporalYearMonth takes arguments isoDate (an ISO Date Record) and calendar (a known calendar type) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainYearMonth or a throw completion. It creates a Temporal.PlainYearMonth instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If ISOYearMonthWithinLimits(isoDate) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.PlainYearMonth%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainYearMonth.prototype%", « [[InitializedTemporalYearMonth]], [[ISODate]], [[Calendar]] »).
  4. Set object.[[ISODate]] to isoDate.
  5. Set object.[[Calendar]] to calendar.
  6. Return object.

22.13.5.2 ToTemporalYearMonth ( item [ , options ] )

The abstract operation ToTemporalYearMonth takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainYearMonth, or a throw completion. 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 item is an Object, then
    1. If item has an [[InitializedTemporalYearMonth]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalYearMonth(item.[[ISODate]], item.[[Calendar]]).
    2. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(item).
    3. Let fields be ? PrepareCalendarFields(calendar, item, year-month-fields, no-non-calendar-fields, no-required-fields).
    4. Let resolvedOptions be ? GetOptionsObject(options).
    5. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    6. Let isoDate be ? CalendarYearMonthFromFields(calendar, fields, overflow).
    7. Return ! CreateTemporalYearMonth(isoDate, calendar).
  3. If item is not a String, throw a TypeError exception.
  4. Let result be ? ParseISODateTime(item, year-month).
  5. Let calendar be result.[[Calendar]].
  6. If calendar is empty, set calendar to "iso8601".
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Perform ? GetTemporalOverflowOption(resolvedOptions).
  10. Let isoDate be ! CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]).
  11. If ISOYearMonthWithinLimits(isoDate) is false, throw a RangeError exception.
  12. Set result to ISODateToFields(calendar, isoDate, year-month).
  13. NOTE: The following operation is called with "constrain" regardless of overflow, in order for the calendar to store a canonical value in the [[Day]] field of the [[ISODate]] internal slot of the result.
  14. Set isoDate to ? CalendarYearMonthFromFields(calendar, result, "constrain").
  15. Return ! CreateTemporalYearMonth(isoDate, calendar).

22.13.5.3 TemporalYearMonthToString ( yearMonth, showCalendar )

The abstract operation TemporalYearMonthToString takes arguments yearMonth (a Temporal.PlainYearMonth) and showCalendar ("auto", "always", "never", or "critical") and returns a String. It formats yearMonth as an ISO 8601 / RFC 9557 string. It performs the following steps when called:

  1. Let year be PadISOYear(yearMonth.[[ISODate]].[[Year]]).
  2. Let month be ToZeroPaddedDecimalString(yearMonth.[[ISODate]].[[Month]], 2).
  3. Let result be the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and month.
  4. If showCalendar is one of "always" or "critical", or yearMonth.[[Calendar]] is not "iso8601", then
    1. Let day be ToZeroPaddedDecimalString(yearMonth.[[ISODate]].[[Day]], 2).
    2. Set result to the string-concatenation of result, the code unit 0x002D (HYPHEN-MINUS), and day.
  5. Let calendarString be FormatCalendarAnnotation(yearMonth.[[Calendar]], showCalendar).
  6. Set result to the string-concatenation of result and calendarString.
  7. Return result.

22.13.5.4 AddDurationToYearMonth ( operation, yearMonth, temporalDurationLike, options )

The abstract operation AddDurationToYearMonth 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 a throw 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, set duration to CreateNegatedTemporalDuration(duration).
  3. Let internalDuration be ToInternalDurationRecord(duration).
  4. Let resolvedOptions be ? GetOptionsObject(options).
  5. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  6. Let durationToAdd be internalDuration.[[Date]].
  7. If durationToAdd.[[Weeks]] ≠ 0, or durationToAdd.[[Days]] ≠ 0, or internalDuration.[[Time]] ≠ 0, throw a RangeError exception.
  8. Let calendar be yearMonth.[[Calendar]].
  9. Let fields be ISODateToFields(calendar, yearMonth.[[ISODate]], year-month).
  10. Set fields.[[Day]] to 1.
  11. Let date be ? CalendarDateFromFields(calendar, fields, "constrain").
  12. Let addedDate be ? CalendarDateAdd(calendar, date, durationToAdd, overflow).
  13. Let addedDateFields be ISODateToFields(calendar, addedDate, year-month).
  14. Let isoDate be ? CalendarYearMonthFromFields(calendar, addedDateFields, overflow).
  15. Return ! CreateTemporalYearMonth(isoDate, calendar).

22.13.5.5 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 a throw 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. Set other to ? ToTemporalYearMonth(other).
  2. Let calendar be yearMonth.[[Calendar]].
  3. If calendar is not other.[[Calendar]], throw a RangeError exception.
  4. Let resolvedOptions be ? GetOptionsObject(options).
  5. Let settings be ? GetDifferenceSettings(operation, resolvedOptions, date, « "week", "day" », "month", "year").
  6. If CompareISODate(yearMonth.[[ISODate]], other.[[ISODate]]) = 0, return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
  7. Let thisFields be ISODateToFields(calendar, yearMonth.[[ISODate]], year-month).
  8. Set thisFields.[[Day]] to 1.
  9. Let thisDate be ? CalendarDateFromFields(calendar, thisFields, "constrain").
  10. Let otherFields be ISODateToFields(calendar, other.[[ISODate]], year-month).
  11. Set otherFields.[[Day]] to 1.
  12. Let otherDate be ? CalendarDateFromFields(calendar, otherFields, "constrain").
  13. Let dateDifference be CalendarDateUntil(calendar, thisDate, otherDate, settings.[[LargestUnit]]).
  14. Let yearsMonthsDifference be ! AdjustDateDurationRecord(dateDifference, 0, 0).
  15. Let duration be CombineDateAndTimeDuration(yearsMonthsDifference, 0).
  16. If settings.[[SmallestUnit]] is not "month" or settings.[[RoundingIncrement]] ≠ 1, then
    1. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: thisDate, [[Time]]: MidnightTimeRecord() }.
    2. Let originEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTime).
    3. Let isoDateTimeOther be the ISO Date-Time Record { [[ISODate]]: otherDate, [[Time]]: MidnightTimeRecord() }.
    4. Let destEpochNanoseconds be GetUTCEpochNanoseconds(isoDateTimeOther).
    5. Set duration to ? RoundRelativeDuration(duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, no-time-zone, calendar, settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
  17. Let result be ! TemporalDurationFromInternal(duration, "day").
  18. If operation is since, set result to CreateNegatedTemporalDuration(result).
  19. Return result.

22.13.5.6 ISO Year-Month Records

An ISO Year-Month Record is a Record used to represent a valid month in the ISO 8601 calendar, although the year may be outside of the allowed range for Temporal.

ISO Year-Month Records have the fields listed in Table 84.

Table 84: ISO Year-Month Record Fields
Field Name Value Meaning
[[Year]] an integer The year in the ISO 8601 calendar.
[[Month]] an integer in the inclusive interval from 1 to 12 The number of the month in the ISO 8601 calendar.

22.13.5.7 BalanceISOYearMonth ( year, month )

The abstract operation BalanceISOYearMonth takes arguments year (an integer) and month (an integer) and returns an ISO Year-Month Record. It performs the following steps when called:

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

22.13.5.8 ISOYearMonthWithinLimits ( isoDate )

The abstract operation ISOYearMonthWithinLimits takes argument isoDate (an ISO Date Record) and returns a Boolean. It returns true if its argument represents a month within the range that a Temporal.PlainYearMonth object can represent, and false otherwise. It performs the following steps when called:

  1. If isoDate.[[Year]] is not in the inclusive interval from -271821 to 275760, return false.
  2. If isoDate.[[Year]] = -271821 and isoDate.[[Month]] < 4, return false.
  3. If isoDate.[[Year]] = 275760 and isoDate.[[Month]] > 9, return false.
  4. Return true.

22.14 Temporal.PlainMonthDay Objects

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

22.14.1 The Temporal.PlainMonthDay Constructor

The Temporal.PlainMonthDay constructor:

22.14.1.1 Temporal.PlainMonthDay ( isoMonth, isoDay [ , calendar [ , referenceISOYear ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, 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 month be ? SnapToInteger(isoMonth, truncate).
  4. Let day be ? SnapToInteger(isoDay, truncate).
  5. If calendar is undefined, set calendar to "iso8601".
  6. If calendar is not a String, throw a TypeError exception.
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let ref be ? SnapToInteger(referenceISOYear, truncate).
  9. Let isoDate be ? CreateISODateRecord(ref, month, day).
  10. Return ? CreateTemporalMonthDay(isoDate, calendar, NewTarget).

22.14.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:

22.14.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 }.

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

This function performs the following steps when called:

  1. Return ? ToTemporalMonthDay(item, options).

22.14.3 Properties of the Temporal.PlainMonthDay Prototype Object

The Temporal.PlainMonthDay prototype object

Note
An ECMAScript implementation that includes the ECMA-402 Internationalization API extends this prototype with additional properties in order to represent calendar data.

22.14.3.1 Temporal.PlainMonthDay.prototype.constructor

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

22.14.3.2 Temporal.PlainMonthDay.prototype[ %Symbol.toStringTag% ]

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

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

22.14.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 plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Return plainMonthDay.[[Calendar]].

22.14.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 plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Return CalendarISOToDate(plainMonthDay.[[Calendar]], plainMonthDay.[[ISODate]]).[[MonthCode]].

22.14.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 plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Return 𝔽(CalendarISOToDate(plainMonthDay.[[Calendar]], plainMonthDay.[[ISODate]]).[[Day]]).

22.14.3.6 Temporal.PlainMonthDay.prototype.with ( temporalMonthDayLike [ , options ] )

This method performs the following steps when called:

  1. Let plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. If ? IsPartialTemporalObject(temporalMonthDayLike) is false, throw a TypeError exception.
  4. Let calendar be plainMonthDay.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainMonthDay.[[ISODate]], month-day).
  6. Let partialMonthDay be ? PrepareCalendarFields(calendar, temporalMonthDayLike, date-fields, no-non-calendar-fields, partial).
  7. Set fields to CalendarMergeFields(calendar, fields, partialMonthDay).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
  10. Let isoDate be ? CalendarMonthDayFromFields(calendar, fields, overflow).
  11. Return ! CreateTemporalMonthDay(isoDate, calendar).

22.14.3.7 Temporal.PlainMonthDay.prototype.equals ( other )

This method performs the following steps when called:

  1. Let plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Set other to ? ToTemporalMonthDay(other).
  4. If CompareISODate(plainMonthDay.[[ISODate]], other.[[ISODate]]) ≠ 0, return false.
  5. If plainMonthDay.[[Calendar]] is not other.[[Calendar]], return false.
  6. Return true.

22.14.3.8 Temporal.PlainMonthDay.prototype.toString ( [ options ] )

This method performs the following steps when called:

  1. Let plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let showCalendar be ? GetTemporalShowCalendarNameOption(resolvedOptions).
  5. Return TemporalMonthDayToString(plainMonthDay, showCalendar).

22.14.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 ECMA-402. Otherwise, the following specification of this method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Return TemporalMonthDayToString(plainMonthDay, "auto").

22.14.3.10 Temporal.PlainMonthDay.prototype.toJSON ( )

This method performs the following steps when called:

  1. Let plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. Return TemporalMonthDayToString(plainMonthDay, "auto").

22.14.3.11 Temporal.PlainMonthDay.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as plainMonthDay1 > plainMonthDay2 would fall back to being equivalent to plainMonthDay1.toString() > plainMonthDay2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.PlainDate.compare (22.11.2.3) on the corresponding Temporal.PlainDate objects, Temporal.PlainMonthDay.prototype.equals (22.14.3.7), and/or Temporal.PlainMonthDay.prototype.toString (22.14.3.8).

22.14.3.12 Temporal.PlainMonthDay.prototype.toPlainDate ( item )

This method performs the following steps when called:

  1. Let plainMonthDay be the this value.
  2. Perform ? RequireInternalSlot(plainMonthDay, [[InitializedTemporalMonthDay]]).
  3. If item is not an Object, throw a TypeError exception.
  4. Let calendar be plainMonthDay.[[Calendar]].
  5. Let fields be ISODateToFields(calendar, plainMonthDay.[[ISODate]], month-day).
  6. Let inputFields be ? PrepareCalendarFields(calendar, item, only-year, no-non-calendar-fields, no-required-fields).
  7. Let mergedFields be CalendarMergeFields(calendar, fields, inputFields).
  8. Let isoDate be ? CalendarDateFromFields(calendar, mergedFields, "constrain").
  9. Return ! CreateTemporalDate(isoDate, calendar).

22.14.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 85.

Table 85: 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.
[[ISODate]] An ISO Date Record. The [[Year]] field is used by the calendar in the [[Calendar]] slot to disambiguate if the [[Month]] and [[Day]] fields are not sufficient to uniquely identify a month and day in that calendar.
[[Calendar]] A known calendar type.

22.14.5 Abstract Operations for Temporal.PlainMonthDay Objects

22.14.5.1 CreateTemporalMonthDay ( isoDate, calendar [ , newTarget ] )

The abstract operation CreateTemporalMonthDay takes arguments isoDate (an ISO Date Record) and calendar (a known calendar type) and optional argument newTarget (a constructor) and returns either a normal completion containing a Temporal.PlainMonthDay or a throw completion. It creates a Temporal.PlainMonthDay instance and fills the internal slots with valid values. It performs the following steps when called:

  1. If ISODateWithinLimits(isoDate) is false, throw a RangeError exception.
  2. If newTarget is not present, set newTarget to %Temporal.PlainMonthDay%.
  3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainMonthDay.prototype%", « [[InitializedTemporalMonthDay]], [[ISODate]], [[Calendar]] »).
  4. Set object.[[ISODate]] to isoDate.
  5. Set object.[[Calendar]] to calendar.
  6. Return object.

22.14.5.2 ToTemporalMonthDay ( item [ , options ] )

The abstract operation ToTemporalMonthDay takes argument item (an ECMAScript language value) and optional argument options (an ECMAScript language value) and returns either a normal completion containing a Temporal.PlainMonthDay or a throw completion. 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 item is an Object, then
    1. If item has an [[InitializedTemporalMonthDay]] internal slot, then
      1. Let resolvedOptions be ? GetOptionsObject(options).
      2. Perform ? GetTemporalOverflowOption(resolvedOptions).
      3. Return ! CreateTemporalMonthDay(item.[[ISODate]], item.[[Calendar]]).
    2. Let calendar be ? GetTemporalCalendarIdentifierWithISODefault(item).
    3. Let fields be ? PrepareCalendarFields(calendar, item, date-fields, no-non-calendar-fields, no-required-fields).
    4. Let resolvedOptions be ? GetOptionsObject(options).
    5. Let overflow be ? GetTemporalOverflowOption(resolvedOptions).
    6. Let isoDate be ? CalendarMonthDayFromFields(calendar, fields, overflow).
    7. Return ! CreateTemporalMonthDay(isoDate, calendar).
  3. If item is not a String, throw a TypeError exception.
  4. Let result be ? ParseISODateTime(item, month-day).
  5. Let calendar be result.[[Calendar]].
  6. If calendar is empty, set calendar to "iso8601".
  7. Set calendar to ? CanonicalizeCalendar(calendar).
  8. Let resolvedOptions be ? GetOptionsObject(options).
  9. Perform ? GetTemporalOverflowOption(resolvedOptions).
  10. If calendar is "iso8601", then
    1. Let referenceISOYear be 1972 (the first ISO 8601 leap year after the epoch).
    2. Let isoDate be ! CreateISODateRecord(referenceISOYear, result.[[Month]], result.[[Day]]).
    3. Return ! CreateTemporalMonthDay(isoDate, calendar).
  11. Let isoDate be ! CreateISODateRecord(result.[[Year]], result.[[Month]], result.[[Day]]).
  12. If ISODateWithinLimits(isoDate) is false, throw a RangeError exception.
  13. Set result to ISODateToFields(calendar, isoDate, month-day).
  14. NOTE: The following operation is called with "constrain" regardless of overflow, in order for the calendar to store a canonical value in the [[Year]] field of the [[ISODate]] internal slot of the result.
  15. Set isoDate to ? CalendarMonthDayFromFields(calendar, result, "constrain").
  16. Return ! CreateTemporalMonthDay(isoDate, calendar).

22.14.5.3 TemporalMonthDayToString ( monthDay, showCalendar )

The abstract operation TemporalMonthDayToString takes arguments monthDay (a Temporal.PlainMonthDay) and showCalendar ("auto", "always", "never", or "critical") and returns a String. It formats monthDay into an ISO 8601 / RFC 9557 string. It performs the following steps when called:

  1. Let month be ToZeroPaddedDecimalString(monthDay.[[ISODate]].[[Month]], 2).
  2. Let day be ToZeroPaddedDecimalString(monthDay.[[ISODate]].[[Day]], 2).
  3. Let result be the string-concatenation of month, the code unit 0x002D (HYPHEN-MINUS), and day.
  4. If showCalendar is one of "always" or "critical", or monthDay.[[Calendar]] is not "iso8601", then
    1. Let year be PadISOYear(monthDay.[[ISODate]].[[Year]]).
    2. Set result to the string-concatenation of year, the code unit 0x002D (HYPHEN-MINUS), and result.
  5. Let calendarString be FormatCalendarAnnotation(monthDay.[[Calendar]], showCalendar).
  6. Set result to the string-concatenation of result and calendarString.
  7. Return result.

22.15 Temporal.Duration Objects

A Temporal.Duration object describes the difference in elapsed time between two other Temporal objects of the same type: Temporal.Instant, Temporal.PlainDate, Temporal.PlainDateTime, Temporal.PlainTime, Temporal.PlainYearMonth, or Temporal.ZonedDateTime.

22.15.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.

22.15.1.1 Temporal.Duration ( [ yearsValue [ , monthsValue [ , weeksValue [ , daysValue [ , hoursValue [ , minutesValue [ , secondsValue [ , millisecondsValue [ , microsecondsValue [ , nanosecondsValue ] ] ] ] ] ] ] ] ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If yearsValue is undefined, let years be 0; else let years be ? SnapToInteger(yearsValue, reject).
  3. If monthsValue is undefined, let months be 0; else let months be ? SnapToInteger(monthsValue, reject).
  4. If weeksValue is undefined, let weeks be 0; else let weeks be ? SnapToInteger(weeksValue, reject).
  5. If daysValue is undefined, let days be 0; else let days be ? SnapToInteger(daysValue, reject).
  6. If hoursValue is undefined, let hours be 0; else let hours be ? SnapToInteger(hoursValue, reject).
  7. If minutesValue is undefined, let minutes be 0; else let minutes be ? SnapToInteger(minutesValue, reject).
  8. If secondsValue is undefined, let seconds be 0; else let seconds be ? SnapToInteger(secondsValue, reject).
  9. If millisecondsValue is undefined, let milliseconds be 0; else let milliseconds be ? SnapToInteger(millisecondsValue, reject).
  10. If microsecondsValue is undefined, let microseconds be 0; else let microseconds be ? SnapToInteger(microsecondsValue, reject).
  11. If nanosecondsValue is undefined, let nanoseconds be 0; else let nanoseconds be ? SnapToInteger(nanosecondsValue, reject).
  12. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, NewTarget).

22.15.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:

22.15.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 }.

22.15.2.2 Temporal.Duration.from ( item )

This function performs the following steps when called:

  1. Return ? ToTemporalDuration(item).

22.15.2.3 Temporal.Duration.compare ( xDurationLike, yDurationLike [ , options ] )

This function performs the following steps when called:

  1. Set xDurationLike to ? ToTemporalDuration(xDurationLike).
  2. Set yDurationLike to ? ToTemporalDuration(yDurationLike).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let relativeToRecord be ? GetTemporalRelativeToOption(resolvedOptions).
  5. If xDurationLike.[[Years]] = yDurationLike.[[Years]], and xDurationLike.[[Months]] = yDurationLike.[[Months]], and xDurationLike.[[Weeks]] = yDurationLike.[[Weeks]], and xDurationLike.[[Days]] = yDurationLike.[[Days]], and xDurationLike.[[Hours]] = yDurationLike.[[Hours]], and xDurationLike.[[Minutes]] = yDurationLike.[[Minutes]], and xDurationLike.[[Seconds]] = yDurationLike.[[Seconds]], and xDurationLike.[[Milliseconds]] = yDurationLike.[[Milliseconds]], and xDurationLike.[[Microseconds]] = yDurationLike.[[Microseconds]], and xDurationLike.[[Nanoseconds]] = yDurationLike.[[Nanoseconds]], then
    1. Return +0𝔽.
  6. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  7. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  8. Let xLargestUnit be DefaultTemporalLargestUnit(xDurationLike).
  9. Let yLargestUnit be DefaultTemporalLargestUnit(yDurationLike).
  10. Let xDuration be ToInternalDurationRecord(xDurationLike).
  11. Let yDuration be ToInternalDurationRecord(yDurationLike).
  12. If zonedRelativeTo is not empty, and xLargestUnit is a date unit or yLargestUnit is a date unit, then
    1. Let timeZone be zonedRelativeTo.[[TimeZone]].
    2. Let calendar be zonedRelativeTo.[[Calendar]].
    3. Let xAfter be ? AddZonedDateTime(zonedRelativeTo.[[EpochNanoseconds]], timeZone, calendar, xDuration, "constrain").
    4. Let yAfter be ? AddZonedDateTime(zonedRelativeTo.[[EpochNanoseconds]], timeZone, calendar, yDuration, "constrain").
    5. If xAfter > yAfter, return 1𝔽.
    6. If xAfter < yAfter, return -1𝔽.
    7. Return +0𝔽.
  13. If xLargestUnit is a calendar unit or yLargestUnit is a calendar unit, then
    1. If plainRelativeTo is empty, throw a RangeError exception.
    2. Let xDays be ? DateDurationDays(xDuration.[[Date]], plainRelativeTo).
    3. Let yDays be ? DateDurationDays(yDuration.[[Date]], plainRelativeTo).
  14. Else,
    1. Let xDays be xDurationLike.[[Days]].
    2. Let yDays be yDurationLike.[[Days]].
  15. Let xTimeDuration be ? Add24HourDaysToTimeDuration(xDuration.[[Time]], xDays).
  16. Let yTimeDuration be ? Add24HourDaysToTimeDuration(yDuration.[[Time]], yDays).
  17. If xTimeDuration > yTimeDuration, return 1𝔽.
  18. If xTimeDuration < yTimeDuration, return -1𝔽.
  19. Return +0𝔽.

22.15.3 Properties of the Temporal.Duration Prototype Object

The Temporal.Duration prototype object

22.15.3.1 Temporal.Duration.prototype.constructor

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

22.15.3.2 Temporal.Duration.prototype[ %Symbol.toStringTag% ]

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

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

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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]]).

22.15.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)).

22.15.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. If DurationSign(duration) = 0, return true.
  4. Return false.

22.15.3.15 Temporal.Duration.prototype.with ( temporalDurationLike )

This method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let partial be ? ToPartialDurationRecord(temporalDurationLike).
  4. If partial.[[Years]] is not empty, let years be partial.[[Years]]; else, let years be duration.[[Years]].
  5. If partial.[[Months]] is not empty, let months be partial.[[Months]]; else, let months be duration.[[Months]].
  6. If partial.[[Weeks]] is not empty, let weeks be partial.[[Weeks]]; else, let weeks be duration.[[Weeks]].
  7. If partial.[[Days]] is not empty, let days be partial.[[Days]]; else, let days be duration.[[Days]].
  8. If partial.[[Hours]] is not empty, let hours be partial.[[Hours]]; else, let hours be duration.[[Hours]].
  9. If partial.[[Minutes]] is not empty, let minutes be partial.[[Minutes]]; else, let minutes be duration.[[Minutes]].
  10. If partial.[[Seconds]] is not empty, let seconds be partial.[[Seconds]]; else, let seconds be duration.[[Seconds]].
  11. If partial.[[Milliseconds]] is not empty, let milliseconds be partial.[[Milliseconds]]; else, let milliseconds be duration.[[Milliseconds]].
  12. If partial.[[Microseconds]] is not empty, let microseconds be partial.[[Microseconds]]; else, let microseconds be duration.[[Microseconds]].
  13. If partial.[[Nanoseconds]] is not empty, let nanoseconds be partial.[[Nanoseconds]]; else, let nanoseconds be duration.[[Nanoseconds]].
  14. Return ? CreateTemporalDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).

22.15.3.16 Temporal.Duration.prototype.negated ( )

This method performs the following steps when called:

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

22.15.3.17 Temporal.Duration.prototype.abs ( )

This 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]])).

22.15.3.18 Temporal.Duration.prototype.add ( other )

This method performs the following steps when called:

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

22.15.3.19 Temporal.Duration.prototype.subtract ( other )

This method performs the following steps when called:

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

22.15.3.20 Temporal.Duration.prototype.round ( roundTo )

This method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. If roundTo is undefined, throw a TypeError exception.
  4. If roundTo is a 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. Let largestUnit be ? GetTemporalUnitValuedOption(roundTo, "largestUnit", optional).
  9. Let relativeToRecord be ? GetTemporalRelativeToOption(roundTo).
  10. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  11. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  12. Let roundingIncrement be ? GetRoundingIncrementOption(roundTo).
  13. Let roundingMode be ? GetRoundingModeOption(roundTo, "halfExpand").
  14. Let smallestUnit be ? GetTemporalUnitValuedOption(roundTo, "smallestUnit", optional).
  15. If smallestUnit is "auto", throw a RangeError exception.
  16. If smallestUnit is no-unit, then
    1. Set smallestUnitPresent to false.
    2. Set smallestUnit to "nanosecond".
  17. Let existingLargestUnit be DefaultTemporalLargestUnit(duration).
  18. Let defaultLargestUnit be LargerOfTwoTemporalUnits(existingLargestUnit, smallestUnit).
  19. If largestUnit is no-unit, then
    1. Set largestUnitPresent to false.
    2. Set largestUnit to defaultLargestUnit.
  20. Else if largestUnit is "auto", then
    1. Set largestUnit to defaultLargestUnit.
  21. If smallestUnitPresent is false and largestUnitPresent is false, throw a RangeError exception.
  22. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
  23. Let maximum be MaximumTemporalDurationRoundingIncrement(smallestUnit).
  24. If maximum is not no-maximum, perform ? ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false).
  25. If roundingIncrement > 1, and largestUnit is not smallestUnit, and smallestUnit is a date unit, throw a RangeError exception.
  26. If zonedRelativeTo is not empty, then
    1. Let internalDuration be ToInternalDurationRecord(duration).
    2. Let timeZone be zonedRelativeTo.[[TimeZone]].
    3. Let calendar be zonedRelativeTo.[[Calendar]].
    4. Let relativeEpochNanoseconds be zonedRelativeTo.[[EpochNanoseconds]].
    5. Let targetEpochNanoseconds be ? AddZonedDateTime(relativeEpochNanoseconds, timeZone, calendar, internalDuration, "constrain").
    6. Set internalDuration to ? DifferenceZonedDateTimeWithRounding(relativeEpochNanoseconds, targetEpochNanoseconds, timeZone, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).
    7. If largestUnit is a date unit, set largestUnit to "hour".
    8. Return ? TemporalDurationFromInternal(internalDuration, largestUnit).
  27. If plainRelativeTo is not empty, then
    1. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
    2. Let targetTime be AddTime(MidnightTimeRecord(), internalDuration.[[Time]]).
    3. Let calendar be plainRelativeTo.[[Calendar]].
    4. Let dateDuration be ? AdjustDateDurationRecord(internalDuration.[[Date]], targetTime.[[Days]]).
    5. Let targetDate be ? CalendarDateAdd(calendar, plainRelativeTo.[[ISODate]], dateDuration, "constrain").
    6. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: plainRelativeTo.[[ISODate]], [[Time]]: MidnightTimeRecord() }.
    7. Let targetDateTime be the ISO Date-Time Record { [[ISODate]]: targetDate, [[Time]]: targetTime }.
    8. Set internalDuration to ? DifferencePlainDateTimeWithRounding(isoDateTime, targetDateTime, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).
    9. Return ? TemporalDurationFromInternal(internalDuration, largestUnit).
  28. If existingLargestUnit is a calendar unit or largestUnit is a calendar unit, throw a RangeError exception.
  29. Assert: smallestUnit is not a calendar unit.
  30. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
  31. If smallestUnit is "day", then
    1. Let fractionalDays be TotalTimeDuration(internalDuration.[[Time]], "day").
    2. Let days be RoundNumberToIncrement(fractionalDays, roundingIncrement, roundingMode).
    3. Let dateDuration be ? CreateDateDurationRecord(0, 0, 0, days).
    4. Set internalDuration to CombineDateAndTimeDuration(dateDuration, 0).
  32. Else,
    1. Let timeDuration be ? RoundTimeDuration(internalDuration.[[Time]], roundingIncrement, smallestUnit, roundingMode).
    2. Set internalDuration to CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration).
  33. Return ? TemporalDurationFromInternal(internalDuration, largestUnit).

22.15.3.21 Temporal.Duration.prototype.total ( totalOf )

This 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 totalOf is a 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. Let relativeToRecord be ? GetTemporalRelativeToOption(totalOf).
  7. Let zonedRelativeTo be relativeToRecord.[[ZonedRelativeTo]].
  8. Let plainRelativeTo be relativeToRecord.[[PlainRelativeTo]].
  9. Let unit be ? GetTemporalUnitValuedOption(totalOf, "unit", required).
  10. If unit is "auto", throw a RangeError exception.
  11. If zonedRelativeTo is not empty, then
    1. Let internalDuration be ToInternalDurationRecord(duration).
    2. Let timeZone be zonedRelativeTo.[[TimeZone]].
    3. Let calendar be zonedRelativeTo.[[Calendar]].
    4. Let relativeEpochNanoseconds be zonedRelativeTo.[[EpochNanoseconds]].
    5. Let targetEpochNanoseconds be ? AddZonedDateTime(relativeEpochNanoseconds, timeZone, calendar, internalDuration, "constrain").
    6. Let total be ? DifferenceZonedDateTimeWithTotal(relativeEpochNanoseconds, targetEpochNanoseconds, timeZone, calendar, unit).
  12. Else if plainRelativeTo is not empty, then
    1. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
    2. Let targetTime be AddTime(MidnightTimeRecord(), internalDuration.[[Time]]).
    3. Let calendar be plainRelativeTo.[[Calendar]].
    4. Let dateDuration be ? AdjustDateDurationRecord(internalDuration.[[Date]], targetTime.[[Days]]).
    5. Let targetDate be ? CalendarDateAdd(calendar, plainRelativeTo.[[ISODate]], dateDuration, "constrain").
    6. Let isoDateTime be the ISO Date-Time Record { [[ISODate]]: plainRelativeTo.[[ISODate]], [[Time]]: MidnightTimeRecord() }.
    7. Let targetDateTime be the ISO Date-Time Record { [[ISODate]]: targetDate, [[Time]]: targetTime }.
    8. Let total be ? DifferencePlainDateTimeWithTotal(isoDateTime, targetDateTime, calendar, unit).
  13. Else,
    1. Let largestUnit be DefaultTemporalLargestUnit(duration).
    2. If largestUnit is a calendar unit or unit is a calendar unit, throw a RangeError exception.
    3. Let internalDuration be ToInternalDurationRecordWith24HourDays(duration).
    4. Let total be TotalTimeDuration(internalDuration.[[Time]], unit).
  14. Return 𝔽(total).

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

This method performs the following steps when called:

  1. Let duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Let resolvedOptions be ? GetOptionsObject(options).
  4. Let digits be ? GetTemporalFractionalSecondDigitsOption(resolvedOptions).
  5. Let roundingMode be ? GetRoundingModeOption(resolvedOptions, "trunc").
  6. Let smallestUnit be ? GetTemporalUnitValuedOption(resolvedOptions, "smallestUnit", optional).
  7. Perform ? ValidateTemporalUnitValue(smallestUnit, time).
  8. If smallestUnit is either "hour" or "minute", throw a RangeError exception.
  9. Let precision be ToSecondsStringPrecisionRecord(smallestUnit, digits).
  10. If precision.[[Unit]] is "nanosecond" and precision.[[Increment]] = 1, then
    1. Return TemporalDurationToString(duration, precision.[[Precision]]).
  11. Let largestUnit be DefaultTemporalLargestUnit(duration).
  12. Let internalDuration be ToInternalDurationRecord(duration).
  13. Let timeDuration be ? RoundTimeDuration(internalDuration.[[Time]], precision.[[Increment]], precision.[[Unit]], roundingMode).
  14. Set internalDuration to CombineDateAndTimeDuration(internalDuration.[[Date]], timeDuration).
  15. Let roundedLargestUnit be LargerOfTwoTemporalUnits(largestUnit, "second").
  16. Let roundedDuration be ? TemporalDurationFromInternal(internalDuration, roundedLargestUnit).
  17. Return TemporalDurationToString(roundedDuration, precision.[[Precision]]).

22.15.3.23 Temporal.Duration.prototype.toJSON ( )

This method performs the following steps when called:

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

22.15.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 ECMA-402. Otherwise, the following specification of the Temporal.Duration.prototype.toLocaleString method is used.

The meanings of the optional parameters to this method are defined in ECMA-402; 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 duration be the this value.
  2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
  3. Return TemporalDurationToString(duration, auto).

22.15.3.25 Temporal.Duration.prototype.valueOf ( )

This method performs the following steps when called:

  1. Throw a TypeError exception.
Note

This method always throws, because in the absence of valueOf(), expressions with arithmetic operators such as duration1 > duration2 would fall back to being equivalent to duration1.toString() > duration2.toString(). Lexicographical comparison of serialized strings might not seem obviously wrong, because the result would sometimes be correct. Implementations are encouraged to phrase the error message to point users to Temporal.Duration.compare (22.15.2.3) and/or Temporal.Duration.prototype.toString (22.15.3.22).

22.15.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 86.

A float64-representable integer is an integer that is exactly representable as a Number. 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 Temporal.Duration fields using 64-bit floating-point values.

However, duration arithmetic is not performed in 64-bit floating-point space. In this specification, duration arithmetic is performed on mathematical values, but a correct implementation could use 96-bit integer arithmetic for all but the division operations in NudgeToCalendarUnit and TotalTimeDuration.

The [[Years]], [[Months]], and [[Weeks]] slots are further limited, so a conforming implementation could store them using 32-bit unsigned integers if the overall duration sign is stored separately. Every 32-bit unsigned integer is also a float64-representable integer.

Table 86: 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.

22.15.5 Abstract Operations for Temporal.Duration Objects

22.15.5.1 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 a throw 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.

22.15.5.2 CreateNegatedTemporalDuration ( duration )

The abstract operation CreateNegatedTemporalDuration takes argument duration (a Temporal.Duration) and returns 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]]).

22.15.5.3 TemporalDurationFromInternal ( internalDuration, largestUnit )

The abstract operation TemporalDurationFromInternal takes arguments internalDuration (an Internal Duration Record) and largestUnit (a Temporal unit) and returns either a normal completion containing a Temporal.Duration, or a throw completion. It converts internalDuration back into the form of a Temporal.Duration object, with each component stored separately, at the end of a duration calculation. The time units are balanced up to largestUnit. The conversion may be lossy if largestUnit is "millisecond", "microsecond", or "nanosecond". In that case, the internal slots of the returned Temporal.Duration may contain unsafe (but float64-representable) integers. The result of a lossy conversion may be outside the allowed range for Durations, even if the input was not. It performs the following steps when called:

  1. Let days, hours, minutes, seconds, milliseconds, and microseconds be 0.
  2. Let sign be TimeDurationSign(internalDuration.[[Time]]).
  3. Let nanoseconds be abs(internalDuration.[[Time]]).
  4. If largestUnit is a date unit, 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 ? CreateTemporalDuration(internalDuration.[[Date]].[[Years]], internalDuration.[[Date]].[[Months]], internalDuration.[[Date]].[[Weeks]], internalDuration.[[Date]].[[Days]] + days × sign, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).

22.15.5.4 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. 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 item is an 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. If item is not an Object, then
    1. If item is not a String, throw a TypeError exception.
    2. Return ? ParseTemporalDurationString(item).
  3. Let result be the partial Duration Record { [[Years]]: 0, [[Months]]: 0, [[Weeks]]: 0, [[Days]]: 0, [[Hours]]: 0, [[Minutes]]: 0, [[Seconds]]: 0, [[Milliseconds]]: 0, [[Microseconds]]: 0, [[Nanoseconds]]: 0  }.
  4. Let partial be ? ToPartialDurationRecord(item).
  5. If partial.[[Years]] is not empty, set result.[[Years]] to partial.[[Years]].
  6. If partial.[[Months]] is not empty, set result.[[Months]] to partial.[[Months]].
  7. If partial.[[Weeks]] is not empty, set result.[[Weeks]] to partial.[[Weeks]].
  8. If partial.[[Days]] is not empty, set result.[[Days]] to partial.[[Days]].
  9. If partial.[[Hours]] is not empty, set result.[[Hours]] to partial.[[Hours]].
  10. If partial.[[Minutes]] is not empty, set result.[[Minutes]] to partial.[[Minutes]].
  11. If partial.[[Seconds]] is not empty, set result.[[Seconds]] to partial.[[Seconds]].
  12. If partial.[[Milliseconds]] is not empty, set result.[[Milliseconds]] to partial.[[Milliseconds]].
  13. If partial.[[Microseconds]] is not empty, set result.[[Microseconds]] to partial.[[Microseconds]].
  14. If partial.[[Nanoseconds]] is not empty, set result.[[Nanoseconds]] to partial.[[Nanoseconds]].
  15. Return ? CreateTemporalDuration(result.[[Years]], result.[[Months]], result.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).

22.15.5.5 TemporalDurationToString ( duration, precision )

The abstract operation TemporalDurationToString takes arguments duration (a Temporal.Duration) and precision (either an integer in the inclusive interval from 0 to 9 or auto) and returns a String. It returns a String which is the ISO 8601 representation of duration, 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(duration).
  2. Let datePart be the empty String.
  3. If duration.[[Years]] ≠ 0, then
    1. Set datePart to the string-concatenation of:
      • the code units of the decimal representation of abs(duration.[[Years]])
      • the code unit 0x0059 (LATIN CAPITAL LETTER Y)
  4. If duration.[[Months]] ≠ 0, then
    1. Set datePart to the string-concatenation of:
      • datePart
      • the code units of the decimal representation of abs(duration.[[Months]])
      • the code unit 0x004D (LATIN CAPITAL LETTER M)
  5. If duration.[[Weeks]] ≠ 0, then
    1. Set datePart to the string-concatenation of:
      • datePart
      • the code units of the decimal representation of abs(duration.[[Weeks]])
      • the code unit 0x0057 (LATIN CAPITAL LETTER W)
  6. If duration.[[Days]] ≠ 0, then
    1. Set datePart to the string-concatenation of:
      • datePart
      • the code units of the decimal representation of abs(duration.[[Days]])
      • the code unit 0x0044 (LATIN CAPITAL LETTER D)
  7. Let timePart be the empty String.
  8. If duration.[[Hours]] ≠ 0, then
    1. Set timePart to the string-concatenation of:
      • the code units of the decimal representation of abs(duration.[[Hours]])
      • the code unit 0x0048 (LATIN CAPITAL LETTER H)
  9. If duration.[[Minutes]] ≠ 0, then
    1. Set timePart to the string-concatenation of:
      • timePart
      • the code units of the decimal representation of abs(duration.[[Minutes]])
      • the code unit 0x004D (LATIN CAPITAL LETTER M)
  10. Let zeroMinutesAndHigher be false.
  11. If DefaultTemporalLargestUnit(duration) is one of "second", "millisecond", "microsecond", or "nanosecond", set zeroMinutesAndHigher to true.
  12. Let secondsDuration be ! TimeDurationFromComponents(0, 0, duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]]).
  13. If secondsDuration ≠ 0, or zeroMinutesAndHigher is true, or precision is not auto, then
    1. Let subSecondsPart be FormatFractionalSeconds(abs(remainder(secondsDuration, NanosecondsPerSecond)), precision).
    2. Set timePart to the string-concatenation of:
      • timePart
      • the code units of the decimal representation of abs(truncate(secondsDuration / NanosecondsPerSecond))
      • subSecondsPart
      • the code unit 0x0053 (LATIN CAPITAL LETTER S)
  14. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
  15. Let result be the string-concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
  16. If timePart is not the empty String, then
    1. Set result to the string-concatenation of result, the code unit 0x0054 (LATIN CAPITAL LETTER T), and timePart.
  17. Return result.

22.15.5.6 AddDurations ( operation, duration, other )

The abstract operation AddDurations takes arguments operation (add or subtract), duration (a Temporal.Duration), and other (an ECMAScript language value) and returns either a normal completion containing a Temporal.Duration or a throw completion. It adds or subtracts the components of a second duration other to or from those of a first duration duration, resulting in a longer or shorter duration, unless calendar calculations would be required, in which case it throws an exception. It balances the result, ensuring that no mixed signs remain. It performs the following steps when called:

  1. Set other to ? ToTemporalDuration(other).
  2. If operation is subtract, set other to CreateNegatedTemporalDuration(other).
  3. Let xLargestUnit be DefaultTemporalLargestUnit(duration).
  4. Let yLargestUnit be DefaultTemporalLargestUnit(other).
  5. Let largestUnit be LargerOfTwoTemporalUnits(xLargestUnit, yLargestUnit).
  6. If largestUnit is a calendar unit, throw a RangeError exception.
  7. Let xInternalDuration be ToInternalDurationRecordWith24HourDays(duration).
  8. Let yInternalDuration be ToInternalDurationRecordWith24HourDays(other).
  9. Let timeResult be ? AddTimeDuration(xInternalDuration.[[Time]], yInternalDuration.[[Time]]).
  10. Let result be CombineDateAndTimeDuration(ZeroDateDuration(), timeResult).
  11. Return ? TemporalDurationFromInternal(result, largestUnit).

22.15.5.7 DurationSign ( duration )

The abstract operation DurationSign takes argument duration (a Temporal.Duration) and returns -1, 0, or 1. It returns 1 if the most significant non-zero field in the duration argument is positive, and -1 if the most significant non-zero field is negative. If all of duration's fields are zero, it returns 0. It performs the following steps when called:

  1. For each value value of « duration.[[Years]], duration.[[Months]], duration.[[Weeks]], duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]] », do
    1. If value < 0, return -1.
    2. If value > 0, return 1.
  2. Return 0.

22.15.5.8 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) and returns a Boolean. 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 0.
  2. For each value value of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
    1. Assert: 𝔽(value) is finite.
    2. If value < 0, then
      1. If sign > 0, return false.
      2. Set sign to -1.
    3. Else if value > 0, then
      1. If sign < 0, return false.
      2. Set sign to 1.
  3. If years is not in the interval from -232 (exclusive) to 232 (exclusive), return false.
  4. If monthsis not in the interval from -232 (exclusive) to 232 (exclusive), return false.
  5. If weeksis not in the interval from -232 (exclusive) to 232 (exclusive), return false.
  6. Let normalizedNanoseconds be days × NanosecondsPerDay + hours × NanosecondsPerHour + minutes × NanosecondsPerMinute + seconds × NanosecondsPerSecond + (𝔽(milliseconds)) × NanosecondsPerMillisecond + (𝔽(microseconds)) × NanosecondsPerMicrosecond + (𝔽(nanoseconds)).
  7. NOTE: The above step cannot be implemented directly using 64-bit 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. The step can be implemented by using 128-bit integers and performing all arithmetic on nanosecond values. It could also 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 normalizedNanoseconds is not in the interval from -253 × NanosecondsPerSecond (exclusive) to 253 × NanosecondsPerSecond (exclusive), return false.
  9. Return true.

22.15.5.9 Partial Duration Records

A partial Duration Record is a Record used to represent input used for construction of a Temporal.Duration object (such as input passed to Temporal.Duration.prototype.with, 22.15.3.15), in which it is not required that all the fields be specified.

Partial Duration Records have the fields listed in Table 87. Additionally, Partial Duration Records must have at least one field that is not empty.

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

22.15.5.10 ToPartialDurationRecord ( temporalDurationLike )

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

  1. If temporalDurationLike is not an Object, throw a TypeError exception.
  2. Let result be the partial Duration Record { [[Years]]: empty, [[Months]]: empty, [[Weeks]]: empty, [[Days]]: empty, [[Hours]]: empty, [[Minutes]]: empty, [[Seconds]]: empty, [[Milliseconds]]: empty, [[Microseconds]]: empty, [[Nanoseconds]]: empty  }.
  3. Let days be ? Get(temporalDurationLike, "days").
  4. If days is not undefined, set result.[[Days]] to ? SnapToInteger(days, reject).
  5. Let hours be ? Get(temporalDurationLike, "hours").
  6. If hours is not undefined, set result.[[Hours]] to ? SnapToInteger(hours, reject).
  7. Let microseconds be ? Get(temporalDurationLike, "microseconds").
  8. If microseconds is not undefined, set result.[[Microseconds]] to ? SnapToInteger(microseconds, reject).
  9. Let milliseconds be ? Get(temporalDurationLike, "milliseconds").
  10. If milliseconds is not undefined, set result.[[Milliseconds]] to ? SnapToInteger(milliseconds, reject).
  11. Let minutes be ? Get(temporalDurationLike, "minutes").
  12. If minutes is not undefined, set result.[[Minutes]] to ? SnapToInteger(minutes, reject).
  13. Let months be ? Get(temporalDurationLike, "months").
  14. If months is not undefined, set result.[[Months]] to ? SnapToInteger(months, reject).
  15. Let nanoseconds be ? Get(temporalDurationLike, "nanoseconds").
  16. If nanoseconds is not undefined, set result.[[Nanoseconds]] to ? SnapToInteger(nanoseconds, reject).
  17. Let seconds be ? Get(temporalDurationLike, "seconds").
  18. If seconds is not undefined, set result.[[Seconds]] to ? SnapToInteger(seconds, reject).
  19. Let weeks be ? Get(temporalDurationLike, "weeks").
  20. If weeks is not undefined, set result.[[Weeks]] to ? SnapToInteger(weeks, reject).
  21. Let years be ? Get(temporalDurationLike, "years").
  22. If years is not undefined, set result.[[Years]] to ? SnapToInteger(years, reject).
  23. 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.
  24. Return result.

22.15.5.11 Duration Nudge Result Records

A Duration Nudge Result Record is a Record used to represent the result of rounding a duration up or down to an increment relative to a date-time, as in NudgeToCalendarUnit, NudgeToZonedTime, or NudgeToDayOrTime.

Duration Nudge Result Records have the fields listed in Table 88.

Table 88: Duration Nudge Result Record Fields
Field Name Value Meaning
[[Duration]] an Internal Duration Record The resulting duration.
[[NudgedEpochNanoseconds]] an epoch nanoseconds count The epoch nanoseconds count corresponding to the rounded duration, relative to the starting point.
[[DidExpandCalendarUnit]] a Boolean Whether the rounding operation caused the duration to expand to the next day or larger unit.

22.15.5.12 ComputeNudgeWindow ( sign, duration, originEpochNanoseconds, isoDateTime, timeZone, calendar, increment, unit, additionalShift )

The abstract operation ComputeNudgeWindow takes arguments sign (-1 or 1), duration (an Internal Duration Record), originEpochNanoseconds (an epoch nanoseconds count), isoDateTime (an ISO Date-Time Record), timeZone (either an available time zone identifier or no-time-zone), calendar (a known calendar type), increment (a positive integer), unit (a date unit), and additionalShift (a Boolean) and returns either a normal completion containing a Record with fields [[InnerBound]] (a mathematical value), [[OuterBound]] (a mathematical value), [[StartEpochNanoseconds]] (an epoch nanoseconds count), [[EndEpochNanoseconds]] (an epoch nanoseconds count), [[StartDuration]] (an Internal Duration Record), and [[EndDuration]] (an Internal Duration Record), or a throw completion. It implements calculating the upper and lower bounds of the starting point added to the duration in epoch nanoseconds. It performs the following steps when called:

  1. If unit is "year", then
    1. Let years be RoundNumberToIncrement(duration.[[Date]].[[Years]], increment, "trunc").
    2. If additionalShift is false, then
      1. Let innerBound be years.
    3. Else,
      1. Let innerBound be years + increment × sign.
    4. Let outerBound be innerBound + increment × sign.
    5. Let startDateDuration be ? CreateDateDurationRecord(innerBound, 0, 0, 0).
    6. Let endDateDuration be ? CreateDateDurationRecord(outerBound, 0, 0, 0).
  2. Else if unit is "month", then
    1. Let months be RoundNumberToIncrement(duration.[[Date]].[[Months]], increment, "trunc").
    2. If additionalShift is false, then
      1. Let innerBound be months.
    3. Else,
      1. Let innerBound be months + increment × sign.
    4. Let outerBound be innerBound + increment × sign.
    5. Let startDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, 0, innerBound).
    6. Let endDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, 0, outerBound).
  3. Else if unit is "week", then
    1. Let yearsMonths be ! AdjustDateDurationRecord(duration.[[Date]], 0, 0).
    2. Let weeksStart be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], yearsMonths, "constrain").
    3. Let weeksEnd be AddDaysToISODate(weeksStart, duration.[[Date]].[[Days]]).
    4. Let untilResult be CalendarDateUntil(calendar, weeksStart, weeksEnd, "week").
    5. Let weeks be RoundNumberToIncrement(duration.[[Date]].[[Weeks]] + untilResult.[[Weeks]], increment, "trunc").
    6. Let innerBound be weeks.
    7. Let outerBound be weeks + increment × sign.
    8. Let startDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, innerBound).
    9. Let endDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, outerBound).
  4. Else,
    1. Assert: unit is "day".
    2. Let days be RoundNumberToIncrement(duration.[[Date]].[[Days]], increment, "trunc").
    3. Let innerBound be days.
    4. Let outerBound be days + increment × sign.
    5. Let startDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], innerBound).
    6. Let endDateDuration be ? AdjustDateDurationRecord(duration.[[Date]], outerBound).
  5. Assert: If sign = 1, innerBound ≥ 0 and innerBound < outerBound.
  6. Assert: If sign = -1, innerBound ≤ 0 and innerBound > outerBound.
  7. If DateDurationSign(startDateDuration) = 0, then
    1. Let startEpochNanoseconds be originEpochNanoseconds.
  8. Else,
    1. Let start be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], startDateDuration, "constrain").
    2. Let startDateTime be the ISO Date-Time Record { [[ISODate]]: start, [[Time]]: isoDateTime.[[Time]] }.
    3. If timeZone is no-time-zone, then
      1. Let startEpochNanoseconds be GetUTCEpochNanoseconds(startDateTime).
    4. Else,
      1. Let startEpochNanoseconds be ? GetEpochNanosecondsFor(timeZone, startDateTime, "compatible").
  9. Let end be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], endDateDuration, "constrain").
  10. Let endDateTime be the ISO Date-Time Record { [[ISODate]]: end, [[Time]]: isoDateTime.[[Time]] }.
  11. If timeZone is no-time-zone, then
    1. Let endEpochNanoseconds be GetUTCEpochNanoseconds(endDateTime).
  12. Else,
    1. Let endEpochNanoseconds be ? GetEpochNanosecondsFor(timeZone, endDateTime, "compatible").
  13. Let startDuration be CombineDateAndTimeDuration(startDateDuration, 0).
  14. Let endDuration be CombineDateAndTimeDuration(endDateDuration, 0).
  15. Return the Record { [[InnerBound]]: innerBound, [[OuterBound]]: outerBound, [[StartEpochNanoseconds]]: startEpochNanoseconds, [[EndEpochNanoseconds]]: endEpochNanoseconds, [[StartDuration]]: startDuration, [[EndDuration]]: endDuration }.

22.15.5.13 NudgeToCalendarUnit ( sign, duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, timeZone, calendar, increment, unit, roundingMode )

The abstract operation NudgeToCalendarUnit takes arguments sign (-1 or 1), duration (an Internal Duration Record), originEpochNanoseconds (an epoch nanoseconds count), destEpochNanoseconds (an epoch nanoseconds count), isoDateTime (an ISO Date-Time Record), timeZone (either an available time zone identifier or no-time-zone), calendar (a known calendar type), increment (a positive integer), unit (a date unit), and roundingMode (a rounding mode) and returns either a normal completion containing a Record with fields [[NudgeResult]] (a Duration Nudge Result Record) and [[Total]] (a mathematical value), or a throw completion. It implements rounding a duration to an increment of a calendar unit, relative to a starting point, by calculating the upper and lower bounds of the starting point added to the duration in epoch nanoseconds, and rounding according to which one is closer to destEpochNanoseconds. It performs the following steps when called:

  1. Let didExpandCalendarUnit be false.
  2. Let nudgeWindow be ? ComputeNudgeWindow(sign, duration, originEpochNanoseconds, isoDateTime, timeZone, calendar, increment, unit, false).
  3. Let startEpochNanoseconds be nudgeWindow.[[StartEpochNanoseconds]].
  4. Let endEpochNanoseconds be nudgeWindow.[[EndEpochNanoseconds]].
  5. If sign = 1, then
    1. If startEpochNanosecondsdestEpochNanosecondsendEpochNanoseconds is false, then
      1. Set nudgeWindow to ? ComputeNudgeWindow(sign, duration, originEpochNanoseconds, isoDateTime, timeZone, calendar, increment, unit, true).
      2. Assert: nudgeWindow.[[StartEpochNanoseconds]]destEpochNanosecondsnudgeWindow.[[EndEpochNanoseconds]].
      3. Set didExpandCalendarUnit to true.
  6. Else,
    1. If endEpochNanosecondsdestEpochNanosecondsstartEpochNanoseconds is false, then
      1. Set nudgeWindow to ? ComputeNudgeWindow(sign, duration, originEpochNanoseconds, isoDateTime, timeZone, calendar, increment, unit, true).
      2. Assert: nudgeWindow.[[EndEpochNanoseconds]]destEpochNanosecondsnudgeWindow.[[StartEpochNanoseconds]].
      3. Set didExpandCalendarUnit to true.
  7. Let innerBound be nudgeWindow.[[InnerBound]].
  8. Let outerBound be nudgeWindow.[[OuterBound]].
  9. Set startEpochNanoseconds to nudgeWindow.[[StartEpochNanoseconds]].
  10. Set endEpochNanoseconds to nudgeWindow.[[EndEpochNanoseconds]].
  11. Let startDuration be nudgeWindow.[[StartDuration]].
  12. Let endDuration be nudgeWindow.[[EndDuration]].
  13. Assert: startEpochNanosecondsendEpochNanoseconds.
  14. Let progress be (destEpochNanoseconds - startEpochNanoseconds) / (endEpochNanoseconds - startEpochNanoseconds).
  15. Let total be innerBound + progress × increment × sign.
  16. NOTE: The above two steps cannot be implemented directly using floating-point arithmetic. This division can be implemented as if expressing total as the quotient of two time durations (which may not be safe integers), performing all other calculations before the division, and finally performing one division operation with a floating-point result for total. 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.
  17. Assert: 0 ≤ progress ≤ 1.
  18. If sign < 0, let isNegative be negative; else let isNegative be positive.
  19. Let unsignedRoundingMode be GetUnsignedRoundingMode(roundingMode, isNegative).
  20. If progress = 1, then
    1. Let roundedUnit be abs(outerBound).
  21. Else,
    1. Assert: abs(innerBound) ≤ abs(total) < abs(outerBound).
    2. Let roundedUnit be ApplyUnsignedRoundingMode(abs(total), abs(innerBound), abs(outerBound), unsignedRoundingMode).
  22. If roundedUnit is abs(outerBound), then
    1. Set didExpandCalendarUnit to true.
    2. Let resultDuration be endDuration.
    3. Let nudgedEpochNanoseconds be endEpochNanoseconds.
  23. Else,
    1. Let resultDuration be startDuration.
    2. Let nudgedEpochNanoseconds be startEpochNanoseconds.
  24. Let nudgeResult be Duration Nudge Result Record { [[Duration]]: resultDuration, [[NudgedEpochNanoseconds]]: nudgedEpochNanoseconds, [[DidExpandCalendarUnit]]: didExpandCalendarUnit }.
  25. Return the Record { [[NudgeResult]]: nudgeResult, [[Total]]: total }.

22.15.5.14 NudgeToZonedTime ( sign, duration, isoDateTime, timeZone, calendar, increment, unit, roundingMode )

The abstract operation NudgeToZonedTime takes arguments sign (-1 or 1), duration (an Internal Duration Record), isoDateTime (an ISO Date-Time Record), timeZone (an available time zone identifier), calendar (a known calendar type), increment (a positive integer), unit (a time unit), and roundingMode (a rounding mode) and returns either a normal completion containing a Duration Nudge Result Record or a throw completion. It implements rounding a duration to an increment of a time unit, accounting for the case where the rounding causes the time to exceed the total time within a day, which may be influenced by UTC offset changes in the time zone. This operation is used in duration rounding arithmetic that takes time zones into account, such as that performed by Temporal.ZonedDateTime.prototype.until (22.9.3.37). It performs the following steps when called:

  1. Let start be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], duration.[[Date]], "constrain").
  2. Let startDateTime be the ISO Date-Time Record { [[ISODate]]: start, [[Time]]: isoDateTime.[[Time]] }.
  3. Let endDate be AddDaysToISODate(start, sign).
  4. Let endDateTime be the ISO Date-Time Record { [[ISODate]]: endDate, [[Time]]: isoDateTime.[[Time]] }.
  5. Let startEpochNanoseconds be ? GetEpochNanosecondsFor(timeZone, startDateTime, "compatible").
  6. Let endEpochNanoseconds be ? GetEpochNanosecondsFor(timeZone, endDateTime, "compatible").
  7. Let daySpan be TimeDurationFromEpochNanosecondsDifference(startEpochNanoseconds, endEpochNanoseconds).
  8. Assert: TimeDurationSign(daySpan) = sign.
  9. Let unitLength be TemporalUnitLength(unit).
  10. Let roundedTimeDuration be ? RoundTimeDurationToIncrement(duration.[[Time]], increment × unitLength, roundingMode).
  11. Let beyondDaySpan be ! AddTimeDuration(roundedTimeDuration, -daySpan).
  12. If TimeDurationSign(beyondDaySpan) ≠ -sign, then
    1. Let didRoundBeyondDay be true.
    2. Let dayDelta be sign.
    3. Set roundedTimeDuration to ? RoundTimeDurationToIncrement(beyondDaySpan, increment × unitLength, roundingMode).
    4. Let nudgedEpochNanoseconds be AddTimeDurationToEpochNanoseconds(roundedTimeDuration, endEpochNanoseconds).
  13. Else,
    1. Let didRoundBeyondDay be false.
    2. Let dayDelta be 0.
    3. Let nudgedEpochNanoseconds be AddTimeDurationToEpochNanoseconds(roundedTimeDuration, startEpochNanoseconds).
  14. Let dateDuration be ! AdjustDateDurationRecord(duration.[[Date]], duration.[[Date]].[[Days]] + dayDelta).
  15. Let resultDuration be CombineDateAndTimeDuration(dateDuration, roundedTimeDuration).
  16. Return the Duration Nudge Result Record { [[Duration]]: resultDuration, [[NudgedEpochNanoseconds]]: nudgedEpochNanoseconds, [[DidExpandCalendarUnit]]: didRoundBeyondDay }.

22.15.5.15 NudgeToDayOrTime ( duration, destEpochNanoseconds, largestUnit, increment, smallestUnit, roundingMode )

The abstract operation NudgeToDayOrTime takes arguments duration (an Internal Duration Record), destEpochNanoseconds (an epoch nanoseconds count), largestUnit (a Temporal unit), increment (a positive integer), smallestUnit (either a time unit or "day"), and roundingMode (a rounding mode) and returns either a normal completion containing a Duration Nudge Result Record or a throw completion. It implements rounding a duration to an increment of a time unit, in cases unaffected by the calendar or time zone. It performs the following steps when called:

  1. Let timeDuration be ! Add24HourDaysToTimeDuration(duration.[[Time]], duration.[[Date]].[[Days]]).
  2. Let roundedTime be ? RoundTimeDurationToIncrement(timeDuration, TemporalUnitLength(smallestUnit) × increment, roundingMode).
  3. Let diffTime be ! AddTimeDuration(roundedTime, -timeDuration).
  4. Let wholeDays be truncate(TotalTimeDuration(timeDuration, "day")).
  5. Let roundedWholeDays be truncate(TotalTimeDuration(roundedTime, "day")).
  6. Let dayDelta be roundedWholeDays - wholeDays.
  7. If dayDelta < 0, let dayDeltaSign be -1; else if dayDelta > 0, let dayDeltaSign be 1; else let dayDeltaSign be 0.
  8. If dayDeltaSign = TimeDurationSign(timeDuration), let didExpandDays be true; else let didExpandDays be false.
  9. Let nudgedEpochNanoseconds be AddTimeDurationToEpochNanoseconds(diffTime, destEpochNanoseconds).
  10. Let days be 0.
  11. Let remainder be roundedTime.
  12. If largestUnit is a date unit, then
    1. Set days to roundedWholeDays.
    2. Set remainder to ! AddTimeDuration(roundedTime, ! TimeDurationFromComponents(-roundedWholeDays × HoursPerDay, 0, 0, 0, 0, 0)).
  13. Let dateDuration be ! AdjustDateDurationRecord(duration.[[Date]], days).
  14. Let resultDuration be CombineDateAndTimeDuration(dateDuration, remainder).
  15. Return the Duration Nudge Result Record { [[Duration]]: resultDuration, [[NudgedEpochNanoseconds]]: nudgedEpochNanoseconds, [[DidExpandCalendarUnit]]: didExpandDays }.

22.15.5.16 BubbleRelativeDuration ( sign, duration, nudgedEpochNanoseconds, isoDateTime, timeZone, calendar, largestUnit, startUnit )

The abstract operation BubbleRelativeDuration takes arguments sign (-1 or 1), duration (an Internal Duration Record), nudgedEpochNanoseconds (an epoch nanoseconds count), isoDateTime (an ISO Date-Time Record), timeZone (either an available time zone identifier or no-time-zone), calendar (a known calendar type), largestUnit (a Temporal unit), and startUnit ("month" or "day") and returns either a normal completion containing an Internal Duration Record or a throw completion. Given a duration that has potentially been made bottom-heavy by rounding in NudgeToCalendarUnit, NudgeToZonedTime, or NudgeToDayOrTime, it bubbles up smaller units to larger units. It performs the following steps when called:

  1. If LargerOfTwoTemporalUnits(startUnit, largestUnit) is startUnit, return duration.
  2. Let bubbleUnits be a new empty List.
  3. If largestUnit is "year", prepend "year" to bubbleUnits.
  4. If startUnit is "day", then
    1. If largestUnit is either "year" or "month", prepend "month" to bubbleUnits.
    2. If largestUnit is "week", prepend "week" to bubbleUnits.
  5. For each element unit of bubbleUnits, do
    1. If unit is "year", then
      1. Let years be duration.[[Date]].[[Years]] + sign.
      2. Let endDuration be ? CreateDateDurationRecord(years, 0, 0, 0).
    2. Else if unit is "month", then
      1. Let months be duration.[[Date]].[[Months]] + sign.
      2. Let endDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, 0, months).
    3. Else,
      1. Assert: unit is "week".
      2. Let weeks be duration.[[Date]].[[Weeks]] + sign.
      3. Let endDuration be ? AdjustDateDurationRecord(duration.[[Date]], 0, weeks).
    4. Let end be ? CalendarDateAdd(calendar, isoDateTime.[[ISODate]], endDuration, "constrain").
    5. Let endDateTime be the ISO Date-Time Record { [[ISODate]]: end, [[Time]]: isoDateTime.[[Time]] }.
    6. If timeZone is no-time-zone, then
      1. Let endEpochNanoseconds be GetUTCEpochNanoseconds(endDateTime).
    7. Else,
      1. Let endEpochNanoseconds be ? GetEpochNanosecondsFor(timeZone, endDateTime, "compatible").
    8. Let beyondEnd be nudgedEpochNanoseconds - endEpochNanoseconds.
    9. If beyondEnd < 0, let beyondEndSign be -1; else if beyondEnd > 0, let beyondEndSign be 1; else let beyondEndSign be 0.
    10. If beyondEndSign = -sign, return duration.
    11. Set duration to CombineDateAndTimeDuration(endDuration, 0).
  6. Return duration.

22.15.5.17 RoundRelativeDuration ( duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, timeZone, calendar, largestUnit, increment, smallestUnit, roundingMode )

The abstract operation RoundRelativeDuration takes arguments duration (an Internal Duration Record), originEpochNanoseconds (an epoch nanoseconds count), destEpochNanoseconds (an epoch nanoseconds count), isoDateTime (an ISO Date-Time Record), timeZone (either an available time zone identifier or no-time-zone), calendar (a known calendar type), largestUnit (a Temporal unit), increment (a positive integer), smallestUnit (a Temporal unit), and roundingMode (a rounding mode) and returns either a normal completion containing an Internal Duration Record or a throw completion. It rounds a duration duration relative to isoDateTime according to the rounding parameters smallestUnit, increment, and roundingMode, bubbles overflows up to the next highest unit until largestUnit, and returns the rounded duration. It performs the following steps when called:

  1. Let irregularLengthUnit be false.
  2. If smallestUnit is a calendar unit, set irregularLengthUnit to true.
  3. If timeZone is not no-time-zone and smallestUnit is "day", set irregularLengthUnit to true.
  4. If InternalDurationSign(duration) < 0, let sign be -1; else let sign be 1.
  5. If irregularLengthUnit is true, then
    1. Let record be ? NudgeToCalendarUnit(sign, duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, timeZone, calendar, increment, smallestUnit, roundingMode).
    2. Let nudgeResult be record.[[NudgeResult]].
  6. Else if timeZone is not no-time-zone, then
    1. Let nudgeResult be ? NudgeToZonedTime(sign, duration, isoDateTime, timeZone, calendar, increment, smallestUnit, roundingMode).
  7. Else,
    1. Let nudgeResult be ? NudgeToDayOrTime(duration, destEpochNanoseconds, largestUnit, increment, smallestUnit, roundingMode).
  8. Set duration to nudgeResult.[[Duration]].
  9. If nudgeResult.[[DidExpandCalendarUnit]] is true and smallestUnit is not "year" or "week", then
    1. Let startUnit be LargerOfTwoTemporalUnits(smallestUnit, "day").
    2. Set duration to ? BubbleRelativeDuration(sign, duration, nudgeResult.[[NudgedEpochNanoseconds]], isoDateTime, timeZone, calendar, largestUnit, startUnit).
  10. Return duration.

22.15.5.18 TotalRelativeDuration ( duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, timeZone, calendar, unit )

The abstract operation TotalRelativeDuration takes arguments duration (an Internal Duration Record), originEpochNanoseconds (an epoch nanoseconds count), destEpochNanoseconds (an epoch nanoseconds count), isoDateTime (an ISO Date-Time Record), timeZone (either an available time zone identifier or no-time-zone), calendar (a known calendar type), and unit (a Temporal unit) and returns either a normal completion containing a mathematical value, or a throw completion. It returns the total number of unit in duration, relative to isoDateTime if a starting point is necessary for calendar units. It performs the following steps when called:

  1. If unit is a calendar unit, or timeZone is not no-time-zone and unit is "day", then
    1. If InternalDurationSign(duration) < 0, let sign be -1; else let sign be 1.
    2. Let record be ? NudgeToCalendarUnit(sign, duration, originEpochNanoseconds, destEpochNanoseconds, isoDateTime, timeZone, calendar, 1, unit, "trunc").
    3. Return record.[[Total]].
  2. Let timeDuration be ! Add24HourDaysToTimeDuration(duration.[[Time]], duration.[[Date]].[[Days]]).
  3. Return TotalTimeDuration(timeDuration, unit).