-
Notifications
You must be signed in to change notification settings - Fork 175
Expand file tree
/
Copy pathtimezone.html
More file actions
434 lines (415 loc) · 24.9 KB
/
timezone.html
File metadata and controls
434 lines (415 loc) · 24.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
<!DOCTYPE html>
<meta charset="utf8">
<emu-clause id="sec-temporal-timezones">
<h1>Time Zones</h1>
<emu-clause id="sec-temporal-timezone-abstract-ops">
<h1>Abstract Operations</h1>
<emu-note type="editor">
In ECMA-262, many time-zone-related sections and abstract operations are contained in the <a href="https://tc39.es/ecma262/#sec-date-objects">Date Objects</a> section of the specification.
It may be appropriate to move those sections here, for example:
<ul>
<li><a href="https://tc39.es/ecma262/#sec-time-zone-identifiers">Time Zone Identifiers</a></li>
<li>AvailableNamedTimeZoneIdentifiers</li>
<li>SystemTimeZoneIdentifier</li>
<li>IsTimeZoneOffsetString</li>
<li>GetNamedTimeZoneEpochNanoseconds</li>
<li>GetNamedTimeZoneOffsetNanoseconds</li>
</ul>
</emu-note>
<emu-clause id="sec-getavailablenamedtimezoneidentifier" type="abstract operation">
<h1>
GetAvailableNamedTimeZoneIdentifier (
_timeZoneIdentifier_: a named time zone identifier,
): either a Time Zone Identifier Record or ~empty~
</h1>
<dl class="header">
<dt>description</dt>
<dd>
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.
</dd>
</dl>
<emu-alg>
1. For each element _record_ of AvailableNamedTimeZoneIdentifiers(), do
1. If _record_.[[Identifier]] is an ASCII-case-insensitive match for _timeZoneIdentifier_, return _record_.
1. Return ~empty~.
</emu-alg>
<emu-note>
<p>
For any _timeZoneIdentifier_, or any value that is an ASCII-case-insensitive match for it, the result of this operation must remain the same for the lifetime of the surrounding agent.
Specifically, if that result is a Time Zone Identifier Record, its fields must contain the same values.
</p>
<p>Furthermore, time zone identifiers must not dynamically change from primary to non-primary or vice versa during the lifetime of the surrounding agent, meaning that if _timeZoneIdentifier_ is an ASCII-case-insensitive match for the [[PrimaryIdentifier]] field of the result of a previous call to GetAvailableNamedTimeZoneIdentifier, then GetAvailableNamedTimeZoneIdentifier(_timeZoneIdentifier_) must return a record where [[Identifier]] is [[PrimaryIdentifier]].</p>
<p>Due to the complexity of supporting these requirements, it is recommended that the result of AvailableNamedTimeZoneIdentifiers (and therefore GetAvailableNamedTimeZoneIdentifier) remains the same for the lifetime of the surrounding agent.</p>
</emu-note>
</emu-clause>
<emu-clause id="sec-temporal-getisopartsfromepoch" type="abstract operation">
<h1>
GetISOPartsFromEpoch (
_epochNanoseconds_: an integer,
): an ISO Date-Time Record
</h1>
<dl class="header">
<dt>description</dt>
<dd>It returns the components of a date in UTC corresponding to the given number of nanoseconds since the epoch.</dd>
</dl>
<emu-alg>
1. Assert: IsValidEpochNanoseconds(ℤ(_epochNanoseconds_)) is *true*.
1. Let _remainderNs_ be _epochNanoseconds_ modulo 10<sup>6</sup>.
1. Let _epochMilliseconds_ be 𝔽((_epochNanoseconds_ - _remainderNs_) / 10<sup>6</sup>).
1. Let _year_ be EpochTimeToEpochYear(_epochMilliseconds_).
1. Let _month_ be EpochTimeToMonthInYear(_epochMilliseconds_) + 1.
1. Let _day_ be EpochTimeToDate(_epochMilliseconds_).
1. Let _hour_ be ℝ(HourFromTime(_epochMilliseconds_)).
1. Let _minute_ be ℝ(MinFromTime(_epochMilliseconds_)).
1. Let _second_ be ℝ(SecFromTime(_epochMilliseconds_)).
1. Let _millisecond_ be ℝ(msFromTime(_epochMilliseconds_)).
1. Let _microsecond_ be floor(_remainderNs_ / 1000).
1. Assert: _microsecond_ < 1000.
1. Let _nanosecond_ be _remainderNs_ modulo 1000.
1. Let _isoDate_ be CreateISODateRecord(_year_, _month_, _day_).
1. Let _time_ be CreateTimeRecord(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_).
1. Return CombineISODateAndTimeRecord(_isoDate_, _time_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getnamedtimezonenexttransition" type="implementation-defined abstract operation">
<h1>
GetNamedTimeZoneNextTransition (
_timeZoneIdentifier_: an available named time zone identifier,
_epochNanoseconds_: a BigInt,
): either a BigInt or *null*
</h1>
<dl class="header">
</dl>
<p>
The returned value _t_ represents the number of nanoseconds since the epoch 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 _t_ ≤ ℤ(nsMaxInstant).
</p>
<p>
A transition is a point in time where the UTC offset of a time zone changes, for example when Daylight Saving Time starts or stops.
The returned value _t_ represents the first nanosecond where the new UTC offset is used in this time zone, not the last nanosecond where the previous UTC offset is used.
In other words, GetOffsetNanosecondsFor(_timeZone_, _t_) ≠ GetOffsetNanosecondsFor(_timeZone_, _t_ - 1).
</p>
<p>Given the same values of _timeZoneIdentifier_ and _epochNanoseconds_, the result must be the same for the lifetime of the surrounding agent.</p>
<p>The minimum implementation of GetNamedTimeZoneNextTransition for ECMAScript implementations that do not include local political rules for any time zones performs the following steps when called:</p>
<emu-alg>
1. Assert: _timeZoneIdentifier_ is *"UTC"*.
1. Return *null*.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getnamedtimezoneprevioustransition" type="implementation-defined abstract operation">
<h1>
GetNamedTimeZonePreviousTransition (
_timeZoneIdentifier_: an available named time zone identifier,
_epochNanoseconds_: a BigInt,
): either a BigInt or *null*
</h1>
<dl class="header">
</dl>
<p>
The returned value _t_ represents the number of nanoseconds since the epoch 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 _t_ ≥ ℤ(nsMinInstant).
</p>
<p>
A transition is a point in time where the UTC offset of a time zone changes, for example when Daylight Saving Time starts or stops.
The returned value _t_ represents the first nanosecond where the new UTC offset is used in this time zone, not the last nanosecond where the previous UTC offset is used.
In other words, GetOffsetNanosecondsFor(_timeZone_, _t_) ≠ GetOffsetNanosecondsFor(_timeZone_, _t_ - 1).
</p>
<p>Given the same values of _timeZoneIdentifier_ and _epochNanoseconds_, the result must be the same for the lifetime of the surrounding agent.</p>
<p>The minimum implementation of GetNamedTimeZonePreviousTransition for ECMAScript implementations that do not include local political rules for any time zones performs the following steps when called:</p>
<emu-alg>
1. Assert: _timeZoneIdentifier_ is *"UTC"*.
1. Return *null*.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-formatoffsettimezoneidentifier" type="abstract operation">
<h1>
FormatOffsetTimeZoneIdentifier (
_offsetMinutes_: an integer in the inclusive interval from -1439 to 1439,
optional _style_: either ~separated~ or ~unseparated~,
): an offset time zone identifier
</h1>
<dl class="header">
<dt>description</dt>
<dd>
It formats a UTC offset, in minutes, into a UTC offset string.
If _style_ is ~separated~ or not present, then the output will be formatted like ±HH:MM.
If _style_ is ~unseparated~, then the output will be formatted like ±HHMM.
</dd>
</dl>
<emu-alg>
1. If _offsetMinutes_ ≥ 0, let _sign_ be the code unit 0x002B (PLUS SIGN); else let _sign_ be the code unit 0x002D (HYPHEN-MINUS).
1. Let _absoluteMinutes_ be abs(_offsetMinutes_).
1. Let _hour_ be floor(_absoluteMinutes_ / 60).
1. Let _minute_ be _absoluteMinutes_ modulo 60.
1. Let _timeString_ be FormatTimeString(_hour_, _minute_, 0, 0, ~minute~, _style_).
1. Return the string-concatenation of _sign_ and _timeString_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-formatutcoffsetnanoseconds" type="abstract operation">
<h1>
FormatUTCOffsetNanoseconds (
_offsetNanoseconds_: an integer in the interval from -86400 × 10<sup>9</sup> (exclusive) to 86400 × 10<sup>9</sup> (exclusive),
): a String
</h1>
<dl class="header">
<dt>description</dt>
<dd>
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.
</dd>
</dl>
<emu-alg>
1. If _offsetNanoseconds_ ≥ 0, let _sign_ be the code unit 0x002B (PLUS SIGN); else let _sign_ be the code unit 0x002D (HYPHEN-MINUS).
1. Let _absoluteNanoseconds_ be abs(_offsetNanoseconds_).
1. Let _hour_ be floor(_absoluteNanoseconds_ / (3600 × 10<sup>9</sup>)).
1. Let _minute_ be floor(_absoluteNanoseconds_ / (60 × 10<sup>9</sup>)) modulo 60.
1. Let _second_ be floor(_absoluteNanoseconds_ / 10<sup>9</sup>) modulo 60.
1. Let _subSecondNanoseconds_ be _absoluteNanoseconds_ modulo 10<sup>9</sup>.
1. If _second_ = 0 and _subSecondNanoseconds_ = 0, let _precision_ be ~minute~; else let _precision_ be ~auto~.
1. Let _timeString_ be FormatTimeString(_hour_, _minute_, _second_, _subSecondNanoseconds_, _precision_).
1. Return the string-concatenation of _sign_ and _timeString_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-formatdatetimeutcoffsetrounded" type="abstract operation">
<h1>
FormatDateTimeUTCOffsetRounded (
_offsetNanoseconds_: an integer in the interval from -86400 × 10<sup>9</sup> (exclusive) to 86400 × 10<sup>9</sup> (exclusive),
): a String
</h1>
<dl class="header">
<dt>description</dt>
<dd>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.</dd>
</dl>
<emu-alg>
1. Set _offsetNanoseconds_ to RoundNumberToIncrement(_offsetNanoseconds_, 60 × 10<sup>9</sup>, ~half-expand~).
1. Let _offsetMinutes_ be _offsetNanoseconds_ / (60 × 10<sup>9</sup>).
1. Return FormatOffsetTimeZoneIdentifier(_offsetMinutes_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-totemporaltimezoneidentifier" type="abstract operation">
<h1>
ToTemporalTimeZoneIdentifier (
_temporalTimeZoneLike_: an ECMAScript value,
): either a normal completion containing an available time zone identifier or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It attempts to derive a value from _temporalTimeZoneLike_ that is an available time zone identifier, and returns that value if found or throws an exception if not.</dd>
</dl>
<emu-alg>
1. If _temporalTimeZoneLike_ is an Object and _temporalTimeZoneLike_ has an [[InitializedTemporalZonedDateTime]] internal slot, return _temporalTimeZoneLike_.[[TimeZone]].
1. If _temporalTimeZoneLike_ is not a String, throw a *TypeError* exception.
1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_temporalTimeZoneLike_).
1. Let _offsetMinutes_ be _parseResult_.[[OffsetMinutes]].
1. If _offsetMinutes_ is not ~empty~, return FormatOffsetTimeZoneIdentifier(_offsetMinutes_).
1. Let _name_ be _parseResult_.[[Name]].
1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_name_).
1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception.
1. Return _timeZoneIdentifierRecord_.[[Identifier]].
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getoffsetnanosecondsfor" type="abstract operation">
<h1>
GetOffsetNanosecondsFor (
_timeZone_: an available time zone identifier,
_epochNs_: a BigInt,
): an integer in the interval from -86400 × 10<sup>9</sup> (exclusive) to 86400 × 10<sup>9</sup> (exclusive)
</h1>
<dl class="header">
<dt>description</dt>
<dd>
It determines the UTC offset of an exact time _epochNs_, in nanoseconds.
</dd>
</dl>
<emu-alg>
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_timeZone_).
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, return _parseResult_.[[OffsetMinutes]] × (60 × 10<sup>9</sup>).
1. Return GetNamedTimeZoneOffsetNanoseconds(_parseResult_.[[Name]], _epochNs_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getisodatetimefor" type="abstract operation">
<h1>
GetISODateTimeFor (
_timeZone_: an available time zone identifier,
_epochNs_: a BigInt,
): an ISO Date-Time Record
</h1>
<dl class="header">
<dt>description</dt>
<dd>It converts _epochNs_ to a wall-clock date and time in the time zone _timeZone_.</dd>
</dl>
<emu-alg>
1. Let _offsetNanoseconds_ be GetOffsetNanosecondsFor(_timeZone_, _epochNs_).
1. Let _result_ be GetISOPartsFromEpoch(ℝ(_epochNs_)).
1. Return BalanceISODateTime(_result_.[[ISODate]].[[Year]], _result_.[[ISODate]].[[Month]], _result_.[[ISODate]].[[Day]], _result_.[[Time]].[[Hour]], _result_.[[Time]].[[Minute]], _result_.[[Time]].[[Second]], _result_.[[Time]].[[Millisecond]], _result_.[[Time]].[[Microsecond]], _result_.[[Time]].[[Nanosecond]] + _offsetNanoseconds_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getepochnanosecondsfor" type="abstract operation">
<h1>
GetEpochNanosecondsFor (
_timeZone_: an available time zone identifier,
_isoDateTime_: an ISO Date-Time Record,
_disambiguation_: one of ~compatible~, ~earlier~, ~later~, or ~reject~,
): either a normal completion containing a BigInt or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It converts _isoDateTime_ to an epoch nanoseconds value in the time zone _timeZone_, using _disambiguation_ to resolve ambiguity.</dd>
</dl>
<emu-alg>
1. Let _possibleEpochNs_ be ? GetPossibleEpochNanoseconds(_timeZone_, _isoDateTime_).
1. Return ? DisambiguatePossibleEpochNanoseconds(_possibleEpochNs_, _timeZone_, _isoDateTime_, _disambiguation_).
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-disambiguatepossibleepochnanoseconds" type="abstract operation">
<h1>
DisambiguatePossibleEpochNanoseconds (
_possibleEpochNs_: a List of BigInts,
_timeZone_: an available time zone identifier,
_isoDateTime_: an ISO Date-Time Record,
_disambiguation_: one of ~compatible~, ~earlier~, ~later~, or ~reject~,
): either a normal completion containing a BigInt or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It chooses from a List of possible exact times the one indicated by the _disambiguation_ parameter.</dd>
</dl>
<emu-alg>
1. Let _n_ be the number of elements in _possibleEpochNs_.
1. If _n_ = 1, return the sole element of _possibleEpochNs_.
1. If _n_ ≠ 0, then
1. If _disambiguation_ is either ~earlier~ or ~compatible~, return _possibleEpochNs_[0].
1. If _disambiguation_ is ~later~, return _possibleEpochNs_[_n_ - 1].
1. Assert: _disambiguation_ is ~reject~.
1. Throw a *RangeError* exception.
1. Assert: _n_ = 0.
1. If _disambiguation_ is ~reject~, throw a *RangeError* exception.
1. Let _before_ be the latest possible ISO Date-Time Record for which CompareISODateTime(_before_, _isoDateTime_) = -1 and ! GetPossibleEpochNanoseconds(_timeZone_, _before_) is not empty.
1. Let _after_ be the earliest possible ISO Date-Time Record for which CompareISODateTime(_after_, _isoDateTime_) = 1 and ! GetPossibleEpochNanoseconds(_timeZone_, _after_) is not empty.
1. Let _beforePossible_ be ! GetPossibleEpochNanoseconds(_timeZone_, _before_).
1. Assert: The number of elements in _beforePossible_ = 1.
1. Let _afterPossible_ be ! GetPossibleEpochNanoseconds(_timeZone_, _after_).
1. Assert: The number of elements in _afterPossible_ = 1.
1. Let _offsetBefore_ be GetOffsetNanosecondsFor(_timeZone_, the sole element of _beforePossible_).
1. Let _offsetAfter_ be GetOffsetNanosecondsFor(_timeZone_, the sole element of _afterPossible_).
1. Let _nanoseconds_ be _offsetAfter_ - _offsetBefore_.
1. Assert: abs(_nanoseconds_) ≤ nsPerDay.
1. If _disambiguation_ is ~earlier~, then
1. Let _timeDuration_ be TimeDurationFromComponents(0, 0, 0, 0, 0, -_nanoseconds_).
1. Let _earlierTime_ be AddTime(_isoDateTime_.[[Time]], _timeDuration_).
1. Let _earlierDate_ be AddDaysToISODate(_isoDateTime_.[[ISODate]], _earlierTime_.[[Days]]).
1. Let _earlierDateTime_ be CombineISODateAndTimeRecord(_earlierDate_, _earlierTime_).
1. Set _possibleEpochNs_ to ? GetPossibleEpochNanoseconds(_timeZone_, _earlierDateTime_).
1. Assert: _possibleEpochNs_ is not empty.
1. Return _possibleEpochNs_[0].
1. Assert: _disambiguation_ is ~compatible~ or ~later~.
1. Let _timeDuration_ be TimeDurationFromComponents(0, 0, 0, 0, 0, _nanoseconds_).
1. Let _laterTime_ be AddTime(_isoDateTime_.[[Time]], _timeDuration_).
1. Let _laterDate_ be AddDaysToISODate(_isoDateTime_.[[ISODate]], _laterTime_.[[Days]]).
1. Let _laterDateTime_ be CombineISODateAndTimeRecord(_laterDate_, _laterTime_).
1. Set _possibleEpochNs_ to ? GetPossibleEpochNanoseconds(_timeZone_, _laterDateTime_).
1. Set _n_ to the number of elements in _possibleEpochNs_.
1. Assert: _n_ ≠ 0.
1. Return _possibleEpochNs_[_n_ - 1].
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getpossibleepochnanoseconds" type="abstract operation">
<h1>
GetPossibleEpochNanoseconds (
_timeZone_: an available time zone identifier,
_isoDateTime_: an ISO Date-Time Record,
): either a normal completion containing a List of BigInts or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>
It determines the possible exact times that may correspond to _isoDateTime_.
</dd>
</dl>
<emu-alg>
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_timeZone_).
1. 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]]).
1. Perform ? CheckISODaysRange(_balanced_.[[ISODate]]).
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_).
1. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ ».
1. Else,
1. Let _possibleEpochNanoseconds_ be GetNamedTimeZoneEpochNanoseconds(_parseResult_.[[Name]], _isoDateTime_).
1. For each value _epochNanoseconds_ in _possibleEpochNanoseconds_, do
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
1. Return _possibleEpochNanoseconds_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-getstartofday" type="abstract operation">
<h1>
GetStartOfDay (
_timeZone_: an available time zone identifier,
_isoDate_: an ISO Date Record,
): either a normal completion containing a BigInt or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It determines the exact time that corresponds to the first valid wall-clock time in the calendar date _isoDate_ in _timeZone_.</dd>
</dl>
<emu-alg>
1. Let _isoDateTime_ be CombineISODateAndTimeRecord(_isoDate_, MidnightTimeRecord()).
1. Let _possibleEpochNs_ be ? GetPossibleEpochNanoseconds(_timeZone_, _isoDateTime_).
1. If _possibleEpochNs_ is not empty, return _possibleEpochNs_[0].
1. Assert: IsOffsetTimeZoneIdentifier(_timeZone_) is *false*.
1. [declared="isoDateTimeAfter"] Let _possibleEpochNsAfter_ be GetNamedTimeZoneEpochNanoseconds(_timeZone_, _isoDateTimeAfter_), where _isoDateTimeAfter_ is the ISO Date-Time Record for which DifferenceISODateTime(_isoDateTime_, _isoDateTimeAfter_, *"iso8601"*, ~hour~).[[Time]] is the smallest possible value > 0 for which _possibleEpochNsAfter_ is not empty (i.e., _isoDateTimeAfter_ represents the first local time after the transition).
1. Assert: The number of elements in _possibleEpochNsAfter_ = 1.
1. Return the sole element of _possibleEpochNsAfter_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-timezoneequals" type="abstract operation">
<h1>
TimeZoneEquals (
_one_: an available time zone identifier,
_two_: an available time zone identifier,
): a Boolean
</h1>
<dl class="header">
<dt>description</dt>
<dd>It returns *true* if its arguments represent time zones using the same identifier.</dd>
</dl>
<emu-alg>
1. If _one_ is _two_, return *true*.
1. If IsOffsetTimeZoneIdentifier(_one_) is *false* and IsOffsetTimeZoneIdentifier(_two_) is *false*, then
1. Let _recordOne_ be GetAvailableNamedTimeZoneIdentifier(_one_).
1. Let _recordTwo_ be GetAvailableNamedTimeZoneIdentifier(_two_).
1. Assert: _recordOne_ is not ~empty~.
1. Assert: _recordTwo_ is not ~empty~.
1. If _recordOne_.[[PrimaryIdentifier]] is _recordTwo_.[[PrimaryIdentifier]], return *true*.
1. Assert: If _one_ and _two_ are both offset time zone identifiers, they do not represent the same number of offset minutes.
1. Return *false*.
</emu-alg>
</emu-clause>
<emu-clause id="sec-parsetimezoneidentifier" type="abstract operation">
<h1>
ParseTimeZoneIdentifier (
_identifier_: a String,
): either a normal completion containing a Time Zone Identifier Parse Record, or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>
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.
</dd>
</dl>
<emu-alg>
1. Let _parseResult_ be ParseText(StringToCodePoints(_identifier_), |TimeZoneIdentifier|).
1. If _parseResult_ is a List of errors, throw a *RangeError* exception.
1. If _parseResult_ contains a |TimeZoneIANAName| Parse Node, then
1. Let _name_ be the source text matched by the |TimeZoneIANAName| Parse Node contained within _parseResult_.
1. NOTE: _name_ is syntactically valid, but does not necessarily conform to <a href="https://data.iana.org/time-zones/theory.html#naming">IANA Time Zone Database naming guidelines</a> or correspond with an available named time zone identifier.
1. Return Time Zone Identifier Parse Record { [[Name]]: CodePointsToString(_name_), [[OffsetMinutes]]: ~empty~ }.
1. Assert: _parseResult_ contains a |UTCOffset[~SubMinutePrecision]| Parse Node.
1. Let _offset_ be the source text matched by the |UTCOffset[~SubMinutePrecision]| Parse Node contained within _parseResult_.
1. Let _offsetNanoseconds_ be ! ParseDateTimeUTCOffset(CodePointsToString(_offset_)).
1. Let _offsetMinutes_ be _offsetNanoseconds_ / (60 × 10<sup>9</sup>).
1. Return Time Zone Identifier Parse Record { [[Name]]: ~empty~, [[OffsetMinutes]]: _offsetMinutes_ }.
</emu-alg>
</emu-clause>
</emu-clause>
</emu-clause>