From 1b3d0186dcd202431bd455bf8e76b94e62698c16 Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Wed, 8 Jun 2022 13:33:33 -0400 Subject: [PATCH] Editorial: Simplify operations (#2248) * Replace ToLargestTemporalUnit with a more general GetTemporalUnit * Replace ToSmallestTemporalUnit with GetTemporalUnit * Replace ToTemporalDurationTotalUnit with GetTemporalUnit * Use the units table to support more operations --- polyfill/lib/calendar.mjs | 8 +- polyfill/lib/duration.mjs | 11 ++- polyfill/lib/ecmascript.mjs | 175 ++++++++++++++++++--------------- polyfill/lib/instant.mjs | 4 +- polyfill/lib/plaindatetime.mjs | 3 +- polyfill/lib/plaintime.mjs | 4 +- polyfill/lib/zoneddatetime.mjs | 3 +- spec/abstractops.html | 165 +++++++++++-------------------- spec/calendar.html | 3 +- spec/duration.html | 8 +- spec/instant.html | 10 +- spec/intl.html | 3 +- spec/plaindate.html | 8 +- spec/plaindatetime.html | 10 +- spec/plaintime.html | 10 +- spec/plainyearmonth.html | 10 +- spec/zoneddatetime.html | 10 +- 17 files changed, 204 insertions(+), 241 deletions(-) diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs index 7efcd94e26..d3c286dcc9 100644 --- a/polyfill/lib/calendar.mjs +++ b/polyfill/lib/calendar.mjs @@ -137,12 +137,8 @@ export class Calendar { one = ES.ToTemporalDate(one); two = ES.ToTemporalDate(two); options = ES.GetOptionsObject(options); - const largestUnit = ES.ToLargestTemporalUnit( - options, - 'auto', - ['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond'], - 'day' - ); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'date', 'auto'); + if (largestUnit === 'auto') largestUnit = 'day'; const { years, months, weeks, days } = impl[GetSlot(this, CALENDAR_ID)].dateUntil(one, two, largestUnit); const Duration = GetIntrinsic('%Temporal.Duration%'); return new Duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0); diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs index 8e8ee629f3..27ed34976e 100644 --- a/polyfill/lib/duration.mjs +++ b/polyfill/lib/duration.mjs @@ -230,14 +230,14 @@ export class Duration { } else { roundTo = ES.GetOptionsObject(roundTo); } - let smallestUnit = ES.ToSmallestTemporalUnit(roundTo, undefined); + let smallestUnit = ES.GetTemporalUnit(roundTo, 'smallestUnit', 'datetime', undefined); let smallestUnitPresent = true; if (!smallestUnit) { smallestUnitPresent = false; smallestUnit = 'nanosecond'; } defaultLargestUnit = ES.LargerOfTwoTemporalUnits(defaultLargestUnit, smallestUnit); - let largestUnit = ES.ToLargestTemporalUnit(roundTo, undefined); + let largestUnit = ES.GetTemporalUnit(roundTo, 'largestUnit', 'datetime', undefined, ['auto']); let largestUnitPresent = true; if (!largestUnit) { largestUnitPresent = false; @@ -247,7 +247,9 @@ export class Duration { if (!smallestUnitPresent && !largestUnitPresent) { throw new RangeError('at least one of smallestUnit or largestUnit is required'); } - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } const roundingMode = ES.ToTemporalRoundingMode(roundTo, 'halfExpand'); const roundingIncrement = ES.ToTemporalDateTimeRoundingIncrement(roundTo, smallestUnit); let relativeTo = ES.ToRelativeTemporalObject(roundTo); @@ -333,8 +335,7 @@ export class Duration { } else { totalOf = ES.GetOptionsObject(totalOf); } - const unit = ES.ToTemporalDurationTotalUnit(totalOf, undefined); - if (unit === undefined) throw new RangeError('unit option is required'); + const unit = ES.GetTemporalUnit(totalOf, 'unit', 'datetime', ES.REQUIRED); const relativeTo = ES.ToRelativeTemporalObject(totalOf); // Convert larger units down to days diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index e0617de269..ae1a3c35f0 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -155,30 +155,22 @@ const BUILTIN_CASTS = new Map([ ['offset', ToString] ]); -const ALLOWED_UNITS = [ - 'year', - 'month', - 'week', - 'day', - 'hour', - 'minute', - 'second', - 'millisecond', - 'microsecond', - 'nanosecond' -]; +// each item is [plural, singular, category] const SINGULAR_PLURAL_UNITS = [ - ['years', 'year'], - ['months', 'month'], - ['weeks', 'week'], - ['days', 'day'], - ['hours', 'hour'], - ['minutes', 'minute'], - ['seconds', 'second'], - ['milliseconds', 'millisecond'], - ['microseconds', 'microsecond'], - ['nanoseconds', 'nanosecond'] + ['years', 'year', 'date'], + ['months', 'month', 'date'], + ['weeks', 'week', 'date'], + ['days', 'day', 'date'], + ['hours', 'hour', 'time'], + ['minutes', 'minute', 'time'], + ['seconds', 'second', 'time'], + ['milliseconds', 'millisecond', 'time'], + ['microseconds', 'microsecond', 'time'], + ['nanoseconds', 'nanosecond', 'time'] ]; +const SINGULAR_FOR = new Map(SINGULAR_PLURAL_UNITS); +const PLURAL_FOR = new Map(SINGULAR_PLURAL_UNITS.map(([p, s]) => [s, p])); +const UNITS_DESCENDING = SINGULAR_PLURAL_UNITS.map(([, s]) => s); import * as PARSE from './regex.mjs'; @@ -691,7 +683,14 @@ export const ES = ObjectAssign({}, ES2020, { return ES.ToTemporalRoundingIncrement(options, maximumIncrements[smallestUnit], false); }, ToSecondsStringPrecision: (options) => { - let smallestUnit = ES.ToSmallestTemporalUnit(options, undefined, ['year', 'month', 'week', 'day', 'hour']); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'time', undefined); + if (smallestUnit === 'hour') { + const ALLOWED_UNITS = SINGULAR_PLURAL_UNITS.reduce((allowed, [p, s, c]) => { + if (c === 'time' && s !== 'hour') allowed.push(s, p); + return allowed; + }, []); + throw new RangeError(`smallestUnit must be one of ${ALLOWED_UNITS.join(', ')}, not ${smallestUnit}`); + } switch (smallestUnit) { case 'minute': return { precision: 'minute', unit: 'minute', increment: 1 }; @@ -733,37 +732,33 @@ export const ES = ObjectAssign({}, ES2020, { return { precision, unit: 'nanosecond', increment: 10 ** (9 - precision) }; } }, - ToLargestTemporalUnit: (options, fallback, disallowedStrings = [], autoValue) => { - const singular = new Map(SINGULAR_PLURAL_UNITS.filter(([, sing]) => !disallowedStrings.includes(sing))); - const allowed = new Set(ALLOWED_UNITS); - for (const s of disallowedStrings) { - allowed.delete(s); + REQUIRED: Symbol('~required~'), + GetTemporalUnit: (options, key, unitGroup, requiredOrDefault, extraValues = []) => { + const allowedSingular = []; + for (const [, singular, category] of SINGULAR_PLURAL_UNITS) { + if (unitGroup === 'datetime' || unitGroup === category) { + allowedSingular.push(singular); + } + } + allowedSingular.push(...extraValues); + let defaultVal = requiredOrDefault; + if (defaultVal === ES.REQUIRED) { + defaultVal = undefined; + } else if (defaultVal !== undefined) { + allowedSingular.push(defaultVal); + } + const allowedValues = [...allowedSingular]; + for (const singular of allowedSingular) { + const plural = PLURAL_FOR.get(singular); + if (plural !== undefined) allowedValues.push(plural); + } + let retval = ES.GetOption(options, key, allowedValues, defaultVal); + if (retval === undefined && requiredOrDefault === ES.REQUIRED) { + throw new RangeError(`${key} is required`); } - const retval = ES.GetOption(options, 'largestUnit', ['auto', ...allowed, ...singular.keys()], fallback); - if (retval === 'auto' && autoValue !== undefined) return autoValue; - if (singular.has(retval)) return singular.get(retval); + if (SINGULAR_FOR.has(retval)) retval = SINGULAR_FOR.get(retval); return retval; }, - ToSmallestTemporalUnit: (options, fallback, disallowedStrings = []) => { - const singular = new Map(SINGULAR_PLURAL_UNITS.filter(([, sing]) => !disallowedStrings.includes(sing))); - const allowed = new Set(ALLOWED_UNITS); - for (const s of disallowedStrings) { - allowed.delete(s); - } - const value = ES.GetOption(options, 'smallestUnit', [...allowed, ...singular.keys()], fallback); - if (singular.has(value)) return singular.get(value); - return value; - }, - ToTemporalDurationTotalUnit: (options) => { - // This AO is identical to ToSmallestTemporalUnit, except: - // - default is always `undefined` (caller will throw if omitted) - // - option is named `unit` (not `smallestUnit`) - // - all units are valid (no `disallowedStrings`) - const singular = new Map(SINGULAR_PLURAL_UNITS); - const value = ES.GetOption(options, 'unit', [...singular.values(), ...singular.keys()], undefined); - if (singular.has(value)) return singular.get(value); - return value; - }, ToRelativeTemporalObject: (options) => { const relativeTo = options.relativeTo; if (relativeTo === undefined) return relativeTo; @@ -834,11 +829,6 @@ export const ES = ObjectAssign({}, ES2020, { } return ES.CreateTemporalDate(year, month, day, calendar); }, - ValidateTemporalUnitRange: (largestUnit, smallestUnit) => { - if (ALLOWED_UNITS.indexOf(largestUnit) > ALLOWED_UNITS.indexOf(smallestUnit)) { - throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); - } - }, DefaultTemporalLargestUnit: ( years, months, @@ -851,7 +841,6 @@ export const ES = ObjectAssign({}, ES2020, { microseconds, nanoseconds ) => { - const singular = new Map(SINGULAR_PLURAL_UNITS); for (const [prop, v] of ObjectEntries({ years, months, @@ -864,12 +853,12 @@ export const ES = ObjectAssign({}, ES2020, { microseconds, nanoseconds })) { - if (v !== 0) return singular.get(prop); + if (v !== 0) return SINGULAR_FOR.get(prop); } return 'nanosecond'; }, LargerOfTwoTemporalUnits: (unit1, unit2) => { - if (ALLOWED_UNITS.indexOf(unit1) > ALLOWED_UNITS.indexOf(unit2)) return unit2; + if (UNITS_DESCENDING.indexOf(unit1) > UNITS_DESCENDING.indexOf(unit2)) return unit2; return unit1; }, MergeLargestUnitOption: (options, largestUnit) => { @@ -3309,11 +3298,13 @@ export const ES = ObjectAssign({}, ES2020, { [first, second] = [other, instant]; } options = ES.GetOptionsObject(options); - const DISALLOWED_UNITS = ['year', 'month', 'week', 'day']; - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'nanosecond', DISALLOWED_UNITS); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'time', 'nanosecond'); const defaultLargestUnit = ES.LargerOfTwoTemporalUnits('second', smallestUnit); - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', DISALLOWED_UNITS, defaultLargestUnit); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'time', 'auto'); + if (largestUnit === 'auto') largestUnit = defaultLargestUnit; + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } const roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); const MAX_DIFFERENCE_INCREMENTS = { hour: 24, @@ -3359,11 +3350,13 @@ export const ES = ObjectAssign({}, ES2020, { } options = ES.GetOptionsObject(options); - const DISALLOWED_UNITS = ['hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond']; - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'day', DISALLOWED_UNITS); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'date', 'day'); const defaultLargestUnit = ES.LargerOfTwoTemporalUnits('day', smallestUnit); - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', DISALLOWED_UNITS, defaultLargestUnit); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'date', 'auto'); + if (largestUnit === 'auto') largestUnit = defaultLargestUnit; + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } let roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); if (operation === 'since') roundingMode = ES.NegateTemporalRoundingMode(roundingMode); const roundingIncrement = ES.ToTemporalRoundingIncrement(options, undefined, false); @@ -3404,10 +3397,13 @@ export const ES = ObjectAssign({}, ES2020, { throw new RangeError(`cannot compute difference between dates of ${calendarId} and ${otherCalendarId} calendars`); } options = ES.GetOptionsObject(options); - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'nanosecond'); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'datetime', 'nanosecond'); const defaultLargestUnit = ES.LargerOfTwoTemporalUnits('day', smallestUnit); - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', [], defaultLargestUnit); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'datetime', 'auto'); + if (largestUnit === 'auto') largestUnit = defaultLargestUnit; + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } let roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); if (operation === 'since') roundingMode = ES.NegateTemporalRoundingMode(roundingMode); const roundingIncrement = ES.ToTemporalDateTimeRoundingIncrement(options, smallestUnit); @@ -3484,10 +3480,12 @@ export const ES = ObjectAssign({}, ES2020, { const sign = operation === 'since' ? -1 : 1; other = ES.ToTemporalTime(other); options = ES.GetOptionsObject(options); - const DISALLOWED_UNITS = ['year', 'month', 'week', 'day']; - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', DISALLOWED_UNITS, 'hour'); - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'nanosecond', DISALLOWED_UNITS); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'time', 'auto'); + if (largestUnit === 'auto') largestUnit = 'hour'; + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'time', 'nanosecond'); + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } let roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); if (operation === 'since') roundingMode = ES.NegateTemporalRoundingMode(roundingMode); const MAX_INCREMENTS = { @@ -3565,10 +3563,22 @@ export const ES = ObjectAssign({}, ES2020, { ); } options = ES.GetOptionsObject(options); - const DISALLOWED_UNITS = ['week', 'day', 'hour', 'minute', 'second', 'millisecond', 'microsecond', 'nanosecond']; - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'month', DISALLOWED_UNITS); - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', DISALLOWED_UNITS, 'year'); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + const ALLOWED_UNITS = SINGULAR_PLURAL_UNITS.reduce((allowed, [p, s, c]) => { + if (c === 'date' && s !== 'week' && s !== 'day') allowed.push(s, p); + return allowed; + }, []); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'date', 'month'); + if (smallestUnit === 'week' || smallestUnit === 'day') { + throw new RangeError(`smallestUnit must be one of ${ALLOWED_UNITS.join(', ')}, not ${smallestUnit}`); + } + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'date', 'auto'); + if (largestUnit === 'week' || largestUnit === 'day') { + throw new RangeError(`largestUnit must be one of ${ALLOWED_UNITS.join(', ')}, not ${largestUnit}`); + } + if (largestUnit === 'auto') largestUnit = 'year'; + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } let roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); if (operation === 'since') roundingMode = ES.NegateTemporalRoundingMode(roundingMode); const roundingIncrement = ES.ToTemporalRoundingIncrement(options, undefined, false); @@ -3615,10 +3625,13 @@ export const ES = ObjectAssign({}, ES2020, { throw new RangeError(`cannot compute difference between dates of ${calendarId} and ${otherCalendarId} calendars`); } options = ES.GetOptionsObject(options); - const smallestUnit = ES.ToSmallestTemporalUnit(options, 'nanosecond'); + const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'datetime', 'nanosecond'); const defaultLargestUnit = ES.LargerOfTwoTemporalUnits('hour', smallestUnit); - const largestUnit = ES.ToLargestTemporalUnit(options, 'auto', [], defaultLargestUnit); - ES.ValidateTemporalUnitRange(largestUnit, smallestUnit); + let largestUnit = ES.GetTemporalUnit(options, 'largestUnit', 'datetime', 'auto'); + if (largestUnit === 'auto') largestUnit = defaultLargestUnit; + if (ES.LargerOfTwoTemporalUnits(largestUnit, smallestUnit) !== largestUnit) { + throw new RangeError(`largestUnit ${largestUnit} cannot be smaller than smallestUnit ${smallestUnit}`); + } let roundingMode = ES.ToTemporalRoundingMode(options, 'trunc'); if (operation === 'since') roundingMode = ES.NegateTemporalRoundingMode(roundingMode); const roundingIncrement = ES.ToTemporalDateTimeRoundingIncrement(options, smallestUnit); diff --git a/polyfill/lib/instant.mjs b/polyfill/lib/instant.mjs index 7bc639e6ac..8c60024e1f 100644 --- a/polyfill/lib/instant.mjs +++ b/polyfill/lib/instant.mjs @@ -79,9 +79,7 @@ export class Instant { } else { roundTo = ES.GetOptionsObject(roundTo); } - const DISALLOWED_UNITS = ['year', 'month', 'week', 'day']; - const smallestUnit = ES.ToSmallestTemporalUnit(roundTo, undefined, DISALLOWED_UNITS); - if (smallestUnit === undefined) throw new RangeError('smallestUnit is required'); + const smallestUnit = ES.GetTemporalUnit(roundTo, 'smallestUnit', 'time', ES.REQUIRED); const roundingMode = ES.ToTemporalRoundingMode(roundTo, 'halfExpand'); const maximumIncrements = { hour: 24, diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs index e05aa76aab..02de13d7c2 100644 --- a/polyfill/lib/plaindatetime.mjs +++ b/polyfill/lib/plaindatetime.mjs @@ -295,8 +295,7 @@ export class PlainDateTime { } else { roundTo = ES.GetOptionsObject(roundTo); } - const smallestUnit = ES.ToSmallestTemporalUnit(roundTo, undefined, ['year', 'month', 'week']); - if (smallestUnit === undefined) throw new RangeError('smallestUnit is required'); + const smallestUnit = ES.GetTemporalUnit(roundTo, 'smallestUnit', 'time', ES.REQUIRED, ['day']); const roundingMode = ES.ToTemporalRoundingMode(roundTo, 'halfExpand'); const maximumIncrements = { day: 1, diff --git a/polyfill/lib/plaintime.mjs b/polyfill/lib/plaintime.mjs index 9d0f102610..f5d95efaad 100644 --- a/polyfill/lib/plaintime.mjs +++ b/polyfill/lib/plaintime.mjs @@ -171,9 +171,7 @@ export class PlainTime { } else { roundTo = ES.GetOptionsObject(roundTo); } - const DISALLOWED_UNITS = ['year', 'month', 'week', 'day']; - const smallestUnit = ES.ToSmallestTemporalUnit(roundTo, undefined, DISALLOWED_UNITS); - if (smallestUnit === undefined) throw new RangeError('smallestUnit is required'); + const smallestUnit = ES.GetTemporalUnit(roundTo, 'smallestUnit', 'time', ES.REQUIRED); const roundingMode = ES.ToTemporalRoundingMode(roundTo, 'halfExpand'); const MAX_INCREMENTS = { hour: 24, diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs index 91d7020c49..3a010fb9df 100644 --- a/polyfill/lib/zoneddatetime.mjs +++ b/polyfill/lib/zoneddatetime.mjs @@ -350,8 +350,7 @@ export class ZonedDateTime { } else { roundTo = ES.GetOptionsObject(roundTo); } - const smallestUnit = ES.ToSmallestTemporalUnit(roundTo, undefined, ['year', 'month', 'week']); - if (smallestUnit === undefined) throw new RangeError('smallestUnit is required'); + const smallestUnit = ES.GetTemporalUnit(roundTo, 'smallestUnit', 'time', ES.REQUIRED, ['day']); const roundingMode = ES.ToTemporalRoundingMode(roundTo, 'halfExpand'); const maximumIncrements = { day: 1, diff --git a/spec/abstractops.html b/spec/abstractops.html index e9b4d810f5..f05c5e7039 100644 --- a/spec/abstractops.html +++ b/spec/abstractops.html @@ -256,7 +256,8 @@

ToSecondsStringPrecision ( _normalizedOptions_ )

The precision may be an integer 0 through 9 signifying a number of digits after the decimal point in the seconds, the string *"minute"* signifying not to print seconds at all, or the string *"auto"* signifying to drop trailing zeroes after the decimal point.

- 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_normalizedOptions_, « *"year"*, *"month"*, *"week"*, *"day"*, *"hour"* », *undefined*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_normalizedOptions_, *"smallestUnit"*, ~time~, *undefined*). + 1. If _smallestUnit_ is *"hour"*, throw a *RangeError* exception. 1. If _smallestUnit_ is *"minute"*, then 1. Return the Record { [[Precision]]: *"minute"*, @@ -322,135 +323,118 @@

ToSecondsStringPrecision ( _normalizedOptions_ )

- -

ToLargestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_ [ , _autoValue_ ] )

-

- The abstract operation ToLargestTemporalUnit consults the `largestUnit` property of the Object _normalizedOptions_, and checks that it is a valid unit and not one of a List of _disallowedUnits_. - It returns a _fallback_ value if the property is not present. - Optionally, if an _autoValue_ is provided, then a value of *"auto"* is replaced with this value. -

-

- Both singular and plural unit names are accepted, but only the singular form is returned. -

- - 1. Assert: _disallowedUnits_ does not contain _fallback_. - 1. Assert: _disallowedUnits_ does not contain *"auto"*. - 1. Assert: _autoValue_ is not present or _fallback_ is *"auto"*. - 1. Assert: _autoValue_ is not present or _disallowedUnits_ does not contain _autoValue_. - 1. Let _largestUnit_ be ? GetOption(_normalizedOptions_, *"largestUnit"*, « String », « *"auto"*, *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_). - 1. If _largestUnit_ is *"auto"* and _autoValue_ is present, then - 1. Return _autoValue_. - 1. If _largestUnit_ is in the Plural column of , then - 1. Set _largestUnit_ to the corresponding Singular value of the same row. - 1. If _disallowedUnits_ contains _largestUnit_, then - 1. Throw a *RangeError* exception. - 1. Return _largestUnit_. - -
- - -

ToSmallestTemporalUnit ( _normalizedOptions_, _disallowedUnits_, _fallback_ )

-

- The abstract operation ToSmallestTemporalUnit consults the `smallestUnit` property of the Object _normalizedOptions_, and checks that it is a valid unit and not one of a List of _disallowedUnits_. - It returns a _fallback_ value if the property is not present. -

-

- Both singular and plural unit names are accepted, but only the singular form is returned. -

- - 1. Assert: _disallowedUnits_ does not contain _fallback_. - 1. Let _smallestUnit_ be ? GetOption(_normalizedOptions_, *"smallestUnit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », _fallback_). - 1. If _smallestUnit_ is in the Plural column of , then - 1. Set _smallestUnit_ to the corresponding Singular value of the same row. - 1. If _disallowedUnits_ contains _smallestUnit_, then - 1. Throw a *RangeError* exception. - 1. Return _smallestUnit_. - -
- - -

ToTemporalDurationTotalUnit ( _normalizedOptions_ )

-

- The abstract operation ToTemporalDurationTotalUnit consults the `unit` property of the Object _normalizedOptions_, and checks that it is a valid unit. - It throws if the property is not present. -

+ +

+ GetTemporalUnit ( + _normalizedOptions_: an Object, + _key_: a property key, + _unitGroup_: ~date~, ~time~, or ~datetime~, + _default_: ~required~ or an ECMAScript language value, + optional _extraValues_: a List of ECMAScript language values, + ): either a normal completion containing an ECMAScript language value, or an abrupt completion +

+
+
description
+
It attempts to read from the specified property of _normalizedOptions_ a Temporal unit that is covered by the union of _unitGroup_ and _extraValues_, substituting _default_ if the property value is *undefined*.
+

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

- 1. Let _unit_ be ? GetOption(_normalizedOptions_, *"unit"*, « String », « *"year"*, *"years"*, *"month"*, *"months"*, *"week"*, *"weeks"*, *"day"*, *"days"*, *"hour"*, *"hours"*, *"minute"*, *"minutes"*, *"second"*, *"seconds"*, *"millisecond"*, *"milliseconds"*, *"microsecond"*, *"microseconds"*, *"nanosecond"*, *"nanoseconds"* », *undefined*). - 1. If _unit_ is *undefined*, then - 1. Throw a *RangeError* exception. - 1. If _unit_ is in the Plural column of , then - 1. Set _unit_ to the corresponding Singular value of the same row. - 1. Return _unit_. + 1. Let _singularNames_ be a new empty List. + 1. For each row of , except the header row, in table order, do + 1. Let _unit_ be the value in the Singular column of the row. + 1. If the Category column of the row is ~date~ and _unitGroup_ is ~date~ or ~datetime~, append _unit_ to _singularNames_. + 1. Else if the Category column of the row is ~time~ and _unitGroup_ is ~time~ or ~datetime~, append _unit_ to _singularNames_. + 1. If _extraValues_ is present, then + 1. Set _singularNames_ to the list-concatenation of _singularNames_ and _extraValues_. + 1. If _default_ is ~required~, then + 1. Let _defaultValue_ be *undefined*. + 1. Else, + 1. Let _defaultValue_ be _default_. + 1. If _defaultValue_ is not *undefined* and _singularNames_ does not contain _defaultValue_, then + 1. Append _defaultValue_ to _singularNames_. + 1. Let _allowedValues_ be a copy of _singularNames_. + 1. For each element _singularName_ of _singularNames_, do + 1. If _singularName_ is listed in the Singular column of , then + 1. Let _pluralName_ be the value in the Plural column of the corresponding row. + 1. Append _pluralName_ to _allowedValues_. + 1. NOTE: For each singular Temporal unit name that is contained within _allowedValues_, the corresponding plural name is also contained within it. + 1. Let _value_ be ? GetOption(_normalizedOptions_, _key_, « String », _allowedValues_, _defaultValue_). + 1. If _value_ is *undefined* and _default_ is ~required~, throw a *RangeError* exception. + 1. If _value_ is listed in the Plural column of , then + 1. Set _value_ to the value in the Singular column of the corresponding row. + 1. Return _value_. -
- - -

Singular and plural units

-

- Where possible, the `smallestUnit`, `largestUnit`, and `unit` options accept both singular and plural forms. - Only the singular form is used internally. -

- - Singular and plural units + + Temporal units by descending magnitude + + + + + + + + + + +
Singular PluralCategory
*"year"* *"years"*~date~
*"month"* *"months"*~date~
*"week"* *"weeks"*~date~
*"day"* *"days"*~date~
*"hour"* *"hours"*~time~
*"minute"* *"minutes"*~time~
*"second"* *"seconds"*~time~
*"millisecond"* *"milliseconds"*~time~
*"microsecond"* *"microseconds"*~time~
*"nanosecond"* *"nanoseconds"*~time~
@@ -519,46 +503,17 @@

ToRelativeTemporalObject ( _options_ )

- -

ValidateTemporalUnitRange ( _largestUnit_, _smallestUnit_ )

- - 1. If _smallestUnit_ is *"year"* and _largestUnit_ is not *"year"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"month"* and _largestUnit_ is not *"year"* or *"month"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"week"* and _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"day"* and _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"hour"* and _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, *"day"*, or *"hour"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"minute"* and _largestUnit_ is *"second"*, *"millisecond"*, *"microsecond"*, or *"nanosecond"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"second"* and _largestUnit_ is *"millisecond"*, *"microsecond"*, or *"nanosecond"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"millisecond"* and _largestUnit_ is *"microsecond"* or *"nanosecond"*, then - 1. Throw a *RangeError* exception. - 1. If _smallestUnit_ is *"microsecond"* and _largestUnit_ is *"nanosecond"*, then - 1. Throw a *RangeError* exception. - -
-

LargerOfTwoTemporalUnits ( _u1_, _u2_ )

- The abstract operation LargerOfTwoTemporalUnits, given two strings representing units of time, returns the string representing the larger of the two units. + The abstract operation LargerOfTwoTemporalUnits, given two strings representing Temporal units, returns the string representing the larger of the two units.

- 1. If either _u1_ or _u2_ is *"year"*, return *"year"*. - 1. If either _u1_ or _u2_ is *"month"*, return *"month"*. - 1. If either _u1_ or _u2_ is *"week"*, return *"week"*. - 1. If either _u1_ or _u2_ is *"day"*, return *"day"*. - 1. If either _u1_ or _u2_ is *"hour"*, return *"hour"*. - 1. If either _u1_ or _u2_ is *"minute"*, return *"minute"*. - 1. If either _u1_ or _u2_ is *"second"*, return *"second"*. - 1. If either _u1_ or _u2_ is *"millisecond"*, return *"millisecond"*. - 1. If either _u1_ or _u2_ is *"microsecond"*, return *"microsecond"*. - 1. Return *"nanosecond"*. + 1. Assert: Both _u1_ and _u2_ are listed in the Singular column of . + 1. For each row of , except the header row, in table order, do + 1. Let _unit_ be the value in the Singular column of the row. + 1. If SameValue(_u1_, _unit_) is *true*, return _unit_. + 1. If SameValue(_u2_, _unit_) is *true*, return _unit_.
diff --git a/spec/calendar.html b/spec/calendar.html index 36c2b17099..dcaaf872be 100644 --- a/spec/calendar.html +++ b/spec/calendar.html @@ -847,7 +847,8 @@

Temporal.Calendar.prototype.dateUntil ( _one_, _two_ [ , _options_ ] )

1. Set _one_ to ? ToTemporalDate(_one_). 1. Set _two_ to ? ToTemporalDate(_two_). 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* », *"auto"*, *"day"*). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~date~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to *"day"*. 1. Let _result_ be DifferenceISODate(_one_.[[ISOYear]], _one_.[[ISOMonth]], _one_.[[ISODay]], _two_.[[ISOYear]], _two_.[[ISOMonth]], _two_.[[ISODay]], _largestUnit_). 1. Return ! CreateTemporalDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], 0, 0, 0, 0, 0, 0). diff --git a/spec/duration.html b/spec/duration.html index e259935a3e..a955979d3b 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -413,13 +413,13 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. Set _roundTo_ to ? GetOptionsObject(_roundTo_). 1. Let _smallestUnitPresent_ be *true*. 1. Let _largestUnitPresent_ be *true*. - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_roundTo_, « », *undefined*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_roundTo_, *"smallestUnit"*, ~datetime~, *undefined*). 1. If _smallestUnit_ is *undefined*, then 1. Set _smallestUnitPresent_ to *false*. 1. Set _smallestUnit_ to *"nanosecond"*. 1. Let _defaultLargestUnit_ be ! DefaultTemporalLargestUnit(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]]). 1. Set _defaultLargestUnit_ to ! LargerOfTwoTemporalUnits(_defaultLargestUnit_, _smallestUnit_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_roundTo_, « », *undefined*). + 1. Let _largestUnit_ be ? GetTemporalUnit(_roundTo_, *"largestUnit"*, ~datetime~, *undefined*, « *"auto"* »). 1. If _largestUnit_ is *undefined*, then 1. Set _largestUnitPresent_ to *false*. 1. Set _largestUnit_ to _defaultLargestUnit_. @@ -427,7 +427,7 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. Set _largestUnit_ to _defaultLargestUnit_. 1. If _smallestUnitPresent_ is *false* and _largestUnitPresent_ is *false*, then 1. Throw a *RangeError* exception. - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_roundTo_, *"halfExpand"*). 1. Let _maximum_ be ! MaximumTemporalDurationRoundingIncrement(_smallestUnit_). 1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_roundTo_, _maximum_, *false*). @@ -459,7 +459,7 @@

Temporal.Duration.prototype.total ( _totalOf_ )

1. Else, 1. Set _totalOf_ to ? GetOptionsObject(_totalOf_). 1. Let _relativeTo_ be ? ToRelativeTemporalObject(_totalOf_). - 1. Let _unit_ be ? ToTemporalDurationTotalUnit(_totalOf_). + 1. Let _unit_ be ? GetTemporalUnit(_totalOf_, *"unit"*, ~datetime~, ~required~). 1. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _relativeTo_). 1. Let _intermediate_ be *undefined*. 1. If _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then diff --git a/spec/instant.html b/spec/instant.html index ca2ec71ed3..82e237823c 100644 --- a/spec/instant.html +++ b/spec/instant.html @@ -286,8 +286,7 @@

Temporal.Instant.prototype.round ( _roundTo_ )

1. Perform ! CreateDataPropertyOrThrow(_roundTo_, *"smallestUnit"*, _paramString_). 1. Else, 1. Set _roundTo_ to ? GetOptionsObject(_roundTo_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_roundTo_, « *"year"*, *"month"*, *"week"*, *"day"* », *undefined*). - 1. If _smallestUnit_ is *undefined*, throw a *RangeError* exception. + 1. Let _smallestUnit_ be ? GetTemporalUnit(_roundTo_, *"smallestUnit"*, ~time~, ~required~). 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_roundTo_, *"halfExpand"*). 1. If _smallestUnit_ is *"hour"*, then 1. Let _maximum_ be HoursPerDay. @@ -655,10 +654,11 @@

1. If _operation_ is ~since~, let _sign_ be -1. Otherwise, let _sign_ be 1. 1. Set _other_ to ? ToTemporalInstant(_other_). 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"nanosecond"*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~time~, *"nanosecond"*). 1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"second"*, _smallestUnit_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"auto"*, _defaultLargestUnit_). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~time~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to _defaultLargestUnit_. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_). diff --git a/spec/intl.html b/spec/intl.html index f807eea935..ccbe732363 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -1726,7 +1726,8 @@

Temporal.Calendar.prototype.dateUntil ( _one_, _two_ [ , _options_ ] )

1. Set _one_ to ? ToTemporalDate(_one_). 1. Set _two_ to ? ToTemporalDate(_two_). 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* », *"auto"*, *"day"*). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~date~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to *"day"*. 1. If _calendar_.[[Identifier]] is *"iso8601"*, then 1. Let _result_ be DifferenceISODate(_one_.[[ISOYear]], _one_.[[ISOMonth]], _one_.[[ISODay]], _two_.[[ISOYear]], _two_.[[ISOMonth]], _two_.[[ISODay]], _largestUnit_). 1. Else, diff --git a/spec/plaindate.html b/spec/plaindate.html index 188f696585..05e7d90efe 100644 --- a/spec/plaindate.html +++ b/spec/plaindate.html @@ -944,11 +944,11 @@

1. Set _other_ to ? ToTemporalDate(_other_). 1. If ? CalendarEquals(_temporalDate_.[[Calendar]], _other_.[[Calendar]]) is *false*, throw a *RangeError* exception. 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _disallowedUnits_ be « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* ». - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, _disallowedUnits_, *"day"*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~date~, *"day"*). 1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _smallestUnit_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _disallowedUnits_, *"auto"*, _defaultLargestUnit_). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~date~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to _defaultLargestUnit_. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_). diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html index 5a06ead181..ed3e6139b6 100644 --- a/spec/plaindatetime.html +++ b/spec/plaindatetime.html @@ -512,8 +512,7 @@

Temporal.PlainDateTime.prototype.round ( _roundTo_ )

1. Perform ! CreateDataPropertyOrThrow(_roundTo_, *"smallestUnit"*, _paramString_). 1. Else, 1. Set _roundTo_ to ? GetOptionsObject(_roundTo_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_roundTo_, « *"year"*, *"month"*, *"week"* », *undefined*). - 1. If _smallestUnit_ is *undefined*, throw a *RangeError* exception. + 1. Let _smallestUnit_ be ? GetTemporalUnit(_roundTo_, *"smallestUnit"*, ~time~, ~required~, « *"day"* »). 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_roundTo_, *"halfExpand"*). 1. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_roundTo_, _smallestUnit_). 1. Let _result_ be ! RoundISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _roundingIncrement_, _smallestUnit_, _roundingMode_). @@ -1136,10 +1135,11 @@

1. Set _other_ to ? ToTemporalDateTime(_other_). 1. If ? CalendarEquals(_dateTime_.[[Calendar]], _other_.[[Calendar]]) is *false*, throw a *RangeError* exception. 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « », *"nanosecond"*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~datetime~, *"nanosecond"*). 1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _smallestUnit_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « », *"auto"*, _defaultLargestUnit_). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~datetime~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to _defaultLargestUnit_. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_). diff --git a/spec/plaintime.html b/spec/plaintime.html index 46dfeaaa5c..08460bf09d 100644 --- a/spec/plaintime.html +++ b/spec/plaintime.html @@ -314,8 +314,7 @@

Temporal.PlainTime.prototype.round ( _roundTo_ )

1. Perform ! CreateDataPropertyOrThrow(_roundTo_, *"smallestUnit"*, _paramString_). 1. Else, 1. Set _roundTo_ to ? GetOptionsObject(_roundTo_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_roundTo_, « *"year"*, *"month"*, *"week"*, *"day"* », *undefined*). - 1. If _smallestUnit_ is *undefined*, throw a *RangeError* exception. + 1. Let _smallestUnit_ be ? GetTemporalUnit(_roundTo_, *"smallestUnit"*, ~time~, ~required~). 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_roundTo_, *"halfExpand"*). 1. If _smallestUnit_ is *"hour"*, then 1. Let _maximum_ be 24. @@ -951,9 +950,10 @@

1. If _operation_ is ~since~, let _sign_ be -1. Otherwise, let _sign_ be 1. 1. Set _other_ to ? ToTemporalTime(_other_). 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"nanosecond"*). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"auto"*, *"hour"*). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~time~, *"nanosecond"*). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~time~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to *"hour"*. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_). diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html index 3d6c5bf9b6..2c72d77019 100644 --- a/spec/plainyearmonth.html +++ b/spec/plainyearmonth.html @@ -628,10 +628,12 @@

1. Let _calendar_ be _yearMonth_.[[Calendar]]. 1. If ? CalendarEquals(_calendar_, _other_.[[Calendar]]) is *false*, throw a *RangeError* exception. 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _disallowedUnits_ be « *"week"*, *"day"*, *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* ». - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, _disallowedUnits_, *"month"*). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _disallowedUnits_, *"auto"*, *"year"*). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~date~, *"month"*). + 1. If _smallestUnit_ is *"week"* or *"day"*, throw a *RangeError* exception. + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~date~, *"auto"*). + 1. If _largestUnit_ is *"week"* or *"day"*, throw a *RangeError* exception. + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to *"year"*. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_). diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html index 68fb549ec0..5ac0bf37c9 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -727,8 +727,7 @@

Temporal.ZonedDateTime.prototype.round ( _roundTo_ )

1. Perform ! CreateDataPropertyOrThrow(_roundTo_, *"smallestUnit"*, _paramString_). 1. Else, 1. Set _roundTo_ to ? GetOptionsObject(_roundTo_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_roundTo_, « *"year"*, *"month"*, *"week"* », *undefined*). - 1. If _smallestUnit_ is *undefined*, throw a *RangeError* exception. + 1. Let _smallestUnit_ be ? GetTemporalUnit(_roundTo_, *"smallestUnit"*, ~time~, ~required~, « *"day"* »). 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_roundTo_, *"halfExpand"*). 1. Let _roundingIncrement_ be ? ToTemporalDateTimeRoundingIncrement(_roundTo_, _smallestUnit_). 1. Let _timeZone_ be _zonedDateTime_.[[TimeZone]]. @@ -1363,10 +1362,11 @@

1. If ? CalendarEquals(_zonedDateTime_.[[Calendar]], _other_.[[Calendar]]) is *false*, then 1. Throw a *RangeError* exception. 1. Set _options_ to ? GetOptionsObject(_options_). - 1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « », *"nanosecond"*). + 1. Let _smallestUnit_ be ? GetTemporalUnit(_options_, *"smallestUnit"*, ~datetime~, *"nanosecond"*). 1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"hour"*, _smallestUnit_). - 1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « », *"auto"*, _defaultLargestUnit_). - 1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_). + 1. Let _largestUnit_ be ? GetTemporalUnit(_options_, *"largestUnit"*, ~datetime~, *"auto"*). + 1. If _largestUnit_ is *"auto"*, set _largestUnit_ to _defaultLargestUnit_. + 1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*). 1. If _operation_ is ~since~, then 1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_).