Skip to content

Commit f6818ce

Browse files
committed
Normative: Limit offset time zones to minutes
1 parent abf3db8 commit f6818ce

File tree

8 files changed

+46
-44
lines changed

8 files changed

+46
-44
lines changed

polyfill/lib/ecmascript.mjs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,9 @@ const OFFSET_IDENTIFIER = new RegExp(`^${PARSE.offsetIdentifier.source}$`);
558558
export function ParseTimeZoneIdentifier(identifier) {
559559
if (!TIMEZONE_IDENTIFIER.test(identifier)) return undefined;
560560
if (OFFSET_IDENTIFIER.test(identifier)) {
561+
// The regex limits the input to minutes precision
561562
const { offsetNanoseconds } = ParseUTCOffsetString(identifier);
562-
return { offsetNanoseconds };
563+
return { offsetMinutes: offsetNanoseconds / 6e10 };
563564
}
564565
return { tzName: identifier };
565566
}
@@ -2096,16 +2097,19 @@ export function ToTemporalTimeZoneSlotValue(temporalTimeZoneLike) {
20962097
const { tzName, offset, z } = ParseTemporalTimeZoneString(identifier);
20972098
if (tzName) {
20982099
// tzName is any valid identifier string in brackets, and could be an offset identifier
2099-
const { offsetNanoseconds } = ParseTimeZoneIdentifier(tzName);
2100-
if (offsetNanoseconds !== undefined) return FormatTimeZoneOffsetString(offsetNanoseconds);
2100+
const { offsetMinutes } = ParseTimeZoneIdentifier(tzName);
2101+
if (offsetMinutes !== undefined) return FormatTimeZoneOffsetString(offsetMinutes * 6e10);
21012102

21022103
const record = GetAvailableNamedTimeZoneIdentifier(tzName);
21032104
if (!record) throw new RangeError(`Unrecognized time zone ${tzName}`);
21042105
return record.primaryIdentifier;
21052106
}
21062107
if (z) return 'UTC';
21072108
// if !tzName && !z then offset must be present
2108-
const { offsetNanoseconds } = ParseUTCOffsetString(offset);
2109+
const { offsetNanoseconds, hasSubMinutePrecision } = ParseUTCOffsetString(offset);
2110+
if (hasSubMinutePrecision) {
2111+
throw new RangeError(`Seconds not allowed in offset time zone: ${offset}`);
2112+
}
21092113
return FormatTimeZoneOffsetString(offsetNanoseconds);
21102114
}
21112115

polyfill/lib/regex.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const datesplit = new RegExp(
2424
const timesplit = /(\d{2})(?::(\d{2})(?::(\d{2})(?:[.,](\d{1,9}))?)?|(\d{2})(?:(\d{2})(?:[.,](\d{1,9}))?)?)?/;
2525
export const offset = /([+\u2212-])([01][0-9]|2[0-3])(?::?([0-5][0-9])(?::?([0-5][0-9])(?:[.,](\d{1,9}))?)?)?/;
2626
const offsetpart = new RegExp(`([zZ])|${offset.source}?`);
27-
export const offsetIdentifier = offset;
27+
export const offsetIdentifier = /([+\u2212-])([01][0-9]|2[0-3])(?::?([0-5][0-9])?)?/;
2828
export const annotation = /\[(!)?([a-z_][a-z0-9_-]*)=([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\]/g;
2929

3030
export const zoneddatetime = new RegExp(

polyfill/lib/timezone.mjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ export class TimeZone {
2828
}
2929
let stringIdentifier = ES.ToString(identifier);
3030
const parseResult = ES.ParseTimeZoneIdentifier(identifier);
31-
if (parseResult?.offsetNanoseconds !== undefined) {
32-
stringIdentifier = ES.FormatTimeZoneOffsetString(parseResult.offsetNanoseconds);
31+
if (parseResult?.offsetMinutes !== undefined) {
32+
stringIdentifier = ES.FormatTimeZoneOffsetString(parseResult.offsetMinutes * 6e10);
3333
} else {
3434
const record = ES.GetAvailableNamedTimeZoneIdentifier(stringIdentifier);
3535
if (!record) throw new RangeError(`Invalid time zone identifier: ${stringIdentifier}`);
@@ -56,8 +56,8 @@ export class TimeZone {
5656
instant = ES.ToTemporalInstant(instant);
5757
const id = GetSlot(this, TIMEZONE_ID);
5858

59-
const offsetNanoseconds = ES.ParseTimeZoneIdentifier(id)?.offsetNanoseconds;
60-
if (offsetNanoseconds !== undefined) return offsetNanoseconds;
59+
const offsetMinutes = ES.ParseTimeZoneIdentifier(id)?.offsetMinutes;
60+
if (offsetMinutes !== undefined) return offsetMinutes * 6e10;
6161

6262
return ES.GetNamedTimeZoneOffsetNanoseconds(id, GetSlot(instant, EPOCHNANOSECONDS));
6363
}
@@ -85,8 +85,8 @@ export class TimeZone {
8585
const Instant = GetIntrinsic('%Temporal.Instant%');
8686
const id = GetSlot(this, TIMEZONE_ID);
8787

88-
const offsetNanoseconds = ES.ParseTimeZoneIdentifier(id)?.offsetNanoseconds;
89-
if (offsetNanoseconds !== undefined) {
88+
const offsetMinutes = ES.ParseTimeZoneIdentifier(id)?.offsetMinutes;
89+
if (offsetMinutes !== undefined) {
9090
const epochNs = ES.GetUTCEpochNanoseconds(
9191
GetSlot(dateTime, ISO_YEAR),
9292
GetSlot(dateTime, ISO_MONTH),
@@ -99,7 +99,7 @@ export class TimeZone {
9999
GetSlot(dateTime, ISO_NANOSECOND)
100100
);
101101
if (epochNs === null) throw new RangeError('DateTime outside of supported range');
102-
return [new Instant(epochNs.minus(offsetNanoseconds))];
102+
return [new Instant(epochNs.minus(offsetMinutes * 6e10))];
103103
}
104104

105105
const possibleEpochNs = ES.GetNamedTimeZoneEpochNanoseconds(

polyfill/test/validStrings.mjs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,7 @@ const utcOffset = withCode(
262262
saveOffset
263263
);
264264
const timeZoneUTCOffset = choice(utcDesignator, utcOffset);
265-
const timeZoneUTCOffsetName = seq(
266-
sign,
267-
hour,
268-
choice([minuteSecond, [minuteSecond, [fraction]]], seq(':', minuteSecond, [':', minuteSecond, [fraction]]))
269-
);
265+
const timeZoneUTCOffsetName = seq(sign, hour, choice([minuteSecond], seq(':', minuteSecond)));
270266
const timeZoneIANAName = choice(...timezoneNames);
271267
const timeZoneIdentifier = withCode(
272268
choice(timeZoneUTCOffsetName, timeZoneIANAName),

spec/abstractops.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ <h1>ISO 8601 grammar</h1>
11211121
UTCOffsetSubMinutePrecision
11221122

11231123
TimeZoneUTCOffsetName :
1124-
UTCOffsetSubMinutePrecision
1124+
UTCOffsetMinutePrecision
11251125

11261126
TZLeadingChar :
11271127
Alpha

spec/intl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,7 @@ <h1>Temporal.ZonedDateTime.prototype.toLocaleString ( [ _locales_ [ , _options_
25432543
1. Let _dateTimeFormat_ be ! OrdinaryCreateFromConstructor(%DateTimeFormat%, %DateTimeFormat.prototype%, « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[DayPeriod]], [[Hour]], [[Minute]], [[Second]], [[FractionalSecondDigits]], [[TimeZoneName]], [[HourCycle]], [[Pattern]], [[BoundFormat]] »).
25442544
1. Let _timeZone_ be ? ToTemporalTimeZoneIdentifier(_zonedDateTime_.[[TimeZone]]).
25452545
1. Let _timeZoneParseResult_ be ParseTimeZoneIdentifier(_timeZone_).
2546-
1. If _timeZoneParseResult_ is not ~unmatched~ and _timeZoneParseResult_.[[OffsetNanoseconds]] is not ~empty~, throw a *RangeError* exception.
2546+
1. If _timeZoneParseResult_ is not ~unmatched~ and _timeZoneParseResult_.[[OffsetMinutes]] is not ~empty~, throw a *RangeError* exception.
25472547
1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_timeZone_).
25482548
1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception.
25492549
1. Set _timeZone_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifier]].

spec/mainadditions.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ <h1>Time Zone Offset String <del>Format</del><ins>Formats</ins></h1>
311311
<ins class="block">
312312
<p>
313313
ECMAScript defines string interchange formats for UTC offsets, derived from ISO 8601.
314+
UTC offsets that represent offset time zone identifiers, or that are intended for interoperability with ISO 8601, use only hours and minutes and are specified by |UTCOffsetMinutePrecision|.
315+
UTC offsets that represent the offset of a named or custom time zone can be more precise, and are specified by |UTCOffsetSubMinutePrecision|.
314316
</p>
315317
<p>
316318
These formats are described by the ISO String grammar in <emu-xref href="#sec-temporal-iso8601grammar"></emu-xref>.

spec/timezone.html

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ <h1>Temporal.TimeZone ( _identifier_ )</h1>
3434
1. Set _identifier_ to ? ToString(_identifier_).
3535
1. Let _parseResult_ be ParseTimeZoneIdentifier(_identifier_).
3636
1. If _parseResult_ is ~unmatched~, throw a *RangeError* exception.
37-
1. If _parseResult_.[[OffsetNanoseconds]] is not ~empty~, then
38-
1. Set _identifier_ to FormatTimeZoneOffsetString(_parseResult_.[[OffsetNanoseconds]]).
37+
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, then
38+
1. Set _identifier_ to FormatTimeZoneOffsetString(_parseResult_.[[OffsetMinutes]] × (6 × 10<sup>10</sup>)).
3939
1. Else,
4040
1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_identifier_).
4141
1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception.
@@ -102,7 +102,7 @@ <h1>get Temporal.TimeZone.prototype.id</h1>
102102
<emu-alg>
103103
1. Let _timeZone_ be the *this* value.
104104
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
105-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetNanoseconds]]).
105+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetMinutes]] × (6 × 10<sup>10</sup>)).
106106
1. Return _timeZone_.[[Identifier]].
107107
</emu-alg>
108108
</emu-clause>
@@ -116,7 +116,7 @@ <h1>Temporal.TimeZone.prototype.getOffsetNanosecondsFor ( _instant_ )</h1>
116116
1. Let _timeZone_ be the *this* value.
117117
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
118118
1. Set _instant_ to ? ToTemporalInstant(_instant_).
119-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return 𝔽(_timeZone_.[[OffsetNanoseconds]]).
119+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return 𝔽(_timeZone_.[[OffsetMinutes]]).
120120
1. Return 𝔽(GetNamedTimeZoneOffsetNanoseconds(_timeZone_.[[Identifier]], _instant_.[[Nanoseconds]])).
121121
</emu-alg>
122122
</emu-clause>
@@ -172,9 +172,9 @@ <h1>Temporal.TimeZone.prototype.getPossibleInstantsFor ( _dateTime_ )</h1>
172172
1. Let _timeZone_ be the *this* value.
173173
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
174174
1. Set _dateTime_ to ? ToTemporalDateTime(_dateTime_).
175-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, then
175+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, then
176176
1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
177-
1. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ - ℤ(_timeZone_.[[OffsetNanoseconds]]) ».
177+
1. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ - ℤ(_timeZone_.[[OffsetMinutes]] &times; (6 &times; 10<sup>10</sup>)) ».
178178
1. Else,
179179
1. Let _possibleEpochNanoseconds_ be GetNamedTimeZoneEpochNanoseconds(_timeZone_.[[Identifier]], _dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
180180
1. Let _possibleInstants_ be a new empty List.
@@ -195,7 +195,7 @@ <h1>Temporal.TimeZone.prototype.getNextTransition ( _startingPoint_ )</h1>
195195
1. Let _timeZone_ be the *this* value.
196196
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
197197
1. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
198-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return *null*.
198+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return *null*.
199199
1. Let _transition_ be GetNamedTimeZoneNextTransition(_timeZone_.[[Identifier]], _startingPoint_.[[Nanoseconds]]).
200200
1. If _transition_ is *null*, return *null*.
201201
1. Return ! CreateTemporalInstant(_transition_).
@@ -211,7 +211,7 @@ <h1>Temporal.TimeZone.prototype.getPreviousTransition ( _startingPoint_ )</h1>
211211
1. Let _timeZone_ be the *this* value.
212212
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
213213
1. Set _startingPoint_ to ? ToTemporalInstant(_startingPoint_).
214-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return *null*.
214+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return *null*.
215215
1. Let _transition_ be GetNamedTimeZonePreviousTransition(_timeZone_.[[Identifier]], _startingPoint_.[[Nanoseconds]]).
216216
1. If _transition_ is *null*, return *null*.
217217
1. Return ! CreateTemporalInstant(_transition_).
@@ -226,7 +226,7 @@ <h1>Temporal.TimeZone.prototype.toString ( )</h1>
226226
<emu-alg>
227227
1. Let _timeZone_ be the *this* value.
228228
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
229-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetNanoseconds]]).
229+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetMinutes]] × (6 × 10<sup>10</sup>)).
230230
1. Return _timeZone_.[[Identifier]].
231231
</emu-alg>
232232
</emu-clause>
@@ -239,7 +239,7 @@ <h1>Temporal.TimeZone.prototype.toJSON ( )</h1>
239239
<emu-alg>
240240
1. Let _timeZone_ be the *this* value.
241241
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
242-
1. If _timeZone_.[[OffsetNanoseconds]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetNanoseconds]]).
242+
1. If _timeZone_.[[OffsetMinutes]] is not ~empty~, return FormatTimeZoneOffsetString(_timeZone_.[[OffsetMinutes]] × (6 × 10<sup>10</sup>)).
243243
1. Return _timeZone_.[[Identifier]].
244244
</emu-alg>
245245
</emu-clause>
@@ -281,11 +281,11 @@ <h1>Properties of Temporal.TimeZone Instances</h1>
281281
</tr>
282282
<tr>
283283
<td>
284-
[[OffsetNanoseconds]]
284+
[[OffsetMinutes]]
285285
</td>
286286
<td>
287-
An integer for nanoseconds representing the constant offset of this time zone relative to UTC, or ~empty~ if the instance represents a named time zone.
288-
If not ~empty~, this value must be greater than &minus;8.64 &times; 10<sup>13</sup> nanoseconds (&minus;24 hours) and smaller than &plus;8.64 &times; 10<sup>13</sup> nanoseconds (&plus;24 hours).
287+
An integer for minutes representing the constant offset of this time zone relative to UTC, or ~empty~ if the instance represents a named time zone.
288+
If not ~empty~, this value must be greater than &minus;1440 minutes (&minus;24 hours) and smaller than &plus;1440 minutes (&plus;24 hours).
289289
</td>
290290
</tr>
291291
</tbody>
@@ -322,18 +322,18 @@ <h1>
322322
</dl>
323323
<emu-alg>
324324
1. If _newTarget_ is not present, set _newTarget_ to %Temporal.TimeZone%.
325-
1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.TimeZone.prototype%"*, « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetNanoseconds]] »).
325+
1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.TimeZone.prototype%"*, « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetMinutes]] »).
326326
1. Assert: _identifier_ is an available named time zone identifier or an offset time zone identifier.
327327
1. Let _parseResult_ be ParseTimeZoneIdentifier(_identifier_).
328328
1. Assert: _parseResult_ is not ~unmatched~.
329-
1. If _parseResult_.[[OffsetNanoseconds]] is not ~empty~, then
329+
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, then
330330
1. Set _object_.[[Identifier]] to ~empty~.
331-
1. Set _object_.[[OffsetNanoseconds]] to _parseResult_.[[OffsetNanoseconds]].
331+
1. Set _object_.[[OffsetMinutes]] to _parseResult_.[[OffsetMinutes]].
332332
1. Else,
333333
1. Assert: _parseResult_.[[Name]] is not ~empty~.
334334
1. Assert: GetAvailableNamedTimeZoneIdentifier(_identifier_).[[PrimaryIdentifier]] is _identifier_.
335335
1. Set _object_.[[Identifier]] to _identifier_.
336-
1. Set _object_.[[OffsetNanoseconds]] to ~empty~.
336+
1. Set _object_.[[OffsetMinutes]] to ~empty~.
337337
1. Return _object_.
338338
</emu-alg>
339339

@@ -344,7 +344,7 @@ <h1>
344344
Although the [[Identifier]] internal slot is a String in this specification, implementations may choose to store named time zone identifiers it in any other form (for example as an enumeration or index into a List of identifier strings) as long as the String can be regenerated when needed.
345345
</p>
346346
<p>
347-
Similar flexibility exists for the storage of the [[OffsetNanoseconds]] internal slot, which can be interchangeably represented as a 6-byte integer or as a String value that may be as long as 19 characters.
347+
Similar flexibility exists for the storage of the [[OffsetMinutes]] internal slot, which can be interchangeably represented as a 12-bit integer or as a 6-character ±HH:MM string.
348348
ParseTimeZoneIdentifier and FormatTimeZoneOffsetString may be used to losslessly convert one representation to the other.
349349
Implementations are free to store either or both representations.
350350
</p>
@@ -563,8 +563,8 @@ <h1>
563563
1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_identifier_).
564564
1. If _parseResult_.[[Name]] is not *undefined*, then
565565
1. Let _name_ be _parseResult_.[[Name]].
566-
1. Let _offsetNanoseconds_ be ParseTimeZoneIdentifier(_name_).[[OffsetNanoseconds]].
567-
1. If _offsetNanoseconds_ is not ~empty~, return FormatTimeZoneOffsetString(_offsetNanoseconds_).
566+
1. Let _offsetMinutes_ be ParseTimeZoneIdentifier(_name_).[[OffsetMinutes]].
567+
1. If _offsetMinutes_ is not ~empty~, return FormatTimeZoneOffsetString(_offsetMinutes_ × (6 × 10<sup>10</sup>)).
568568
1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_name_).
569569
1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception.
570570
1. Return _timeZoneIdentifierRecord_.[[PrimaryIdentifier]].
@@ -815,13 +815,13 @@ <h1>
815815
<h1>
816816
ParseTimeZoneIdentifier (
817817
_identifier_: a String
818-
): a Record containing [[Name]] and [[OffsetNanoseconds]] fields, or ~unmatched~
818+
): a Record containing [[Name]] and [[OffsetMinutes]] fields, or ~unmatched~
819819
</h1>
820820
<dl class="header">
821821
<dt>description</dt>
822822
<dd>
823-
If _identifier_ is an available named time zone identifier, [[Name]] will be _identifier_ and [[OffsetNanoseconds]] will be ~empty~.
824-
If _identifier_ is an offset time zone identifier, [[Name]] will be ~empty~ and [[OffsetNanoseconds]] will be a signed integer.
823+
If _identifier_ is an available named time zone identifier, [[Name]] will be _identifier_ and [[OffsetMinutes]] will be ~empty~.
824+
If _identifier_ is an offset time zone identifier, [[Name]] will be ~empty~ and [[OffsetMinutes]] will be a signed integer.
825825
Otherwise, ~unmatched~ will be returned.
826826
</dd>
827827
</dl>
@@ -830,13 +830,13 @@ <h1>
830830
1. If _parseResult_ is a List of errors, return ~unmatched~.
831831
1. If _parseResult_ contains a |TimeZoneIANAName| Parse Node, then
832832
1. Let _name_ be the source text matched by the |TimeZoneIANAName| Parse Node contained within _parseResult_.
833-
1. Return the Record { [[Name]]: _name_, [[OffsetNanoseconds]]: ~empty~ }.
833+
1. Return the Record { [[Name]]: _name_, [[OffsetMinutes]]: ~empty~ }.
834834
1. Else,
835835
1. Assert: _parseResult_ contains a |TimeZoneUTCOffsetName| Parse Node.
836836
1. Let _offsetString_ be the source text matched by the |TimeZoneUTCOffsetName| Parse Node contained within _parseResult_.
837837
1. Let _offsetNanoseconds_ be ParseUTCOffsetString(_offsetString_).
838838
1. Assert: _offsetNanoseconds_ modulo 6 &times; 10<sup>10</sup> = 0.
839-
1. Return the Record { [[Name]]: ~empty~, [[OffsetNanoseconds]]: _offsetNanoseconds_ }.
839+
1. Return the Record { [[Name]]: ~empty~, [[OffsetMinutes]]: _offsetNanoseconds_ / (6 &times; 10<sup>10</sup>) }.
840840
</emu-alg>
841841
</emu-clause>
842842
</emu-clause>

0 commit comments

Comments
 (0)