Time Zone Identifiers
Time zones in ECMAScript are represented by time zone identifiers, which are Strings composed entirely of code units in the inclusive interval from 0x0000 to 0x007F0x0021 to 0x007E.
Time zones supported by an ECMAScript implementation may be available named time zones, represented by the [[Identifier]] field of the Time Zone Identifier Records returned by AvailableNamedTimeZoneIdentifiers, or offset time zones, represented by Strings for which IsTimeZoneOffsetStringIsOffsetTimeZoneIdentifier returns *true*.
A primary time zone identifier is the preferred identifier for an available named time zone.
A non-primary time zone identifier is an identifier for an available named time zone that is not a primary time zone identifier.
An available named time zone identifier is either a primary time zone identifier or a non-primary time zone identifier.
Each available named time zone identifier is associated with exactly one available named time zone.
Each available named time zone is associated with exactly one primary time zone identifier and zero or more non-primary time zone identifiers.
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 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| and produced by FormatOffsetTimeZoneIdentifier with _style_ either not present or set to ~separated~.
ECMAScript implementations must support an available named time zone with the identifier *"UTC"*, which must be the primary time zone identifier for the UTC time zone.
In addition, implementations may support any number of other available named time zones.
Implementations that follow the requirements for time zones as described in the ECMA-402 Internationalization API specification are called time zone aware.
Time zone aware implementations must support available named time zones corresponding to the Zone and Link names of the IANA Time Zone Database, and only such names.
In time zone aware implementations, a primary time zone identifier is a Zone name, and a non-primary time zone identifier is a Link name, respectively, in the IANA Time Zone Database except as specifically overridden by AvailableNamedTimeZoneIdentifiers as specified in the ECMA-402 specification.
Implementations that do not support the entire IANA Time Zone Database are still recommended to use IANA Time Zone Database names as identifiers to represent time zones.
GetNamedTimeZoneEpochNanoseconds (
_timeZoneIdentifier_: a String,
_year_: an integer,
_month_: an integer in the inclusive interval from 1 to 12,
_day_: an integer in the inclusive interval from 1 to 31,
_hour_: an integer in the inclusive interval from 0 to 23,
_minute_: an integer in the inclusive interval from 0 to 59,
_second_: an integer in the inclusive interval from 0 to 59,
_millisecond_: an integer in the inclusive interval from 0 to 999,
_microsecond_: an integer in the inclusive interval from 0 to 999,
_nanosecond_: an integer in the inclusive interval from 0 to 999,
_isoDateTime_: an ISO Date-Time Record,
): a List of BigInts
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"*.
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_year_, _month_, _day_, _hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond__isoDateTime_).
1. Return « _epochNanoseconds_ ».
It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.
1:30 AM on 5 November 2017 in America/New_York is repeated twice, so GetNamedTimeZoneEpochNanoseconds(*"America/New_York"*, 2017, 11, 5, 1, 30, 0, 0, 0, 0) 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(*"America/New_York"*, 2017, 3, 12, 2, 30, 0, 0, 0, 0) for that time zone and ISO date-time would return an empty List.
UTC (
_t_: a Number,
): a time value
1. If _t_ is not finite, return *NaN*.
1. Let _systemTimeZoneIdentifier_ be SystemTimeZoneIdentifier().
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_systemTimeZoneIdentifier_).
1. If IsTimeZoneOffsetString(_systemTimeZoneIdentifier_) is *true*_parseResult_.[[OffsetMinutes]] is not ~empty~, then
1. Let _offsetNs_ be ParseTimeZoneOffsetString(_systemTimeZoneIdentifier_)_parseResult_.[[OffsetMinutes]] × (60 × 109).
1. Else,
1. Let _isoDateTime_ be TimeValueToISODateTimeRecord(_t_).
1. Let _possibleInstants_ be GetNamedTimeZoneEpochNanoseconds(_systemTimeZoneIdentifier_, ℝ(YearFromTime(_t_)), ℝ(MonthFromTime(_t_)) + 1, ℝ(DateFromTime(_t_)), ℝ(HourFromTime(_t_)), ℝ(MinFromTime(_t_)), ℝ(SecFromTime(_t_)), ℝ(msFromTime(_t_)), 0, 0_isoDateTime_).
1. 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.
1. If _possibleInstants_ is not empty, then
1. Let _disambiguatedInstant_ be _possibleInstants_[0].
1. 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).
1. [declared="tBefore"] Let _possibleInstantsBefore_ be GetNamedTimeZoneEpochNanoseconds(_systemTimeZoneIdentifier_, ℝ(YearFromTime(_tBefore_)), ℝ(MonthFromTime(_tBefore_)) + 1, ℝ(DateFromTime(_tBefore_)), ℝ(HourFromTime(_tBefore_)), ℝ(MinFromTime(_tBefore_)), ℝ(SecFromTime(_tBefore_)), ℝ(msFromTime(_tBefore_)), 0, 0TimeValueToISODateTimeRecord(_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).
1. Let _disambiguatedInstant_ be the last element of _possibleInstantsBefore_.
1. Let _offsetNs_ be GetNamedTimeZoneOffsetNanoseconds(_systemTimeZoneIdentifier_, _disambiguatedInstant_).
1. Let _offsetMs_ be truncate(_offsetNs_ / 106).
1. Return _t_ - 𝔽(_offsetMs_).
Input _t_ is nominally a time value but may be any Number value.
The algorithm must not limit _t_ to the time value range, so that inputs corresponding with a boundary of the time value range can be supported regardless of local UTC offset.
For example, the maximum time value is 8.64 × 1015, corresponding with *"+275760-09-13T00:00:00Z"*.
In an environment where the local time zone offset is ahead of UTC by 1 hour at that instant, it is represented by the larger input of 8.64 × 1015 + 3.6 × 106, corresponding with *"+275760-09-13T01:00:00+01:00"*.
If political rules for the local time _t_ are not available within the implementation, the result is _t_ because SystemTimeZoneIdentifier returns *"UTC"* and GetNamedTimeZoneOffsetNanoseconds returns 0.
It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.
1:30 AM on 5 November 2017 in America/New_York is repeated twice (fall backward), but it must be interpreted as 1:30 AM UTC-04 instead of 1:30 AM UTC-05.
In UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))), the value of _offsetMs_ is -4 × msPerHour.
2:30 AM on 12 March 2017 in America/New_York does not exist, but it must be interpreted as 2:30 AM UTC-05 (equivalent to 3:30 AM UTC-04).
In UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))), the value of _offsetMs_ is -5 × msPerHour.
UTC(LocalTime(_t_UTC)) is not necessarily always equal to _t_UTC. Correspondingly, LocalTime(UTC(_t_local)) is not necessarily always equal to _t_local.