From fef6e481907774f523daea6b0271134b6b64630e Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Thu, 16 Feb 2023 14:56:43 -0800
Subject: [PATCH 01/14] Editorial: Restore structured headers in
Calendar(Merge)Fields
This was a rebase error on my part when merging in #2467. My bad!
---
spec/calendar.html | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/spec/calendar.html b/spec/calendar.html
index 561fe653fe..5fd02e68e9 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -101,11 +101,17 @@ GetISO8601Calendar ( )
-
- CalendarFields ( _calendar_, _fieldNames_ )
-
- The CalendarFields abstract operation transforms a List of String values _fieldNames_ into another List of String values by calling the `fields` method of the given _calendar_ Object.
-
+
+
+ CalendarFields (
+ _calendar_: an Object,
+ _fieldNames_: a List of Strings,
+ ): either a normal completion containing a List of Strings, or a throw completion
+
+
1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
1. Let _fieldsArray_ be ? Invoke(_calendar_, *"fields"*, « CreateArrayFromList(_fieldNames_) »).
@@ -113,11 +119,18 @@ CalendarFields ( _calendar_, _fieldNames_ )
-
- CalendarMergeFields ( _calendar_, _fields_, _additionalFields_ )
-
- The CalendarMergeFields abstract operation merges the properties of two Objects _fields_ and _additionalFields_ by calling the `mergeFields` method of the given _calendar_ Object.
-
+
+
+ CalendarMergeFields (
+ _calendar_: an Object,
+ _fields_: an Object,
+ _additionalFields_: an Object,
+ ): either a normal completion containing an Object, or a throw completion
+
+
1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
1. Let _result_ be ? Invoke(_calendar_, *"mergeFields"*, « _fields_, _additionalFields_ »).
From d850e1c915856538e7b691ec449a473bd23be933 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Thu, 1 Dec 2022 12:05:11 -0800
Subject: [PATCH 02/14] Normative: Replace Now.timeZone with Now.timeZoneId
Temporal.Now.timeZone() is replaced by Temporal.Now.timeZoneId() which
always returns a time zone identifier string, rather than a TimeZone
instance.
See: #1808
---
docs/cookbook/fromLegacyDate.mjs | 2 +-
docs/cookbook/fromLegacyDateOnly.mjs | 6 +++---
docs/now.md | 11 ++++++-----
polyfill/index.d.ts | 8 ++++----
polyfill/lib/ecmascript.mjs | 6 ++----
polyfill/lib/now.mjs | 20 ++++++++++----------
spec/temporal.html | 18 +++++-------------
7 files changed, 31 insertions(+), 40 deletions(-)
diff --git a/docs/cookbook/fromLegacyDate.mjs b/docs/cookbook/fromLegacyDate.mjs
index 4dbdbdc6de..1626081a75 100644
--- a/docs/cookbook/fromLegacyDate.mjs
+++ b/docs/cookbook/fromLegacyDate.mjs
@@ -21,7 +21,7 @@ assert.equal(instant.toString(), '1970-01-01T00:00:01Z');
// will be the user's time zone, but on a server the value may not
// be what you expect, so avoid doing this in a server context.
-const zoned = instant.toZonedDateTimeISO(Temporal.Now.timeZone());
+const zoned = instant.toZonedDateTimeISO(Temporal.Now.timeZoneId());
assert.equal(zoned.epochMilliseconds, legacyDate.getTime());
diff --git a/docs/cookbook/fromLegacyDateOnly.mjs b/docs/cookbook/fromLegacyDateOnly.mjs
index df3e60e268..463e547ef5 100644
--- a/docs/cookbook/fromLegacyDateOnly.mjs
+++ b/docs/cookbook/fromLegacyDateOnly.mjs
@@ -1,9 +1,9 @@
// Convert a year/month/day `Date` to a `Temporal.PlainDate`. Uses the caller's time zone.
let date = new Date(2000, 0, 1); // => Sat Jan 01 2000 00:00:00 GMT-0800 (Pacific Standard Time)
let plainDate = date
- .toTemporalInstant() // => 2000-01-01T08:00:00Z
- .toZonedDateTimeISO(Temporal.Now.timeZone()) // => 2000-01-01T00:00:00-08:00[America/Los_Angeles]
- .toPlainDate(); // => 2000-01-01
+ .toTemporalInstant() // => 2000-01-01T08:00:00Z
+ .toZonedDateTimeISO(Temporal.Now.timeZoneId()) // => 2000-01-01T00:00:00-08:00[America/Los_Angeles]
+ .toPlainDate(); // => 2000-01-01
assert.equal(plainDate.toString(), '2000-01-01');
diff --git a/docs/now.md b/docs/now.md
index 3030a473a1..94b304294d 100644
--- a/docs/now.md
+++ b/docs/now.md
@@ -82,23 +82,24 @@ timeit(() => JSON.parse(someData));
// The function took PT0.001031756S
```
-### Temporal.Now.**timeZone**() : Temporal.TimeZone
+### Temporal.Now.**timeZoneId**() : string
-**Returns:** a `Temporal.TimeZone` object representing the time zone according to the current system settings.
+**Returns:** The identifier of time zone according to the current system settings.
-This method gets the current system time zone.
+This method gets the identifier of the current system time zone.
This will usually be a named [IANA time zone](https://www.iana.org/time-zones), as that is how most people configure their computers.
Example usage:
```js
// When is the next daylight saving change from now, in the current location?
-tz = Temporal.Now.timeZone();
+id = Temporal.Now.timeZoneId();
now = Temporal.Now.instant();
+tz = Temporal.TimeZone.from(id);
nextTransition = tz.getNextTransition(now);
before = tz.getOffsetStringFor(nextTransition.subtract({ nanoseconds: 1 }));
after = tz.getOffsetStringFor(nextTransition.add({ nanoseconds: 1 }));
-console.log(`At ${nextTransition.toZonedDateTimeISO(tz)} the offset will change from UTC ${before} to ${after}`);
+console.log(`At ${nextTransition.toZonedDateTimeISO(id)} the offset will change from UTC ${before} to ${after}`);
// example output:
// At 2021-03-14T03:00:00-07:00[America/Los_Angeles] the offset will change from UTC -08:00 to -07:00
```
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index 585c81f205..b155b41620 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -1456,13 +1456,13 @@ export namespace Temporal {
plainTimeISO: (tzLike?: TimeZoneLike) => Temporal.PlainTime;
/**
- * Get the environment's current time zone.
+ * Get the identifier of the environment's current time zone.
*
- * This method gets the current system time zone. This will usually be a
- * named
+ * This method gets the identifier of the current system time zone. This
+ * will usually be a named
* {@link https://en.wikipedia.org/wiki/List_of_tz_database_time_zones|IANA time zone}.
*/
- timeZone: () => Temporal.TimeZone;
+ timeZoneId: () => string;
readonly [Symbol.toStringTag]: 'Temporal.Now';
};
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 974e902bd9..24ac8bb8d4 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -5069,10 +5069,8 @@ export const ES = ObjectAssign({}, ES2022, {
return bigInt.min(NS_MAX, bigInt.max(NS_MIN, result));
};
})(),
- SystemTimeZone: () => {
- const fmt = new IntlDateTimeFormat('en-us');
- const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
- return new TemporalTimeZone(ES.ParseTemporalTimeZone(fmt.resolvedOptions().timeZone));
+ DefaultTimeZone: () => {
+ return new Intl.DateTimeFormat().resolvedOptions().timeZone;
},
ComparisonResult: (value) => (value < 0 ? -1 : value > 0 ? 1 : value),
GetOptionsObject: (options) => {
diff --git a/polyfill/lib/now.mjs b/polyfill/lib/now.mjs
index 2e6a183a4d..2b600cafc0 100644
--- a/polyfill/lib/now.mjs
+++ b/polyfill/lib/now.mjs
@@ -5,37 +5,37 @@ const instant = () => {
const Instant = GetIntrinsic('%Temporal.Instant%');
return new Instant(ES.SystemUTCEpochNanoSeconds());
};
-const plainDateTime = (calendarLike, temporalTimeZoneLike = timeZone()) => {
+const plainDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
const calendar = ES.ToTemporalCalendar(calendarLike);
const inst = instant();
return ES.GetPlainDateTimeFor(timeZone, inst, calendar);
};
-const plainDateTimeISO = (temporalTimeZoneLike = timeZone()) => {
+const plainDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
const calendar = ES.GetISO8601Calendar();
const inst = instant();
return ES.GetPlainDateTimeFor(timeZone, inst, calendar);
};
-const zonedDateTime = (calendarLike, temporalTimeZoneLike = timeZone()) => {
+const zonedDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
const calendar = ES.ToTemporalCalendar(calendarLike);
return ES.CreateTemporalZonedDateTime(ES.SystemUTCEpochNanoSeconds(), timeZone, calendar);
};
-const zonedDateTimeISO = (temporalTimeZoneLike = timeZone()) => {
+const zonedDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
return zonedDateTime(ES.GetISO8601Calendar(), temporalTimeZoneLike);
};
-const plainDate = (calendarLike, temporalTimeZoneLike = timeZone()) => {
+const plainDate = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
return ES.TemporalDateTimeToDate(plainDateTime(calendarLike, temporalTimeZoneLike));
};
-const plainDateISO = (temporalTimeZoneLike = timeZone()) => {
+const plainDateISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
return ES.TemporalDateTimeToDate(plainDateTimeISO(temporalTimeZoneLike));
};
-const plainTimeISO = (temporalTimeZoneLike = timeZone()) => {
+const plainTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
return ES.TemporalDateTimeToTime(plainDateTimeISO(temporalTimeZoneLike));
};
-const timeZone = () => {
- return ES.SystemTimeZone();
+const timeZoneId = () => {
+ return ES.DefaultTimeZone();
};
export const Now = {
@@ -45,7 +45,7 @@ export const Now = {
plainDate,
plainDateISO,
plainTimeISO,
- timeZone,
+ timeZoneId,
zonedDateTime,
zonedDateTimeISO
};
diff --git a/spec/temporal.html b/spec/temporal.html
index e88fef43b2..f49755fedd 100644
--- a/spec/temporal.html
+++ b/spec/temporal.html
@@ -91,13 +91,13 @@ Temporal.Now [ @@toStringTag ]
Function Properties of the Temporal.Now Object
-
- Temporal.Now.timeZone ( )
+
+ Temporal.Now.timeZoneId ( )
This function performs the following steps when called:
- 1. Return ! SystemTimeZone().
+ 1. Return DefaultTimeZone().
@@ -192,14 +192,6 @@ Temporal.Now.plainTimeISO ( [ _temporalTimeZoneLike_ ] )
Abstract operations
-
- SystemTimeZone ( )
-
- 1. Let _identifier_ be DefaultTimeZone().
- 1. Return ! CreateTemporalTimeZone(_identifier_).
-
-
-
SystemUTCEpochNanoseconds ( )
@@ -232,7 +224,7 @@ SystemInstant ( )
SystemDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. If _temporalTimeZoneLike_ is *undefined*, then
- 1. Let _timeZone_ be ! SystemTimeZone().
+ 1. Let _timeZone_ be DefaultTimeZone().
1. Else,
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
@@ -245,7 +237,7 @@ SystemDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
SystemZonedDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. If _temporalTimeZoneLike_ is *undefined*, then
- 1. Let _timeZone_ be ! SystemTimeZone().
+ 1. Let _timeZone_ be DefaultTimeZone().
1. Else,
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
From b06e46a16d5abdc7608a11effeca7c95800d6425 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Fri, 25 Nov 2022 09:57:40 -0800
Subject: [PATCH 03/14] Normative: Remove calendar property from PlainTime
PlainTime now has no calendar. Removes the getter and the internal slot.
Calendar annotations are now ignored in ParseTemporalTimeString.
RejectObjectWithCalendarOrTimeZone still rejects PlainTime, so it is
renamed to RejectTemporalLikeObject.
ToTemporalCalendar rejects PlainTime explicitly instead of looking for its
`calendar` property or treating it as a plain object calendar.
See: #1808
Closes: #1588
---
docs/plaintime.md | 9 +-------
polyfill/index.d.ts | 9 --------
polyfill/lib/ecmascript.mjs | 37 +++++++++++++++------------------
polyfill/lib/plaindate.mjs | 2 +-
polyfill/lib/plaindatetime.mjs | 2 +-
polyfill/lib/plainmonthday.mjs | 2 +-
polyfill/lib/plaintime.mjs | 8 +------
polyfill/lib/plainyearmonth.mjs | 2 +-
polyfill/lib/zoneddatetime.mjs | 2 +-
polyfill/test/validStrings.mjs | 2 +-
spec/abstractops.html | 18 +++++++++-------
spec/calendar.html | 8 +++----
spec/plaindate.html | 2 +-
spec/plaindatetime.html | 2 +-
spec/plainmonthday.html | 2 +-
spec/plaintime.html | 32 ++--------------------------
spec/plainyearmonth.html | 2 +-
spec/zoneddatetime.html | 2 +-
18 files changed, 47 insertions(+), 96 deletions(-)
diff --git a/docs/plaintime.md b/docs/plaintime.md
index b47a485d35..b9fed37af7 100644
--- a/docs/plaintime.md
+++ b/docs/plaintime.md
@@ -200,10 +200,6 @@ time.nanosecond; // => 205
```
-### time.**calendar**: Temporal.Calendar
-
-The value of the `calendar` read-only property is always the ISO 8601 calendar, for future compatibility.
-
## Methods
### time.**with**(_timeLike_: object | string, _options_?: object) : Temporal.PlainTime
@@ -323,9 +319,6 @@ You can round the result using the `smallestUnit`, `roundingIncrement`, and `rou
These behave as in the `Temporal.Duration.round()` method.
The default is to do no rounding.
-Computing the difference between two times in different calendar systems is not supported.
-If you need to do this, choose the calendar in which the computation takes place by converting one of the times with `time.withCalendar()`.
-
Usage example:
@@ -640,7 +633,7 @@ date = Temporal.PlainDate.from('2006-08-24');
time.toPlainDateTime(date); // => 2006-08-24T15:23:30.003
```
-### time.**getISOFields**(): { isoHour: number, isoMinute: number, isoSecond: number, isoMillisecond: number, isoMicrosecond: number, isoNanosecond: number, calendar: Temporal.Calendar }
+### time.**getISOFields**(): { isoHour: number, isoMinute: number, isoSecond: number, isoMillisecond: number, isoMicrosecond: number, isoNanosecond: number }
**Returns:** a plain object with properties expressing `time` in the ISO 8601 calendar.
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index b155b41620..f6179bfea7 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -999,12 +999,6 @@ export namespace Temporal {
readonly [Symbol.toStringTag]: 'Temporal.PlainMonthDay';
}
- // Temporal.PlainTime's `calendar` field is a Temporal.Calendar, not a
- // Temporal.CalendarProtocol, because that type's calendar is not customizable
- // by users. Temporal.ZonedDateTime and Temporal.PlainDateTime are also
- // "time-like" but their `calendar` is a Temporal.CalendarProtocol. Therefore,
- // those types are added below to ensure that their instances are accepted by
- // methods that take a PlainTimeLike object.
export type PlainTimeLike =
| {
hour?: number;
@@ -1013,7 +1007,6 @@ export namespace Temporal {
millisecond?: number;
microsecond?: number;
nanosecond?: number;
- calendar?: Temporal.Calendar | 'iso8601';
}
| Temporal.ZonedDateTime
| Temporal.PlainDateTime;
@@ -1025,7 +1018,6 @@ export namespace Temporal {
isoMillisecond: number;
isoMicrosecond: number;
isoNanosecond: number;
- calendar: Temporal.Calendar;
};
/**
@@ -1063,7 +1055,6 @@ export namespace Temporal {
readonly millisecond: number;
readonly microsecond: number;
readonly nanosecond: number;
- readonly calendar: Temporal.Calendar;
equals(other: Temporal.PlainTime | PlainTimeLike | string): boolean;
with(timeLike: Temporal.PlainTime | PlainTimeLike, options?: AssignmentOptions): Temporal.PlainTime;
add(durationLike: Temporal.Duration | DurationLike | string, options?: ArithmeticOptions): Temporal.PlainTime;
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 24ac8bb8d4..f39c1af3dd 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -318,10 +318,13 @@ export const ES = ObjectAssign({}, ES2022, {
IsTemporalYearMonth: (item) => HasSlot(item, YEAR_MONTH_BRAND),
IsTemporalMonthDay: (item) => HasSlot(item, MONTH_DAY_BRAND),
IsTemporalZonedDateTime: (item) => HasSlot(item, EPOCHNANOSECONDS, TIME_ZONE, CALENDAR),
- RejectObjectWithCalendarOrTimeZone: (item) => {
+ RejectTemporalLikeObject: (item) => {
if (HasSlot(item, CALENDAR) || HasSlot(item, TIME_ZONE)) {
throw new TypeError('with() does not support a calendar or timeZone property');
}
+ if (ES.IsTemporalTime(item)) {
+ throw new TypeError('with() does not accept Temporal.PlainTime, use withPlainTime() instead');
+ }
if (item.calendar !== undefined) {
throw new TypeError('with() does not support a calendar property');
}
@@ -431,7 +434,7 @@ export const ES = ObjectAssign({}, ES2022, {
},
ParseTemporalTimeString: (isoString) => {
const match = PARSE.time.exec(isoString);
- let hour, minute, second, millisecond, microsecond, nanosecond, annotations, calendar;
+ let hour, minute, second, millisecond, microsecond, nanosecond, annotations;
if (match) {
hour = ES.ToIntegerOrInfinity(match[1]);
minute = ES.ToIntegerOrInfinity(match[2] || match[5]);
@@ -443,23 +446,20 @@ export const ES = ObjectAssign({}, ES2022, {
nanosecond = ES.ToIntegerOrInfinity(fraction.slice(6, 9));
annotations = match[14];
for (const [, critical, key, value] of annotations.matchAll(PARSE.annotation)) {
- if (key === 'u-ca') {
- if (calendar === undefined) calendar = value;
- } else if (critical === '!') {
+ if (key !== 'u-ca' && critical === '!') {
throw new RangeError(`Unrecognized annotation: !${key}=${value}`);
}
}
if (match[8]) throw new RangeError('Z designator not supported for PlainTime');
} else {
let z, hasTime;
- ({ hasTime, hour, minute, second, millisecond, microsecond, nanosecond, calendar, z } =
- ES.ParseISODateTime(isoString));
+ ({ hasTime, hour, minute, second, millisecond, microsecond, nanosecond, z } = ES.ParseISODateTime(isoString));
if (!hasTime) throw new RangeError(`time is missing in string: ${isoString}`);
if (z) throw new RangeError('Z designator not supported for PlainTime');
}
// if it's a date-time string, OK
if (/[tT ][0-9][0-9]/.test(isoString)) {
- return { hour, minute, second, millisecond, microsecond, nanosecond, calendar };
+ return { hour, minute, second, millisecond, microsecond, nanosecond };
}
// Reject strings that are ambiguous with PlainMonthDay or PlainYearMonth.
try {
@@ -470,7 +470,7 @@ export const ES = ObjectAssign({}, ES2022, {
const { year, month } = ES.ParseTemporalYearMonthString(isoString);
ES.RejectISODate(year, month, 1);
} catch {
- return { hour, minute, second, millisecond, microsecond, nanosecond, calendar };
+ return { hour, minute, second, millisecond, microsecond, nanosecond };
}
}
throw new RangeError(`invalid ISO 8601 time-only string ${isoString}; may need a T prefix`);
@@ -1220,7 +1220,7 @@ export const ES = ObjectAssign({}, ES2022, {
return ES.CalendarMonthDayFromFields(calendar, result);
},
ToTemporalTime: (item, overflow = 'constrain') => {
- let hour, minute, second, millisecond, microsecond, nanosecond, calendar;
+ let hour, minute, second, millisecond, microsecond, nanosecond;
if (ES.Type(item) === 'Object') {
if (ES.IsTemporalTime(item)) return item;
if (ES.IsTemporalZonedDateTime(item)) {
@@ -1237,10 +1237,6 @@ export const ES = ObjectAssign({}, ES2022, {
GetSlot(item, ISO_NANOSECOND)
);
}
- calendar = ES.GetTemporalCalendarWithISODefault(item);
- if (ES.ToString(calendar) !== 'iso8601') {
- throw new RangeError('PlainTime can only have iso8601 calendar');
- }
({ hour, minute, second, millisecond, microsecond, nanosecond } = ES.ToTemporalTimeRecord(item));
({ hour, minute, second, millisecond, microsecond, nanosecond } = ES.RegulateTime(
hour,
@@ -1252,13 +1248,8 @@ export const ES = ObjectAssign({}, ES2022, {
overflow
));
} else {
- ({ hour, minute, second, millisecond, microsecond, nanosecond, calendar } = ES.ParseTemporalTimeString(
- ES.ToString(item)
- ));
+ ({ hour, minute, second, millisecond, microsecond, nanosecond } = ES.ParseTemporalTimeString(ES.ToString(item)));
ES.RejectTime(hour, minute, second, millisecond, microsecond, nanosecond);
- if (calendar !== undefined && calendar !== 'iso8601') {
- throw new RangeError('PlainTime can only have iso8601 calendar');
- }
}
const TemporalPlainTime = GetIntrinsic('%Temporal.PlainTime%');
return new TemporalPlainTime(hour, minute, second, millisecond, microsecond, nanosecond);
@@ -1769,12 +1760,18 @@ export const ES = ObjectAssign({}, ES2022, {
if (ES.Type(calendarLike) === 'Object') {
if (ES.IsTemporalCalendar(calendarLike)) return calendarLike;
if (HasSlot(calendarLike, CALENDAR)) return GetSlot(calendarLike, CALENDAR);
+ if (ES.IsTemporalTime(calendarLike)) {
+ throw new RangeError('Expected a calendar object but received a Temporal.PlainTime');
+ }
if (ES.IsTemporalTimeZone(calendarLike)) {
throw new RangeError('Expected a calendar object but received a Temporal.TimeZone');
}
if (!('calendar' in calendarLike)) return calendarLike;
calendarLike = calendarLike.calendar;
if (ES.Type(calendarLike) === 'Object') {
+ if (ES.IsTemporalTime(calendarLike)) {
+ throw new RangeError('Expected a calendar object as the calendar property but received a Temporal.PlainTime');
+ }
if (ES.IsTemporalTimeZone(calendarLike)) {
throw new RangeError('Expected a calendar object as the calendar property but received a Temporal.TimeZone');
}
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 875a559600..821de329c8 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -94,7 +94,7 @@ export class PlainDate {
if (ES.Type(temporalDateLike) !== 'Object') {
throw new TypeError('invalid argument');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalDateLike);
+ ES.RejectTemporalLikeObject(temporalDateLike);
options = ES.GetOptionsObject(options);
const calendar = GetSlot(this, CALENDAR);
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index 25f146906e..0e86adee7f 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -150,7 +150,7 @@ export class PlainDateTime {
if (ES.Type(temporalDateTimeLike) !== 'Object') {
throw new TypeError('invalid argument');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalDateTimeLike);
+ ES.RejectTemporalLikeObject(temporalDateTimeLike);
options = ES.GetOptionsObject(options);
const calendar = GetSlot(this, CALENDAR);
diff --git a/polyfill/lib/plainmonthday.mjs b/polyfill/lib/plainmonthday.mjs
index 045063c48c..ba7cee7d93 100644
--- a/polyfill/lib/plainmonthday.mjs
+++ b/polyfill/lib/plainmonthday.mjs
@@ -36,7 +36,7 @@ export class PlainMonthDay {
if (ES.Type(temporalMonthDayLike) !== 'Object') {
throw new TypeError('invalid argument');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalMonthDayLike);
+ ES.RejectTemporalLikeObject(temporalMonthDayLike);
options = ES.GetOptionsObject(options);
const calendar = GetSlot(this, CALENDAR);
diff --git a/polyfill/lib/plaintime.mjs b/polyfill/lib/plaintime.mjs
index 23b547a014..d5271362ef 100644
--- a/polyfill/lib/plaintime.mjs
+++ b/polyfill/lib/plaintime.mjs
@@ -70,7 +70,6 @@ export class PlainTime {
SetSlot(this, ISO_MILLISECOND, isoMillisecond);
SetSlot(this, ISO_MICROSECOND, isoMicrosecond);
SetSlot(this, ISO_NANOSECOND, isoNanosecond);
- SetSlot(this, CALENDAR, ES.GetISO8601Calendar());
if (typeof __debug__ !== 'undefined' && __debug__) {
Object.defineProperty(this, '_repr_', {
@@ -82,10 +81,6 @@ export class PlainTime {
}
}
- get calendar() {
- if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
- }
get hour() {
if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver');
return GetSlot(this, ISO_HOUR);
@@ -116,7 +111,7 @@ export class PlainTime {
if (ES.Type(temporalTimeLike) !== 'Object') {
throw new TypeError('invalid argument');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalTimeLike);
+ ES.RejectTemporalLikeObject(temporalTimeLike);
options = ES.GetOptionsObject(options);
const overflow = ES.ToTemporalOverflow(options);
@@ -305,7 +300,6 @@ export class PlainTime {
getISOFields() {
if (!ES.IsTemporalTime(this)) throw new TypeError('invalid receiver');
return {
- calendar: GetSlot(this, CALENDAR),
isoHour: GetSlot(this, ISO_HOUR),
isoMicrosecond: GetSlot(this, ISO_MICROSECOND),
isoMillisecond: GetSlot(this, ISO_MILLISECOND),
diff --git a/polyfill/lib/plainyearmonth.mjs b/polyfill/lib/plainyearmonth.mjs
index 61481bc9e4..8f0630e9d9 100644
--- a/polyfill/lib/plainyearmonth.mjs
+++ b/polyfill/lib/plainyearmonth.mjs
@@ -62,7 +62,7 @@ export class PlainYearMonth {
if (ES.Type(temporalYearMonthLike) !== 'Object') {
throw new TypeError('invalid argument');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalYearMonthLike);
+ ES.RejectTemporalLikeObject(temporalYearMonthLike);
options = ES.GetOptionsObject(options);
const calendar = GetSlot(this, CALENDAR);
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 92170c6f35..3969aa1d46 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -179,7 +179,7 @@ export class ZonedDateTime {
if (ES.Type(temporalZonedDateTimeLike) !== 'Object') {
throw new TypeError('invalid zoned-date-time-like');
}
- ES.RejectObjectWithCalendarOrTimeZone(temporalZonedDateTimeLike);
+ ES.RejectTemporalLikeObject(temporalZonedDateTimeLike);
options = ES.GetOptionsObject(options);
const calendar = GetSlot(this, CALENDAR);
diff --git a/polyfill/test/validStrings.mjs b/polyfill/test/validStrings.mjs
index 5ed0e7ec92..b53cdf2a5c 100644
--- a/polyfill/test/validStrings.mjs
+++ b/polyfill/test/validStrings.mjs
@@ -426,7 +426,7 @@ const comparisonItems = {
'nanoseconds'
],
MonthDay: ['month', 'day', 'calendar'],
- Time: [...timeItems, 'calendar'],
+ Time: [...timeItems],
TimeZone: ['offset', 'ianaName'],
YearMonth: ['year', 'month', 'calendar'],
ZonedDateTime: [...dateItems, ...timeItems, 'offset', 'ianaName', 'calendar']
diff --git a/spec/abstractops.html b/spec/abstractops.html
index d561e46b19..eac484169c 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -554,13 +554,17 @@ MaximumTemporalDurationRoundingIncrement ( _unit_ )
-
- RejectObjectWithCalendarOrTimeZone ( _object_ )
-
- The abstract operation RejectObjectWithCalendarOrTimeZone throws an exception if its argument _object_ is an instance of one of the Temporal types that carries a calendar or time zone, or is an object that has a `calendar` or `timeZone` property.
-
+
+
+ RejectTemporalLikeObject (
+ _object_: an Object,
+ ): either a normal completion containing ~unused~, or a throw completion
+
+
- 1. Assert: Type(_object_) is Object.
1. If _object_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
1. Throw a *TypeError* exception.
1. Let _calendarProperty_ be ? Get(_object_, *"calendar"*).
@@ -569,6 +573,7 @@ RejectObjectWithCalendarOrTimeZone ( _object_ )
1. Let _timeZoneProperty_ be ? Get(_object_, *"timeZone"*).
1. If _timeZoneProperty_ is not *undefined*, then
1. Throw a *TypeError* exception.
+ 1. Return ~unused~.
@@ -1557,7 +1562,6 @@
[[Millisecond]]: _result_.[[Millisecond]],
[[Microsecond]]: _result_.[[Microsecond]],
[[Nanosecond]]: _result_.[[Nanosecond]],
- [[Calendar]]: _result_.[[Calendar]]
}.
diff --git a/spec/calendar.html b/spec/calendar.html
index 5fd02e68e9..6e05cd62f9 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -465,13 +465,13 @@ ToTemporalCalendar ( _temporalCalendarLike_ )
1. If Type(_temporalCalendarLike_) is Object, then
1. If _temporalCalendarLike_ has an [[InitializedTemporalCalendar]] internal slot, then
1. Return _temporalCalendarLike_.
- 1. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ 1. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _temporalCalendarLike_.[[Calendar]].
- 1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
+ 1. If _temporalCalendarLike_ has an [[InitializedTemporalTime]] or [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
1. Set _temporalCalendarLike_ to ? Get(_temporalCalendarLike_, *"calendar"*).
1. If Type(_temporalCalendarLike_) is Object, then
- 1. If _temporalCalendarLike_ has an [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
+ 1. If _temporalCalendarLike_ has an [[InitializedTemporalTime]] or [[InitializedTemporalTimeZone]] internal slot, throw a *RangeError* exception.
1. If ? HasProperty(_temporalCalendarLike_, *"calendar"*) is *false*, return _temporalCalendarLike_.
1. Let _identifier_ be ? ToString(_temporalCalendarLike_).
1. Set _identifier_ to ? ParseTemporalCalendarString(_identifier_).
@@ -500,7 +500,7 @@ GetTemporalCalendarWithISODefault ( _item_ )
If no such property is present, the ISO 8601 calendar is returned.
- 1. If _item_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalTime]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
+ 1. If _item_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _item_.[[Calendar]].
1. Let _calendarLike_ be ? Get(_item_, *"calendar"*).
1. Return ? ToTemporalCalendarWithISODefault(_calendarLike_).
diff --git a/spec/plaindate.html b/spec/plaindate.html
index d5845b0e89..cb9d2568d4 100644
--- a/spec/plaindate.html
+++ b/spec/plaindate.html
@@ -394,7 +394,7 @@ Temporal.PlainDate.prototype.with ( _temporalDateLike_ [ , _options_ ] )
Temporal.PlainDateTime.prototype.with ( _temporalDateTimeLike_ [ , _options_
1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
1. If Type(_temporalDateTimeLike_) is not Object, then
1. Throw a *TypeError* exception.
- 1. Perform ? RejectObjectWithCalendarOrTimeZone(_temporalDateTimeLike_).
+ 1. Perform ? RejectTemporalLikeObject(_temporalDateTimeLike_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _calendar_ be _dateTime_.[[Calendar]].
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »).
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index fbd38fb16b..78278e703e 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -149,7 +149,7 @@ Temporal.PlainMonthDay.prototype.with ( _temporalMonthDayLike_ [ , _options_
1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
1. If Type(_temporalMonthDayLike_) is not Object, then
1. Throw a *TypeError* exception.
- 1. Perform ? RejectObjectWithCalendarOrTimeZone(_temporalMonthDayLike_).
+ 1. Perform ? RejectTemporalLikeObject(_temporalMonthDayLike_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _calendar_ be _monthDay_.[[Calendar]].
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
diff --git a/spec/plaintime.html b/spec/plaintime.html
index 1c4eea90b3..8a748549a0 100644
--- a/spec/plaintime.html
+++ b/spec/plaintime.html
@@ -107,19 +107,6 @@ Temporal.PlainTime.prototype[ @@toStringTag ]
-
- get Temporal.PlainTime.prototype.calendar
-
- `Temporal.PlainTime.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
- Its get accessor function performs the following steps:
-
-
- 1. Let _temporalTime_ be the *this* value.
- 1. Perform ? RequireInternalSlot(_temporalTime_, [[InitializedTemporalTime]]).
- 1. Return _temporalTime_.[[Calendar]].
-
-
-
get Temporal.PlainTime.prototype.hour
@@ -232,7 +219,7 @@
Temporal.PlainTime.prototype.with ( _temporalTimeLike_ [ , _options_ ] )
Temporal.PlainTime.prototype.getISOFields ( )
1. Let _temporalTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalTime_, [[InitializedTemporalTime]]).
1. Let _fields_ be OrdinaryObjectCreate(%Object.prototype%).
- 1. Perform ! CreateDataPropertyOrThrow(_fields_, *"calendar"*, _temporalTime_.[[Calendar]]).
1. Perform ! CreateDataPropertyOrThrow(_fields_, *"isoHour"*, 𝔽(_temporalTime_.[[ISOHour]])).
1. Perform ! CreateDataPropertyOrThrow(_fields_, *"isoMicrosecond"*, 𝔽(_temporalTime_.[[ISOMicrosecond]])).
1. Perform ! CreateDataPropertyOrThrow(_fields_, *"isoMillisecond"*, 𝔽(_temporalTime_.[[ISOMillisecond]])).
@@ -531,14 +517,6 @@ Properties of Temporal.PlainTime Instances
An integer between 0 and 999, inclusive, representing the nanosecond within the microsecond.
-
-
- [[Calendar]]
- |
-
- An instance of the built-in ISO 8601 calendar.
- |
-
@@ -599,17 +577,12 @@ ToTemporalTime ( _item_ [ , _overflow_ ] )
1. Return ! CreateTemporalTime(_plainDateTime_.[[ISOHour]], _plainDateTime_.[[ISOMinute]], _plainDateTime_.[[ISOSecond]], _plainDateTime_.[[ISOMillisecond]], _plainDateTime_.[[ISOMicrosecond]], _plainDateTime_.[[ISONanosecond]]).
1. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then
1. Return ! CreateTemporalTime(_item_.[[ISOHour]], _item_.[[ISOMinute]], _item_.[[ISOSecond]], _item_.[[ISOMillisecond]], _item_.[[ISOMicrosecond]], _item_.[[ISONanosecond]]).
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
- 1. If ? ToString(_calendar_) is not *"iso8601"*, then
- 1. Throw a *RangeError* exception.
1. Let _result_ be ? ToTemporalTimeRecord(_item_).
1. Set _result_ to ? RegulateTime(_result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _overflow_).
1. Else,
1. Let _string_ be ? ToString(_item_).
1. Let _result_ be ? ParseTemporalTimeString(_string_).
1. Assert: IsValidTime(_result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]]) is *true*.
- 1. If _result_.[[Calendar]] is not one of *undefined* or *"iso8601"*, then
- 1. Throw a *RangeError* exception.
1. Return ! CreateTemporalTime(_result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]]).
@@ -738,14 +711,13 @@
1. If IsValidTime(_hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_) is *false*, throw a *RangeError* exception.
1. If _newTarget_ is not present, set _newTarget_ to %Temporal.PlainTime%.
- 1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.PlainTime.prototype%"*, « [[InitializedTemporalTime]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] »).
+ 1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.PlainTime.prototype%"*, « [[InitializedTemporalTime]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]] »).
1. Set _object_.[[ISOHour]] to _hour_.
1. Set _object_.[[ISOMinute]] to _minute_.
1. Set _object_.[[ISOSecond]] to _second_.
1. Set _object_.[[ISOMillisecond]] to _millisecond_.
1. Set _object_.[[ISOMicrosecond]] to _microsecond_.
1. Set _object_.[[ISONanosecond]] to _nanosecond_.
- 1. Set _object_.[[Calendar]] to ! GetISO8601Calendar().
1. Return _object_.
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index ee2f35db00..d5fd7895bd 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -230,7 +230,7 @@ Temporal.PlainYearMonth.prototype.with ( _temporalYearMonthLike_ [ , _option
1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
1. If Type(_temporalYearMonthLike_) is not Object, then
1. Throw a *TypeError* exception.
- 1. Perform ? RejectObjectWithCalendarOrTimeZone(_temporalYearMonthLike_).
+ 1. Perform ? RejectTemporalLikeObject(_temporalYearMonthLike_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _calendar_ be _yearMonth_.[[Calendar]].
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index fa031e58e7..d4eb546e84 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -584,7 +584,7 @@ Temporal.ZonedDateTime.prototype.with ( _temporalZonedDateTimeLike_ [ , _opt
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
1. If Type(_temporalZonedDateTimeLike_) is not Object, then
1. Throw a *TypeError* exception.
- 1. Perform ? RejectObjectWithCalendarOrTimeZone(_temporalZonedDateTimeLike_).
+ 1. Perform ? RejectTemporalLikeObject(_temporalZonedDateTimeLike_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »).
From c90afb14b41d0144f47c014700fad639a97c7f9b Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Mon, 16 Jan 2023 16:43:17 -0800
Subject: [PATCH 04/14] Normative: Store strings or objects in calendar slot,
remove getters
Refactor so that Temporal objects' [[Calendar]] internal slot can now
store either a string (builtin calendar) or an object (custom calendar).
The .calendar getter is replaced with a .calendarId getter that always
returns a string, and a .getCalendar() method that always returns a new
object if the slot stored a string.
The operations ToTemporalCalendarIdentifier and ToTemporalCalendarObject
convert a [[Calendar]] slot value to one or the other.
See: #1808
---
docs/calendar.md | 7 +-
docs/plaindate.md | 27 +++--
docs/plaindatetime.md | 29 +++--
docs/plainmonthday.md | 24 +++-
docs/plainyearmonth.md | 26 +++--
docs/zoneddatetime.md | 28 +++--
polyfill/index.d.ts | 21 ++--
polyfill/lib/calendar.mjs | 71 ++++++++----
polyfill/lib/ecmascript.mjs | 129 ++++++++++++++++++++-
polyfill/lib/plaindate.mjs | 9 +-
polyfill/lib/plaindatetime.mjs | 8 +-
polyfill/lib/plainmonthday.mjs | 9 +-
polyfill/lib/plainyearmonth.mjs | 9 +-
polyfill/lib/zoneddatetime.mjs | 9 +-
spec/calendar.html | 191 +++++++++++++++++++++++---------
spec/instant.html | 2 +-
spec/intl.html | 8 +-
spec/plaindate.html | 22 +++-
spec/plaindatetime.html | 22 +++-
spec/plainmonthday.html | 22 +++-
spec/plainyearmonth.html | 22 +++-
spec/timezone.html | 2 +-
spec/zoneddatetime.html | 22 +++-
23 files changed, 547 insertions(+), 172 deletions(-)
diff --git a/docs/calendar.md b/docs/calendar.md
index 22fca6dab3..33d20fe0de 100644
--- a/docs/calendar.md
+++ b/docs/calendar.md
@@ -107,10 +107,11 @@ There are two ways to do this.
The recommended way is to create a class inheriting from `Temporal.Calendar`.
You must use one of the built-in calendars as the "base calendar".
-In the class's constructor, call `super()` with the identifier of the base calendar.
+In the class's constructor, call `super()` with the identifier of a built-in calendar to serve as a base.
The class must override `toString()` to return its own identifier.
-Overriding all the other members is optional.
-If you don't override the optional members, then they will behave as in the base calendar.
+Overriding all the other properties of `Temporal.Calendar.prototype` is optional.
+Any property that's not overridden will behave as in the base calendar.
+It's recommended to override `dateFromFields()`, `monthDayFromFields()`, `yearMonthFromFields()`, and `dateAdd()`so that they return Temporal objects with the custom calendar and not the base calendar.
The other, more difficult, way to create a custom calendar is to create a plain object implementing the `Temporal.Calendar` protocol, without subclassing.
The object must implement all of the `Temporal.Calendar` properties and methods except for `id`, `fields()`, `mergeFields()`, and `toJSON()`.
diff --git a/docs/plaindate.md b/docs/plaindate.md
index af6721a89c..0441ae545d 100644
--- a/docs/plaindate.md
+++ b/docs/plaindate.md
@@ -17,14 +17,14 @@ It can also be combined with a `Temporal.PlainTime` to yield a "zoneless" `Tempo
## Constructor
-### **new Temporal.PlainDate**(_isoYear_: number, _isoMonth_: number, _isoDay_: number, _calendar_?: string | object) : Temporal.PlainDate
+### **new Temporal.PlainDate**(_isoYear_: number, _isoMonth_: number, _isoDay_: number, _calendar_: string | object = "iso8601") : Temporal.PlainDate
**Parameters:**
- `isoYear` (number): A year.
- `isoMonth` (number): A month, ranging between 1 and 12 inclusive.
- `isoDay` (number): A day of the month, ranging between 1 and 31 inclusive.
-- `calendar` (optional `Temporal.Calendar`, plain object, or string): A calendar to project the date into.
+- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): A calendar to project the date into.
**Returns:** a new `Temporal.PlainDate` object.
@@ -37,6 +37,9 @@ Together, `isoYear`, `isoMonth`, and `isoDay` must represent a valid date in tha
The range of allowed values for this type is exactly enough that calling [`toPlainDate()`](./plaindatetime.md#toPlainDate) on any valid `Temporal.PlainDateTime` will succeed.
If `isoYear`, `isoMonth`, and `isoDay` form a date outside of this range, then this function will throw a `RangeError`.
+Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
+Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
+
> **NOTE**: The `isoMonth` argument ranges from 1 to 12, which is different from legacy `Date` where months are represented by zero-based indices (0 to 11).
Usage examples:
@@ -103,10 +106,8 @@ date = Temporal.PlainDate.from(Temporal.PlainDateTime.from('2006-08-24T15:43:27'
// => 2006-08-24
// same as above; Temporal.PlainDateTime has year, month, and day properties
-calendar = Temporal.Calendar.from('islamic');
-date = Temporal.PlainDate.from({ year: 1427, month: 8, day: 1, calendar }); // => 2006-08-24[u-ca=islamic]
date = Temporal.PlainDate.from({ year: 1427, month: 8, day: 1, calendar: 'islamic' });
- // => 2006-08-24[u-ca=islamic] (same as above)
+ // => 2006-08-24[u-ca=islamic]
// Different overflow modes
date = Temporal.PlainDate.from({ year: 2001, month: 13, day: 1 }, { overflow: 'constrain' });
@@ -199,9 +200,10 @@ date.day; // => 18
```
-### date.**calendar** : object
+### date.**calendarId** : string
-The `calendar` read-only property gives the calendar that the `year`, `month`, and `day` properties are interpreted in.
+The `calendarId` read-only property gives the identifier of the calendar that the `year`, `month`, `monthCode`, and `day` properties are interpreted in.
+If the date was created with a custom calendar object, this gives the `id` property of that object.
### date.**era** : string | undefined
@@ -805,9 +807,16 @@ date.toPlainYearMonth(); // => 2006-08
date.toPlainMonthDay(); // => 08-24
```
-### date.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: object }
+### date.**getCalendar**(): object
+
+**Returns:** a `Temporal.Calendar` instance or plain object representing the calendar in which `date` is reckoned.
+
+This method is mainly useful if you need an object on which to call calendar methods.
+Most code will not need to use it.
+
+### date.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: string | object }
-**Returns:** a plain object with properties expressing `date` in the ISO 8601 calendar, as well as the value of `date.calendar`.
+**Returns:** a plain object with properties expressing `date` in the ISO 8601 calendar, as well as the calendar (usually a string, but may be an object) in which `date` is reckoned.
This method is mainly useful if you are implementing a custom calendar.
Most code will not need to use it.
diff --git a/docs/plaindatetime.md b/docs/plaindatetime.md
index d6a2f4c298..e2bb394ed5 100644
--- a/docs/plaindatetime.md
+++ b/docs/plaindatetime.md
@@ -36,7 +36,7 @@ To learn more about time zones and DST best practices, visit [Time Zones and Res
## Constructor
-### **new Temporal.PlainDateTime**(_isoYear_: number, _isoMonth_: number, _isoDay_: number, _isoHour_: number = 0, _isoMinute_: number = 0, _isoSecond_: number = 0, _isoMillisecond_: number = 0, _isoMicrosecond_: number = 0, _isoNanosecond_: number = 0, _calendar_?: string | object) : Temporal.PlainDateTime
+### **new Temporal.PlainDateTime**(_isoYear_: number, _isoMonth_: number, _isoDay_: number, _isoHour_: number = 0, _isoMinute_: number = 0, _isoSecond_: number = 0, _isoMillisecond_: number = 0, _isoMicrosecond_: number = 0, _isoNanosecond_: number = 0, _calendar_: string | object = "iso8601") : Temporal.PlainDateTime
**Parameters:**
@@ -49,7 +49,7 @@ To learn more about time zones and DST best practices, visit [Time Zones and Res
- `isoMillisecond` (optional number): A number of milliseconds, ranging between 0 and 999 inclusive.
- `isoMicrosecond` (optional number): A number of microseconds, ranging between 0 and 999 inclusive.
- `isoNanosecond` (optional number): A number of nanoseconds, ranging between 0 and 999 inclusive.
-- `calendar` (optional `Temporal.Calendar`, plain object, or string): A calendar to project the datetime into.
+- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): A calendar to project the datetime into.
**Returns:** a new `Temporal.PlainDateTime` object.
@@ -65,6 +65,9 @@ Together, `isoYear`, `isoMonth`, and `isoDay` must represent a valid date in tha
The range of allowed values for this type is exactly enough that calling `timeZone.getPlainDateTimeFor(instant)` will succeed when `timeZone` is any built-in `Temporal.TimeZone` and `instant` is any valid `Temporal.Instant`.
If the parameters passed in to this constructor form a date outside of this range, then this function will throw a `RangeError`.
+Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
+Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
+
> **NOTE**: The `isoMonth` argument ranges from 1 to 12, which is different from legacy `Date` where months are represented by zero-based indices (0 to 11).
Usage examples:
@@ -96,7 +99,7 @@ If the value is any other object, a `Temporal.PlainDateTime` will be constructed
At least the `year` (or `era` and `eraYear`), `month` (or `monthCode`), and `day` properties must be present.
Default values for other missing fields are determined by the calendar.
-If the `calendar` property is not present, it's assumed to be `Temporal.Calendar.from('iso8601')`, the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates).
+If the `calendar` property is not present, it's assumed to be `'iso8601'` (identifying the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates)).
Any other missing properties will be assumed to be 0 (for time fields).
Any non-object value is converted to a string, which is expected to be in ISO 8601 format.
@@ -147,12 +150,8 @@ dt = Temporal.PlainDateTime.from(Temporal.PlainDate.from('1995-12-07T03:24:30'))
// => 1995-12-07T00:00:00
// same as above; Temporal.PlainDate has year, month, and day properties
-calendar = Temporal.Calendar.from('hebrew');
-dt = Temporal.PlainDateTime.from({ year: 5756, month: 3, day: 14, hour: 3, minute: 24, second: 30, calendar });
- // => 1995-12-07T03:24:30[u-ca=hebrew]
dt = Temporal.PlainDateTime.from({ year: 5756, month: 3, day: 14, hour: 3, minute: 24, second: 30, calendar: 'hebrew' });
// => 1995-12-07T03:24:30[u-ca=hebrew]
- // same as above
// Different overflow modes
dt = Temporal.PlainDateTime.from({ year: 2001, month: 13, day: 1 }, { overflow: 'constrain' });
@@ -290,9 +289,10 @@ dt.nanosecond; // => 500
```
-### datetime.**calendar** : object
+### datetime.**calendarId** : string
-The `calendar` read-only property gives the calendar that the `year`, `month`, `day`, `hour`, `minute`, `second`, `millisecond`, `microsecond`, and `nanosecond` properties are interpreted in.
+The `calendarId` read-only property gives the identifier of the calendar that the `year`, `month`, `monthCode`, and `day` properties are interpreted in.
+If the date was created with a custom calendar object, this gives the `id` property of that object.
### datetime.**era** : string | undefined
@@ -1053,9 +1053,16 @@ dt.toPlainMonthDay(); // => 12-07
dt.toPlainTime(); // => 03:24:30.0000035
```
-### datetime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, isoHour: number, isoMinute: number, isoSecond: number, isoMillisecond: number, isoMicrosecond: number, isoNanosecond: number, calendar: object }
+### datetime.**getCalendar**(): object
+
+**Returns:** a `Temporal.Calendar` instance or plain object representing the calendar in which `datetime` is reckoned.
+
+This method is mainly useful if you need an object on which to call calendar methods.
+Most code will not need to use it.
+
+### datetime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, isoHour: number, isoMinute: number, isoSecond: number, isoMillisecond: number, isoMicrosecond: number, isoNanosecond: number, calendar: string | object }
-**Returns:** a plain object with properties expressing `datetime` in the ISO 8601 calendar, as well as the value of `datetime.calendar`.
+**Returns:** a plain object with properties expressing `datetime` in the ISO 8601 calendar, as well as the calendar (usually a string, but may be an object) in which `datetime` is reckoned.
This method is mainly useful if you are implementing a custom calendar.
Most code will not need to use it.
diff --git a/docs/plainmonthday.md b/docs/plainmonthday.md
index dac731d341..ed409e6fd4 100644
--- a/docs/plainmonthday.md
+++ b/docs/plainmonthday.md
@@ -13,13 +13,13 @@ A `Temporal.PlainMonthDay` can be converted into a `Temporal.PlainDate` by combi
## Constructor
-### **new Temporal.PlainMonthDay**(_isoMonth_: number, _isoDay_: number, _calendar_?: string | object, _referenceISOYear_?: number) : Temporal.PlainMonthDay
+### **new Temporal.PlainMonthDay**(_isoMonth_: number, _isoDay_: number, _calendar_: string | object = "iso8601", _referenceISOYear_: number = 1972) : Temporal.PlainMonthDay
**Parameters:**
- `isoMonth` (number): A month, ranging between 1 and 12 inclusive.
- `isoDay` (number): A day of the month, ranging between 1 and 31 inclusive.
-- `calendar` (optional `Temporal.Calendar`, plain object, or string): A calendar to project the date into.
+- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): A calendar to project the date into.
- `referenceISOYear` (optional for ISO 8601 calendar; required for other calendars):
A reference year in the ISO 8601 calendar for disambiguation when implementing calendar systems.
The default for the ISO 8601 calendar is the first leap year after the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time).
@@ -31,6 +31,10 @@ A `Temporal.PlainMonthDay` can be converted into a `Temporal.PlainDate` by combi
> When creating instances for non-ISO-8601 calendars (except when implementing a custom calendar) use the `from()` method which will automatically set a valid and `equals`-compatible reference year.
All values are given as reckoned in the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates).
+Together, `referenceISOYear`, `isoMonth`, and `isoDay` must represent a valid date in that calendar, even if you are passing a different calendar as the `calendar` parameter.
+
+Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
+Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
The `referenceISOYear` ensures that month/day combinations like February 29 (a leap day in the ISO 8601 calendar) or 15 Adar I (in a leap month in the Hebrew calendar) can be used for `Temporal.PlainMonthDay`, even though those dates don't occur every calendar year.
`referenceISOYear` corresponds to a calendar year where this month and day actually exist.
@@ -162,9 +166,10 @@ md.month; // => undefined
// (no `month` property; use `monthCode` instead)
```
-### monthDay.**calendar** : object
+### monthDay.**calendarId** : object
-The `calendar` read-only property gives the calendar that the `monthCode` and `day` properties are interpreted in.
+The `calendarId` read-only property gives the calendar that the `monthCode` and `day` properties are interpreted in.
+If `monthDay` was created with a custom calendar object, this gives the `id` property of that object.
## Methods
@@ -384,9 +389,16 @@ md = Temporal.PlainMonthDay.from({
date = md.toPlainDate({ era: 'reiwa', eraYear: 2 }); // => 2020-01-01[u-ca=japanese]
```
-### monthDay.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: object }
+### monthDay.**getCalendar**(): object
+
+**Returns:** a `Temporal.Calendar` instance or plain object representing the calendar in which `monthDay` is reckoned.
+
+This method is mainly useful if you need an object on which to call calendar methods.
+Most code will not need to use it.
+
+### monthDay.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: string | object }
-**Returns:** a plain object with properties expressing `monthDay` in the ISO 8601 calendar, as well as the value of `monthDay.calendar`.
+**Returns:** a plain object with properties expressing `monthDay` in the ISO 8601 calendar, as well as the calendar (usually a string, but may be an object) in which `monthDay` is reckoned.
This method is mainly useful if you are implementing a custom calendar.
Most code will not need to use it.
diff --git a/docs/plainyearmonth.md b/docs/plainyearmonth.md
index 038571cc8f..556bbd4f3c 100644
--- a/docs/plainyearmonth.md
+++ b/docs/plainyearmonth.md
@@ -13,13 +13,13 @@ A `Temporal.PlainYearMonth` can be converted into a `Temporal.PlainDate` by comb
## Constructor
-### **new Temporal.PlainYearMonth**(_isoYear_: number, _isoMonth_: number, _calendar_?: string | object, _referenceISODay_: number = 1) : Temporal.PlainYearMonth
+### **new Temporal.PlainYearMonth**(_isoYear_: number, _isoMonth_: number, _calendar_: string | object = "iso8601", _referenceISODay_: number = 1) : Temporal.PlainYearMonth
**Parameters:**
- `isoYear` (number): A year.
- `isoMonth` (number): A month, ranging between 1 and 12 inclusive.
-- `calendar` (optional `Temporal.Calendar`, plain object, or string): A calendar to project the month into.
+- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): A calendar to project the month into.
- `referenceISODay` (optional for ISO 8601 calendar; required for other calendars): A reference day, used for disambiguation when implementing calendar systems.
For the ISO 8601 calendar, this parameter will default to 1 if omitted.
For other calendars, the must set this parameter to the ISO-calendar day corresponding to the first day of the desired calendar year and month.
@@ -35,10 +35,14 @@ A `Temporal.PlainYearMonth` can be converted into a `Temporal.PlainDate` by comb
**Returns:** a new `Temporal.PlainYearMonth` object.
All values are given as reckoned in the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates).
+Together, `isoYear`, `isoMonth`, and `referenceISODay` must represent a valid date in that calendar, even if you are passing a different calendar as the `calendar` parameter.
The range of allowed values for this type is exactly enough that calling [`toPlainYearMonth()`](./plaindate.md#toPlainYearMonth) on any valid `Temporal.PlainDate` will succeed.
If `isoYear` and `isoMonth` are outside of this range, then this function will throw a `RangeError`.
+Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
+Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
+
> **NOTE**: The `isoMonth` argument ranges from 1 to 12, which is different from legacy `Date` where months are represented by zero-based indices (0 to 11).
Usage examples:
@@ -69,7 +73,7 @@ If the value is another `Temporal.PlainYearMonth` object, a new object represent
If the value is any other object, it must have `year` (or `era` and `eraYear`), `month` (or `monthCode`) properties, and optionally a `calendar` property.
A `Temporal.PlainYearMonth` will be constructed from these properties.
-If the `calendar` property is not present, it's assumed to be `Temporal.Calendar.from('iso8601')`, the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates).
+If the `calendar` property is not present, it's assumed to be `'iso8601'` (identifying the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates)).
In this calendar, `era` is ignored.
Any non-object value is converted to a string, which is expected to be in ISO 8601 format.
@@ -185,9 +189,10 @@ ym.month; // => 6
ym.monthCode; // => 'M05L'
```
-### yearMonth.**calendar** : object
+### yearMonth.**calendarId** : object
-The `calendar` read-only property gives the calendar that the `year` and `month` properties are interpreted in.
+The `calendarId` read-only property gives the identifier of the calendar that the `year`, `month`, and `monthCode` properties are interpreted in.
+If `yearMonth` was created with a custom calendar object, this gives the `id` property of that project.
### yearMonth.**era** : string | undefined
@@ -632,9 +637,16 @@ ym = Temporal.PlainYearMonth.from('2019-06');
ym.toPlainDate({ day: 24 }); // => 2019-06-24
```
-### yearMonth.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: object }
+### yearMonth.**getCalendar**(): object
+
+**Returns:** a `Temporal.Calendar` instance or plain object representing the calendar in which `yearMonth` is reckoned.
+
+This method is mainly useful if you need an object on which to call calendar methods.
+Most code will not need to use it.
+
+### yearMonth.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, calendar: string | object }
-**Returns:** a plain object with properties expressing `yearMonth` in the ISO 8601 calendar, as well as the value of `yearMonth.calendar`.
+**Returns:** a plain object with properties expressing `yearMonth` in the ISO 8601 calendar, as well as the calendar (usually a string, but may be an object) that `yearMonth` is reckoned in.
This method is mainly useful if you are implementing a custom calendar.
Most code will not need to use it.
diff --git a/docs/zoneddatetime.md b/docs/zoneddatetime.md
index b5b029557d..756b85b31a 100644
--- a/docs/zoneddatetime.md
+++ b/docs/zoneddatetime.md
@@ -25,13 +25,13 @@ The `Temporal.ZonedDateTime` API is a superset of `Temporal.PlainDateTime`, whic
## Constructor
-### **new Temporal.ZonedDateTime**(_epochNanoseconds_: bigint, _timeZone_: string | object, _calendar_?: string | object) : Temporal.ZonedDateTime
+### **new Temporal.ZonedDateTime**(_epochNanoseconds_: bigint, _timeZone_: string | object, _calendar_: string | object = "iso8601") : Temporal.ZonedDateTime
**Parameters:**
- `epochNanoseconds` (bigint): A number of nanoseconds.
- `timeZone` (`Temporal.TimeZone` or plain object): The time zone in which the event takes place.
-- `calendar` (optional `Temporal.Calendar`, plain object, or string): Calendar used to interpret dates and times. Usually set to `'iso8601'`.
+- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): Calendar used to interpret dates and times.
**Returns:** a new `Temporal.ZonedDateTime` object.
@@ -41,12 +41,15 @@ Instead of the constructor, `Temporal.ZonedDateTime.from()` is preferred instead
The range of allowed values for this type is the same as the old-style JavaScript `Date`: 100 million (108) days before or after the Unix epoch.
This range covers approximately half a million years. If `epochNanoseconds` is outside of this range, a `RangeError` will be thrown.
+Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
+Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
+
Usage examples:
```javascript
// UNIX epoch in California
-new Temporal.ZonedDateTime(0n, Temporal.TimeZone.from('America/Los_Angeles'), Temporal.Calendar.from('iso8601'));
+new Temporal.ZonedDateTime(0n, Temporal.TimeZone.from('America/Los_Angeles'), 'iso8601');
// => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
new Temporal.ZonedDateTime(0n, 'America/Los_Angeles');
// => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
@@ -78,7 +81,7 @@ This static method creates a new `Temporal.ZonedDateTime` object from another va
If the value is another `Temporal.ZonedDateTime` object, a new but otherwise identical object will be returned.
If the value is any other object, a `Temporal.ZonedDateTime` will be constructed from the values of any `timeZone`, `year` (or `era` and `eraYear`), `month` (or `monthCode`), `day`, `hour`, `minute`, `second`, `millisecond`, `microsecond`, `nanosecond`, and/or `calendar` properties that are present.
At least the `timeZone`, `year` (or `era` and `eraYear`), `month` (or `monthCode`), and `day` properties must be present. Other properties are optional.
-If `calendar` is missing, it will be assumed to be `Temporal.Calendar.from('iso8601')`.
+If `calendar` is missing, it will be assumed to be `'iso8601'` (identifying the [ISO 8601 calendar](https://en.wikipedia.org/wiki/ISO_8601#Dates)).
Any other missing properties will be assumed to be 0 (for time fields).
Date/time values will be interpreted in context of the provided offset and/or time zone, depending on the `offset` option.
@@ -390,9 +393,11 @@ epochNanos = zdt.epochNanoseconds;
```
-### zonedDateTime.**calendar** : object
+### zonedDateTime.**calendarId** : object
+
+The `calendarId` read-only property gives the identifier of the calendar used to calculate date/time field values.
+If the date was created with a custom calendar object, this gives the `id` property of that object.
-The `calendar` read-only property gives the calendar used to calculate date/time field values.
Calendar-sensitive values are used in most places, including:
- Accessing properties like `.year` or `.month`
@@ -1433,9 +1438,16 @@ zdt.toPlainMonthDay(); // => 12-07
zdt.toPlainTime(); // => 03:24:30
```
-### zonedDateTime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, hour: number, minute: number, second: number, millisecond: number, microsecond: number, nanosecond: number, offset: string, timeZone: object, calendar: object }
+### zonedDateTime.**getCalendar**(): object
+
+**Returns:** a `Temporal.Calendar` instance or plain object representing the calendar in which `zonedDateTime` is reckoned.
+
+This method is mainly useful if you need an object on which to call calendar methods.
+Most code will not need to use it.
+
+### zonedDateTime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, hour: number, minute: number, second: number, millisecond: number, microsecond: number, nanosecond: number, offset: string, timeZone: object, calendar: string | object }
-**Returns:** a plain object with properties expressing `zonedDateTime` in the ISO 8601 calendar, including all date/time fields as well as the `calendar`, `timeZone`, and `offset` properties.
+**Returns:** a plain object with properties expressing `zonedDateTime` in the ISO 8601 calendar, including all date/time fields as well as the `timeZone`, and `offset` properties, and the calendar in which `zonedDateTime` is reckoned.
This is an advanced method that's mainly useful if you are implementing a custom calendar.
Most developers will not need to use it.
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index f6179bfea7..22bd600c1a 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -776,7 +776,7 @@ export namespace Temporal {
isoYear: number;
isoMonth: number;
isoDay: number;
- calendar: CalendarProtocol;
+ calendar: string | CalendarProtocol;
};
/**
@@ -801,7 +801,7 @@ export namespace Temporal {
readonly month: number;
readonly monthCode: string;
readonly day: number;
- readonly calendar: CalendarProtocol;
+ readonly calendarId: string;
readonly dayOfWeek: number;
readonly dayOfYear: number;
readonly weekOfYear: number;
@@ -835,6 +835,7 @@ export namespace Temporal {
): Temporal.ZonedDateTime;
toPlainYearMonth(): Temporal.PlainYearMonth;
toPlainMonthDay(): Temporal.PlainMonthDay;
+ getCalendar(): CalendarProtocol;
getISOFields(): PlainDateISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
@@ -869,7 +870,7 @@ export namespace Temporal {
isoMillisecond: number;
isoMicrosecond: number;
isoNanosecond: number;
- calendar: CalendarProtocol;
+ calendar: string | CalendarProtocol;
};
/**
@@ -915,7 +916,7 @@ export namespace Temporal {
readonly millisecond: number;
readonly microsecond: number;
readonly nanosecond: number;
- readonly calendar: CalendarProtocol;
+ readonly calendarId: string;
readonly dayOfWeek: number;
readonly dayOfYear: number;
readonly weekOfYear: number;
@@ -954,6 +955,7 @@ export namespace Temporal {
toPlainYearMonth(): Temporal.PlainYearMonth;
toPlainMonthDay(): Temporal.PlainMonthDay;
toPlainTime(): Temporal.PlainTime;
+ getCalendar(): CalendarProtocol;
getISOFields(): PlainDateTimeISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
@@ -987,10 +989,11 @@ export namespace Temporal {
constructor(isoMonth: number, isoDay: number, calendar?: CalendarLike, referenceISOYear?: number);
readonly monthCode: string;
readonly day: number;
- readonly calendar: CalendarProtocol;
+ readonly calendarId: string;
equals(other: Temporal.PlainMonthDay | PlainMonthDayLike | string): boolean;
with(monthDayLike: PlainMonthDayLike, options?: AssignmentOptions): Temporal.PlainMonthDay;
toPlainDate(year: { year: number }): Temporal.PlainDate;
+ getCalendar(): CalendarProtocol;
getISOFields(): PlainDateISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
@@ -1168,7 +1171,7 @@ export namespace Temporal {
readonly year: number;
readonly month: number;
readonly monthCode: string;
- readonly calendar: CalendarProtocol;
+ readonly calendarId: string;
readonly daysInMonth: number;
readonly daysInYear: number;
readonly monthsInYear: number;
@@ -1189,6 +1192,7 @@ export namespace Temporal {
options?: DifferenceOptions<'year' | 'month'>
): Temporal.Duration;
toPlainDate(day: { day: number }): Temporal.PlainDate;
+ getCalendar(): CalendarProtocol;
getISOFields(): PlainDateISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
@@ -1227,7 +1231,7 @@ export namespace Temporal {
isoNanosecond: number;
offset: string;
timeZone: TimeZoneProtocol;
- calendar: CalendarProtocol;
+ calendar: string | CalendarProtocol;
};
export class ZonedDateTime {
@@ -1253,7 +1257,7 @@ export namespace Temporal {
readonly microsecond: number;
readonly nanosecond: number;
readonly timeZone: TimeZoneProtocol;
- readonly calendar: CalendarProtocol;
+ readonly calendarId: string;
readonly dayOfWeek: number;
readonly dayOfYear: number;
readonly weekOfYear: number;
@@ -1302,6 +1306,7 @@ export namespace Temporal {
toPlainYearMonth(): Temporal.PlainYearMonth;
toPlainMonthDay(): Temporal.PlainMonthDay;
toPlainTime(): Temporal.PlainTime;
+ getCalendar(): CalendarProtocol;
getISOFields(): ZonedDateTimeISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs
index bfec5884d5..f11fbf2ff4 100644
--- a/polyfill/lib/calendar.mjs
+++ b/polyfill/lib/calendar.mjs
@@ -69,19 +69,22 @@ export class Calendar {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
if (ES.Type(fields) !== 'Object') throw new TypeError('invalid fields');
options = ES.GetOptionsObject(options);
- return impl[GetSlot(this, CALENDAR_ID)].dateFromFields(fields, options, this);
+ const id = GetSlot(this, CALENDAR_ID);
+ return impl[id].dateFromFields(fields, options, id);
}
yearMonthFromFields(fields, options = undefined) {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
if (ES.Type(fields) !== 'Object') throw new TypeError('invalid fields');
options = ES.GetOptionsObject(options);
- return impl[GetSlot(this, CALENDAR_ID)].yearMonthFromFields(fields, options, this);
+ const id = GetSlot(this, CALENDAR_ID);
+ return impl[id].yearMonthFromFields(fields, options, id);
}
monthDayFromFields(fields, options = undefined) {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
if (ES.Type(fields) !== 'Object') throw new TypeError('invalid fields');
options = ES.GetOptionsObject(options);
- return impl[GetSlot(this, CALENDAR_ID)].monthDayFromFields(fields, options, this);
+ const id = GetSlot(this, CALENDAR_ID);
+ return impl[id].monthDayFromFields(fields, options, id);
}
fields(fields) {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
@@ -143,14 +146,15 @@ export class Calendar {
GetSlot(duration, NANOSECONDS),
'day'
);
- return impl[GetSlot(this, CALENDAR_ID)].dateAdd(
+ const id = GetSlot(this, CALENDAR_ID);
+ return impl[id].dateAdd(
date,
GetSlot(duration, YEARS),
GetSlot(duration, MONTHS),
GetSlot(duration, WEEKS),
days,
overflow,
- this
+ id
);
}
dateUntil(one, two, options = undefined) {
@@ -249,31 +253,54 @@ export class Calendar {
return ES.ToString(this);
}
static from(item) {
- return ES.ToTemporalCalendar(item);
+ const calendarSlotValue = ES.ToTemporalCalendar(item);
+ return ES.ToTemporalCalendarObject(calendarSlotValue);
}
}
MakeIntrinsicClass(Calendar, 'Temporal.Calendar');
DefineIntrinsic('Temporal.Calendar.from', Calendar.from);
+DefineIntrinsic('Temporal.Calendar.prototype.dateAdd', Calendar.prototype.dateAdd);
+DefineIntrinsic('Temporal.Calendar.prototype.dateFromFields', Calendar.prototype.dateFromFields);
+DefineIntrinsic('Temporal.Calendar.prototype.dateUntil', Calendar.prototype.dateUntil);
+DefineIntrinsic('Temporal.Calendar.prototype.day', Calendar.prototype.day);
+DefineIntrinsic('Temporal.Calendar.prototype.dayOfWeek', Calendar.prototype.dayOfWeek);
+DefineIntrinsic('Temporal.Calendar.prototype.dayOfYear', Calendar.prototype.dayOfYear);
+DefineIntrinsic('Temporal.Calendar.prototype.daysInMonth', Calendar.prototype.daysInMonth);
+DefineIntrinsic('Temporal.Calendar.prototype.daysInWeek', Calendar.prototype.daysInWeek);
+DefineIntrinsic('Temporal.Calendar.prototype.daysInYear', Calendar.prototype.daysInYear);
+DefineIntrinsic('Temporal.Calendar.prototype.era', Calendar.prototype.era);
+DefineIntrinsic('Temporal.Calendar.prototype.eraYear', Calendar.prototype.eraYear);
+DefineIntrinsic('Temporal.Calendar.prototype.fields', Calendar.prototype.fields);
+DefineIntrinsic('Temporal.Calendar.prototype.inLeapYear', Calendar.prototype.inLeapYear);
+DefineIntrinsic('Temporal.Calendar.prototype.mergeFields', Calendar.prototype.mergeFields);
+DefineIntrinsic('Temporal.Calendar.prototype.month', Calendar.prototype.month);
+DefineIntrinsic('Temporal.Calendar.prototype.monthCode', Calendar.prototype.monthCode);
+DefineIntrinsic('Temporal.Calendar.prototype.monthDayFromFields', Calendar.prototype.monthDayFromFields);
+DefineIntrinsic('Temporal.Calendar.prototype.monthsInYear', Calendar.prototype.monthsInYear);
+DefineIntrinsic('Temporal.Calendar.prototype.weekOfYear', Calendar.prototype.weekOfYear);
+DefineIntrinsic('Temporal.Calendar.prototype.year', Calendar.prototype.year);
+DefineIntrinsic('Temporal.Calendar.prototype.yearMonthFromFields', Calendar.prototype.yearMonthFromFields);
+DefineIntrinsic('Temporal.Calendar.prototype.yearOfWeek', Calendar.prototype.yearOfWeek);
impl['iso8601'] = {
- dateFromFields(fields, options, calendar) {
+ dateFromFields(fields, options, calendarSlotValue) {
fields = ES.PrepareTemporalFields(fields, ['day', 'month', 'monthCode', 'year'], ['year', 'day']);
const overflow = ES.ToTemporalOverflow(options);
fields = resolveNonLunisolarMonth(fields);
let { year, month, day } = fields;
({ year, month, day } = ES.RegulateISODate(year, month, day, overflow));
- return ES.CreateTemporalDate(year, month, day, calendar);
+ return ES.CreateTemporalDate(year, month, day, calendarSlotValue);
},
- yearMonthFromFields(fields, options, calendar) {
+ yearMonthFromFields(fields, options, calendarSlotValue) {
fields = ES.PrepareTemporalFields(fields, ['month', 'monthCode', 'year'], ['year']);
const overflow = ES.ToTemporalOverflow(options);
fields = resolveNonLunisolarMonth(fields);
let { year, month } = fields;
({ year, month } = ES.RegulateISOYearMonth(year, month, overflow));
- return ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ 1);
+ return ES.CreateTemporalYearMonth(year, month, calendarSlotValue, /* referenceISODay = */ 1);
},
- monthDayFromFields(fields, options, calendar) {
+ monthDayFromFields(fields, options, calendarSlotValue) {
fields = ES.PrepareTemporalFields(fields, ['day', 'month', 'monthCode', 'year'], ['day']);
const overflow = ES.ToTemporalOverflow(options);
if (fields.month !== undefined && fields.year === undefined && fields.monthCode === undefined) {
@@ -284,7 +311,7 @@ impl['iso8601'] = {
fields = resolveNonLunisolarMonth(fields);
let { month, day, year } = fields;
({ month, day } = ES.RegulateISODate(useYear ? year : referenceISOYear, month, day, overflow));
- return ES.CreateTemporalMonthDay(month, day, calendar, referenceISOYear);
+ return ES.CreateTemporalMonthDay(month, day, calendarSlotValue, referenceISOYear);
},
fields(fields) {
return fields;
@@ -302,12 +329,12 @@ impl['iso8601'] = {
}
return [...ES.Call(SetPrototypeValues, result, [])];
},
- dateAdd(date, years, months, weeks, days, overflow, calendar) {
+ dateAdd(date, years, months, weeks, days, overflow, calendarSlotValue) {
let year = GetSlot(date, ISO_YEAR);
let month = GetSlot(date, ISO_MONTH);
let day = GetSlot(date, ISO_DAY);
({ year, month, day } = ES.AddISODate(year, month, day, years, months, weeks, days, overflow));
- return ES.CreateTemporalDate(year, month, day, calendar);
+ return ES.CreateTemporalDate(year, month, day, calendarSlotValue);
},
dateUntil(one, two, largestUnit) {
return ES.DifferenceISODate(
@@ -1894,27 +1921,27 @@ const helperDangi = ObjectAssign({}, { ...helperChinese, id: 'dangi' });
* ISO and non-ISO implementations vs. code that was very different.
*/
const nonIsoGeneralImpl = {
- dateFromFields(fields, options, calendar) {
+ dateFromFields(fields, options, calendarSlotValue) {
const cache = new OneObjectCache();
const fieldNames = this.fields(['day', 'month', 'monthCode', 'year']);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const overflow = ES.ToTemporalOverflow(options);
const { year, month, day } = this.helper.calendarToIsoDate(fields, overflow, cache);
- const result = ES.CreateTemporalDate(year, month, day, calendar);
+ const result = ES.CreateTemporalDate(year, month, day, calendarSlotValue);
cache.setObject(result);
return result;
},
- yearMonthFromFields(fields, options, calendar) {
+ yearMonthFromFields(fields, options, calendarSlotValue) {
const cache = new OneObjectCache();
const fieldNames = this.fields(['month', 'monthCode', 'year']);
fields = ES.PrepareTemporalFields(fields, fieldNames, []);
const overflow = ES.ToTemporalOverflow(options);
const { year, month, day } = this.helper.calendarToIsoDate({ ...fields, day: 1 }, overflow, cache);
- const result = ES.CreateTemporalYearMonth(year, month, calendar, /* referenceISODay = */ day);
+ const result = ES.CreateTemporalYearMonth(year, month, calendarSlotValue, /* referenceISODay = */ day);
cache.setObject(result);
return result;
},
- monthDayFromFields(fields, options, calendar) {
+ monthDayFromFields(fields, options, calendarSlotValue) {
const cache = new OneObjectCache();
// For lunisolar calendars, either `monthCode` or `year` must be provided
// because `month` is ambiguous without a year or a code.
@@ -1923,7 +1950,7 @@ const nonIsoGeneralImpl = {
const overflow = ES.ToTemporalOverflow(options);
const { year, month, day } = this.helper.monthDayFromFields(fields, overflow, cache);
// `year` is a reference year where this month/day exists in this calendar
- const result = ES.CreateTemporalMonthDay(month, day, calendar, /* referenceISOYear = */ year);
+ const result = ES.CreateTemporalMonthDay(month, day, calendarSlotValue, /* referenceISOYear = */ year);
cache.setObject(result);
return result;
},
@@ -1974,13 +2001,13 @@ const nonIsoGeneralImpl = {
}
return [...ES.Call(SetPrototypeValues, result, [])];
},
- dateAdd(date, years, months, weeks, days, overflow, calendar) {
+ dateAdd(date, years, months, weeks, days, overflow, calendarSlotValue) {
const cache = OneObjectCache.getCacheForObject(date);
const calendarDate = this.helper.temporalToCalendarDate(date, cache);
const added = this.helper.addCalendar(calendarDate, { years, months, weeks, days }, overflow, cache);
const isoAdded = this.helper.calendarToIsoDate(added, 'constrain', cache);
const { year, month, day } = isoAdded;
- const newTemporalObject = ES.CreateTemporalDate(year, month, day, calendar);
+ const newTemporalObject = ES.CreateTemporalDate(year, month, day, calendarSlotValue);
// The new object's cache starts with the cache of the old object
const newCache = new OneObjectCache(cache);
newCache.setObject(newTemporalObject);
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index f39c1af3dd..a92778593a 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -341,7 +341,7 @@ export const ES = ObjectAssign({}, ES2022, {
},
MaybeFormatCalendarAnnotation: (calendar, showCalendar) => {
if (showCalendar === 'never') return '';
- return ES.FormatCalendarAnnotation(ES.ToString(calendar), showCalendar);
+ return ES.FormatCalendarAnnotation(ES.ToString(ES.ToTemporalCalendarObject(calendar)), showCalendar);
},
FormatCalendarAnnotation: (id, showCalendar) => {
if (showCalendar === 'never') return '';
@@ -1562,6 +1562,11 @@ export const ES = ObjectAssign({}, ES2022, {
return new TemporalCalendar('iso8601');
},
CalendarFields: (calendar, fieldNames) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.fields%'), calendar, [fieldNames]);
+ }
const fields = ES.GetMethod(calendar, 'fields');
fieldNames = ES.Call(fields, calendar, [fieldNames]);
const result = [];
@@ -1572,12 +1577,22 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarMergeFields: (calendar, fields, additionalFields) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.mergeFields%'), calendar, [fields, additionalFields]);
+ }
const mergeFields = ES.GetMethod(calendar, 'mergeFields');
const result = ES.Call(mergeFields, calendar, [fields, additionalFields]);
if (ES.Type(result) !== 'Object') throw new TypeError('bad return from calendar.mergeFields()');
return result;
},
CalendarDateAdd: (calendar, date, duration, options, dateAdd) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.dateAdd%'), calendar, [date, duration, options]);
+ }
if (dateAdd === undefined) {
dateAdd = ES.GetMethod(calendar, 'dateAdd');
}
@@ -1586,6 +1601,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDateUntil: (calendar, date, otherDate, options, dateUntil) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.dateUntil%'), calendar, [date, otherDate, options]);
+ }
if (dateUntil === undefined) {
dateUntil = ES.GetMethod(calendar, 'dateUntil');
}
@@ -1594,6 +1614,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.year%'), calendar, [dateLike]);
+ }
const year = ES.GetMethod(calendar, 'year');
const result = ES.Call(year, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1605,6 +1630,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarMonth: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.month%'), calendar, [dateLike]);
+ }
const month = ES.GetMethod(calendar, 'month');
const result = ES.Call(month, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1616,6 +1646,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarMonthCode: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.monthCode%'), calendar, [dateLike]);
+ }
const monthCode = ES.GetMethod(calendar, 'monthCode');
const result = ES.Call(monthCode, calendar, [dateLike]);
if (typeof result !== 'string') {
@@ -1624,6 +1659,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDay: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.day%'), calendar, [dateLike]);
+ }
const day = ES.GetMethod(calendar, 'day');
const result = ES.Call(day, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1635,6 +1675,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarEra: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.era%'), calendar, [dateLike]);
+ }
const era = ES.GetMethod(calendar, 'era');
let result = ES.Call(era, calendar, [dateLike]);
if (result === undefined) {
@@ -1646,6 +1691,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarEraYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.eraYear%'), calendar, [dateLike]);
+ }
const eraYear = ES.GetMethod(calendar, 'eraYear');
let result = ES.Call(eraYear, calendar, [dateLike]);
if (result === undefined) {
@@ -1660,6 +1710,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDayOfWeek: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.dayOfWeek%'), calendar, [dateLike]);
+ }
const dayOfWeek = ES.GetMethod(calendar, 'dayOfWeek');
const result = ES.Call(dayOfWeek, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1671,6 +1726,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDayOfYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.dayOfYear%'), calendar, [dateLike]);
+ }
const dayOfYear = ES.GetMethod(calendar, 'dayOfYear');
const result = ES.Call(dayOfYear, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1682,6 +1742,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarWeekOfYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.weekOfYear%'), calendar, [dateLike]);
+ }
const weekOfYear = ES.GetMethod(calendar, 'weekOfYear');
const result = ES.Call(weekOfYear, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1693,6 +1758,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarYearOfWeek: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.yearOfWeek%'), calendar, [dateLike]);
+ }
const yearOfWeek = ES.GetMethod(calendar, 'yearOfWeek');
const result = ES.Call(yearOfWeek, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1704,6 +1774,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDaysInWeek: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.daysInWeek%'), calendar, [dateLike]);
+ }
const daysInWeek = ES.GetMethod(calendar, 'daysInWeek');
const result = ES.Call(daysInWeek, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1715,6 +1790,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDaysInMonth: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.daysInMonth%'), calendar, [dateLike]);
+ }
const daysInMonth = ES.GetMethod(calendar, 'daysInMonth');
const result = ES.Call(daysInMonth, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1726,6 +1806,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarDaysInYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.daysInYear%'), calendar, [dateLike]);
+ }
const daysInYear = ES.GetMethod(calendar, 'daysInYear');
const result = ES.Call(daysInYear, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1737,6 +1822,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarMonthsInYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.monthsInYear%'), calendar, [dateLike]);
+ }
const monthsInYear = ES.GetMethod(calendar, 'monthsInYear');
const result = ES.Call(monthsInYear, calendar, [dateLike]);
if (typeof result !== 'number') {
@@ -1748,6 +1838,11 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
CalendarInLeapYear: (calendar, dateLike) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.inLeapYear%'), calendar, [dateLike]);
+ }
const inLeapYear = ES.GetMethod(calendar, 'inLeapYear');
const result = ES.Call(inLeapYear, calendar, [dateLike]);
if (typeof result !== 'boolean') {
@@ -1779,8 +1874,7 @@ export const ES = ObjectAssign({}, ES2022, {
}
}
const identifier = ES.ToString(calendarLike);
- const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
- if (ES.IsBuiltinCalendar(identifier)) return new TemporalCalendar(identifier);
+ if (ES.IsBuiltinCalendar(identifier)) return ES.ASCIILowercase(identifier);
let calendar;
try {
({ calendar } = ES.ParseISODateTime(identifier));
@@ -1792,7 +1886,8 @@ export const ES = ObjectAssign({}, ES2022, {
}
}
if (!calendar) calendar = 'iso8601';
- return new TemporalCalendar(calendar);
+ if (!ES.IsBuiltinCalendar(calendar)) throw new RangeError(`invalid calendar identifier ${calendar}`);
+ return ES.ASCIILowercase(calendar);
},
GetTemporalCalendarWithISODefault: (item) => {
if (HasSlot(item, CALENDAR)) return GetSlot(item, CALENDAR);
@@ -1800,6 +1895,17 @@ export const ES = ObjectAssign({}, ES2022, {
if (calendar === undefined) return ES.GetISO8601Calendar();
return ES.ToTemporalCalendar(calendar);
},
+ ToTemporalCalendarIdentifier: (slotValue) => {
+ if (typeof slotValue === 'string') return slotValue;
+ const result = slotValue.id;
+ if (typeof result !== 'string') throw new TypeError('calendar.id should be a string');
+ return result;
+ },
+ ToTemporalCalendarObject: (slotValue) => {
+ if (ES.Type(slotValue) === 'Object') return slotValue;
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ return new TemporalCalendar(slotValue);
+ },
CalendarEquals: (one, two) => {
if (one === two) return true;
const cal1 = ES.ToString(one);
@@ -1831,18 +1937,33 @@ export const ES = ObjectAssign({}, ES2022, {
}
},
CalendarDateFromFields: (calendar, fields, options) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.dateFromFields%'), calendar, [fields, options]);
+ }
const dateFromFields = ES.GetMethod(calendar, 'dateFromFields');
const result = ES.Call(dateFromFields, calendar, [fields, options]);
if (!ES.IsTemporalDate(result)) throw new TypeError('invalid result');
return result;
},
CalendarYearMonthFromFields: (calendar, fields, options) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.yearMonthFromFields%'), calendar, [fields, options]);
+ }
const yearMonthFromFields = ES.GetMethod(calendar, 'yearMonthFromFields');
const result = ES.Call(yearMonthFromFields, calendar, [fields, options]);
if (!ES.IsTemporalYearMonth(result)) throw new TypeError('invalid result');
return result;
},
CalendarMonthDayFromFields: (calendar, fields, options) => {
+ if (typeof calendar === 'string') {
+ const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
+ calendar = new TemporalCalendar(calendar);
+ return ES.Call(GetIntrinsic('%Temporal.Calendar.prototype.monthDayFromFields%'), calendar, [fields, options]);
+ }
const monthDayFromFields = ES.GetMethod(calendar, 'monthDayFromFields');
const result = ES.Call(monthDayFromFields, calendar, [fields, options]);
if (!ES.IsTemporalMonthDay(result)) throw new TypeError('invalid result');
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 821de329c8..8dbf88fce8 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -25,9 +25,9 @@ export class PlainDate {
ES.CreateTemporalDateSlots(this, isoYear, isoMonth, isoDay, calendar);
}
- get calendar() {
+ get calendarId() {
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
+ return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
get era() {
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
@@ -269,6 +269,11 @@ export class PlainDate {
isoYear: GetSlot(this, ISO_YEAR)
};
}
+ getCalendar() {
+ if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
+ }
+
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
if (ES.IsTemporalDate(item)) {
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index 0e86adee7f..a09871d3a1 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -57,9 +57,9 @@ export class PlainDateTime {
calendar
);
}
- get calendar() {
+ get calendarId() {
if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
+ return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
get year() {
if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
@@ -423,6 +423,10 @@ export class PlainDateTime {
isoYear: GetSlot(this, ISO_YEAR)
};
}
+ getCalendar() {
+ if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
+ }
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
diff --git a/polyfill/lib/plainmonthday.mjs b/polyfill/lib/plainmonthday.mjs
index ba7cee7d93..200aa0cf5d 100644
--- a/polyfill/lib/plainmonthday.mjs
+++ b/polyfill/lib/plainmonthday.mjs
@@ -26,9 +26,9 @@ export class PlainMonthDay {
if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
return ES.CalendarDay(GetSlot(this, CALENDAR), this);
}
- get calendar() {
+ get calendarId() {
if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
+ return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
with(temporalMonthDayLike, options = undefined) {
@@ -111,6 +111,11 @@ export class PlainMonthDay {
isoYear: GetSlot(this, ISO_YEAR)
};
}
+ getCalendar() {
+ if (!ES.IsTemporalMonthDay(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
+ }
+
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
if (ES.IsTemporalMonthDay(item)) {
diff --git a/polyfill/lib/plainyearmonth.mjs b/polyfill/lib/plainyearmonth.mjs
index 8f0630e9d9..0ff3d8f862 100644
--- a/polyfill/lib/plainyearmonth.mjs
+++ b/polyfill/lib/plainyearmonth.mjs
@@ -29,9 +29,9 @@ export class PlainYearMonth {
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
return ES.CalendarMonthCode(GetSlot(this, CALENDAR), this);
}
- get calendar() {
+ get calendarId() {
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
+ return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
get era() {
if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
@@ -153,6 +153,11 @@ export class PlainYearMonth {
isoYear: GetSlot(this, ISO_YEAR)
};
}
+ getCalendar() {
+ if (!ES.IsTemporalYearMonth(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
+ }
+
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
if (ES.IsTemporalYearMonth(item)) {
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 3969aa1d46..d0f2ab3526 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -38,9 +38,9 @@ export class ZonedDateTime {
ES.CreateTemporalZonedDateTimeSlots(this, epochNanoseconds, timeZone, calendar);
}
- get calendar() {
+ get calendarId() {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, CALENDAR);
+ return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
get timeZone() {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
@@ -522,6 +522,11 @@ export class ZonedDateTime {
timeZone: tz
};
}
+ getCalendar() {
+ if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
+ }
+
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
if (ES.IsTemporalZonedDateTime(item)) {
diff --git a/spec/calendar.html b/spec/calendar.html
index 6e05cd62f9..06cae60e80 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -104,7 +104,7 @@ GetISO8601Calendar ( )
CalendarFields (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_fieldNames_: a List of Strings,
): either a normal completion containing a List of Strings, or a throw completion
@@ -113,7 +113,9 @@
It calls the `fields` method of the given _calendar_ with an array representation of _fieldNames_, and returns a List representation of the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.fields%, _calendar_, « CreateArrayFromList(_fieldNames_) »).
1. Let _fieldsArray_ be ? Invoke(_calendar_, *"fields"*, « CreateArrayFromList(_fieldNames_) »).
1. Return ? IterableToListOfType(_fieldsArray_, « String »).
@@ -122,7 +124,7 @@
CalendarMergeFields (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_fields_: an Object,
_additionalFields_: an Object,
): either a normal completion containing an Object, or a throw completion
@@ -132,7 +134,9 @@
It merges the properties of _fields_ and _additionalFields_ by calling the `mergeFields` method of the given _calendar_.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.mergeFields%, _calendar_, « _fields_, _additionalFields_ »).
1. Let _result_ be ? Invoke(_calendar_, *"mergeFields"*, « _fields_, _additionalFields_ »).
1. If Type(_result_) is not Object, throw a *TypeError* exception.
1. Return _result_.
@@ -142,7 +146,7 @@
CalendarDateAdd (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_date_: a Temporal.PlainDate,
_duration_: a Temporal.Duration,
optional _options_: an Object or *undefined*,
@@ -152,14 +156,16 @@
1. If _options_ is not present, set _options_ to *undefined*.
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.dateAdd%, _calendar_, « _date_, _duration_, _options_ »).
1. If _dateAdd_ is not present, set _dateAdd_ to ? GetMethod(_calendar_, *"dateAdd"*).
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
1. Let _addedDate_ be ? Call(_dateAdd_, _calendar_, « _date_, _duration_, _options_ »).
1. Perform ? RequireInternalSlot(_addedDate_, [[InitializedTemporalDate]]).
1. Return _addedDate_.
@@ -169,7 +175,7 @@
CalendarDateUntil (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_one_: a Temporal.PlainDate,
_two_: a Temporal.PlainDate,
_options_: an Object or *undefined*,
@@ -179,13 +185,15 @@
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.dateUntil%, _calendar_, « _one_, _two_, _options_ »).
1. If _dateUntil_ is not present, set _dateUntil_ to ? GetMethod(_calendar_, *"dateUntil"*).
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
1. Let _duration_ be ? Call(_dateUntil_, _calendar_, « _one_, _two_, _options_ »).
1. Perform ? RequireInternalSlot(_duration_, [[InitializedTemporalDuration]]).
1. Return _duration_.
@@ -195,7 +203,7 @@
CalendarYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing an integer, or an abrupt completion
@@ -204,7 +212,9 @@
It calls the given _calendar_'s `year()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.year%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"year"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -215,7 +225,7 @@
CalendarMonth (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing an integer, or an abrupt completion
@@ -224,7 +234,9 @@
It calls the given _calendar_'s `month()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.month%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"month"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -236,7 +248,7 @@
CalendarMonthCode (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainYearMonth, or Temporal.PlainMonthDay,
): either a normal completion containing a String, or an abrupt completion
@@ -245,7 +257,9 @@
It calls the given _calendar_'s `monthCode()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.monthCode%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"monthCode"*, « _dateLike_ »).
1. If Type(_result_) is not String, throw a *TypeError* exception.
1. Return _result_.
@@ -255,7 +269,7 @@
CalendarDay (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainMonthDay,
): either a normal completion containing an integer, or an abrupt completion
@@ -264,7 +278,9 @@
It calls the given _calendar_'s `day()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.day%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"day"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -276,7 +292,7 @@
CalendarDayOfWeek (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime or Temporal.PlainDate,
): either a normal completion containing an integer, or an abrupt completion
@@ -285,7 +301,9 @@
It calls the given _calendar_'s `dayOfWeek()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.dayOfWeek%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"dayOfWeek"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -297,7 +315,7 @@
CalendarDayOfYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime or Temporal.PlainDate,
): either a normal completion containing an integer, or an abrupt completion
@@ -306,7 +324,9 @@
It calls the given _calendar_'s `dayOfYear()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.dayOfYear%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"dayOfYear"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -318,7 +338,7 @@
CalendarWeekOfYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime or Temporal.PlainDate,
): either a normal completion containing an integer, or an abrupt completion
@@ -327,7 +347,9 @@
It calls the given _calendar_'s `weekOfYear()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.weekOfYear%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"weekOfYear"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -339,7 +361,7 @@
CalendarYearOfWeek (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime or Temporal.PlainDate,
): either a normal completion containing an integer, or an abrupt completion
@@ -348,7 +370,9 @@
It calls the given _calendar_'s `yearOfWeek()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.yearOfWeek%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"yearOfWeek"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -359,7 +383,7 @@
CalendarDaysInWeek (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime or Temporal.PlainDate,
): either a normal completion containing an integer, or an abrupt completion
@@ -368,7 +392,9 @@
It calls the given _calendar_'s `daysInWeek()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.daysInWeek%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"daysInWeek"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -380,7 +406,7 @@
CalendarDaysInMonth (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing an integer, or an abrupt completion
@@ -389,7 +415,9 @@
It calls the given _calendar_'s `daysInMonth()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.daysInMonth%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"daysInMonth"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -401,7 +429,7 @@
CalendarDaysInYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing an integer, or an abrupt completion
@@ -410,7 +438,9 @@
It calls the given _calendar_'s `daysInYear()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.daysInYear%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"daysInYear"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -422,7 +452,7 @@
CalendarMonthsInYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing an integer, or an abrupt completion
@@ -431,7 +461,9 @@
It calls the given _calendar_'s `monthsInYear()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.monthsInYear%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"monthsInYear"*, « _dateLike_ »).
1. If Type(_result_) is not Number, throw a *TypeError* exception.
1. If IsIntegralNumber(_result_) is *false*, throw a *RangeError* exception.
@@ -443,7 +475,7 @@
CalendarInLeapYear (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_dateLike_: a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth,
): either a normal completion containing a Boolean, or an abrupt completion
@@ -452,15 +484,25 @@
It calls the given _calendar_'s `inLeapYear()` method and validates the result.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.inLeapYear%, _calendar_, « _dateLike_ »).
1. Let _result_ be ? Invoke(_calendar_, *"inLeapYear"*, « _dateLike_ »).
1. If Type(_result_) is not Boolean, throw a *TypeError* exception.
1. Return _result_.
-
- ToTemporalCalendar ( _temporalCalendarLike_ )
+
+
+ ToTemporalCalendar (
+ _temporalCalendarLike_: an ECMAScript value,
+ ): either a normal completion containing either a String or an Object, or a throw completion
+
+
1. If Type(_temporalCalendarLike_) is Object, then
1. If _temporalCalendarLike_ has an [[InitializedTemporalCalendar]] internal slot, then
@@ -476,7 +518,7 @@ ToTemporalCalendar ( _temporalCalendarLike_ )
1. Let _identifier_ be ? ToString(_temporalCalendarLike_).
1. Set _identifier_ to ? ParseTemporalCalendarString(_identifier_).
1. If IsBuiltinCalendar(_identifier_) is *false*, throw a *RangeError* exception.
- 1. Return ! CreateTemporalCalendar(_identifier_).
+ 1. Return the ASCII-lowercase of _identifier_.
@@ -507,10 +549,46 @@ GetTemporalCalendarWithISODefault ( _item_ )
+
+
+ ToTemporalCalendarIdentifier (
+ _calendarSlotValue_: a String or Object,
+ ): either a normal completion containing a String, or a throw completion
+
+
+
+ 1. If _calendarSlotValue_ is a String, then
+ 1. Assert: IsBuiltinCalendar(_calendarSlotValue_) is *true*.
+ 1. Return _calendarSlotValue_.
+ 1. Let _identifier_ be ? Get(_calendarSlotValue_, *"id"*).
+ 1. If _identifier_ is not a String, throw a *TypeError* exception.
+ 1. Return _identifier_.
+
+
+
+
+
+ ToTemporalCalendarObject (
+ _calendarSlotValue_: a String or Object,
+ ): an Object
+
+
+
+ 1. If _calendarSlotValue_ is an Object, return _calendarSlotValue_.
+ 1. Return ! CreateTemporalCalendar(_calendarSlotValue_).
+
+
+
CalendarDateFromFields (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_fields_: an Object,
optional _options_: an Object or *undefined*,
): either a normal completion containing a `Temporal.PlainDate` or an abrupt completion
@@ -521,7 +599,9 @@
1. If _options_ is not present, set _options_ to *undefined*.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.dateFromFields%, _calendar_, « _fields_, _options_ »).
1. Let _date_ be ? Invoke(_calendar_, *"dateFromFields"*, « _fields_, _options_ »).
1. Perform ? RequireInternalSlot(_date_, [[InitializedTemporalDate]]).
1. Return _date_.
@@ -531,7 +611,7 @@
CalendarYearMonthFromFields (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_fields_: an Object,
optional _options_: an Object or *undefined*,
): either a normal completion containing a `Temporal.PlainYearMonth` or an abrupt completion
@@ -542,7 +622,9 @@
1. If _options_ is not present, set _options_ to *undefined*.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.yearMonthFromFields%, _calendar_, « _fields_, _options_ »).
1. Let _yearMonth_ be ? Invoke(_calendar_, *"yearMonthFromFields"*, « _fields_, _options_ »).
1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
1. Return _yearMonth_.
@@ -552,7 +634,7 @@
CalendarMonthDayFromFields (
- _calendar_: an Object,
+ _calendar_: a String or Object,
_fields_: an Object,
optional _options_: an Object or *undefined*,
): either a normal completion containing a `Temporal.PlainMonthDay` or an abrupt completion
@@ -563,7 +645,9 @@
1. If _options_ is not present, set _options_ to *undefined*.
- 1. NOTE: If _calendar_ is a built-in object, then the following step will usually invoke or .
+ 1. If _calendar_ is a String, then
+ 1. Set _calendar_ to ! CreateTemporalCalendar(_calendar_).
+ 1. Return ? Call(%Temporal.Calendar.prototype.monthDayFromFields%, _calendar_, « _fields_, _options_ »).
1. Let _monthDay_ be ? Invoke(_calendar_, *"monthDayFromFields"*, « _fields_, _options_ »).
1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
1. Return _monthDay_.
@@ -573,7 +657,7 @@
MaybeFormatCalendarAnnotation (
- _calendarObject_: an Object or *undefined*,
+ _calendar_: a String or Object,
_showCalendar_: one of *"auto"*, *"always"*, *"never"*, or *"critical"*,
): either a normal completion containing a String, or an abrupt completion
@@ -581,13 +665,13 @@
description
It returns a string with a calendar annotation suitable for concatenating to the end of an ISO 8601 string.
- Depending on the given _calendarObject_ and the value of _showCalendar_, the string may be empty if no calendar annotation need be included.
+ Depending on the given _calendar_ and the value of _showCalendar_, the string may be empty if no calendar annotation need be included.
This operation may invoke an observable ToString operation on _calendarObject_, but not if _showCalendar_ is *"never"*.
1. If _showCalendar_ is *"never"*, return the empty String.
- 1. Assert: Type(_calendarObject_) is Object.
+ 1. Let _calendarObject_ be ToTemporalCalendarObject(_calendar_).
1. Let _calendarID_ be ? ToString(_calendarObject_).
1. Return FormatCalendarAnnotation(_calendarID_, _showCalendar_).
@@ -940,7 +1024,8 @@ Temporal.Calendar.from ( _calendarLike_ )
The `Temporal.Calendar.from` function performs the following steps when called:
- 1. Return ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendarSlotValue_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Return ToTemporalCalendarObject(_calendarSlotValue_).
@@ -1005,7 +1090,7 @@ Temporal.Calendar.prototype.dateFromFields ( _fields_ [ , _options_ ] )
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"month"*, *"monthCode"*, *"year"* », « *"year"*, *"day"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _result_ be ? ISODateFromFields(_fields_, _overflow_).
- 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
+ 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], *"iso8601"*).
@@ -1027,7 +1112,7 @@ Temporal.Calendar.prototype.yearMonthFromFields ( _fields_ [ , _options_ ] )
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"month"*, *"monthCode"*, *"year"* », « *"year"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _result_ be ? ISOYearMonthFromFields(_fields_, _overflow_).
- 1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_, _result_.[[ReferenceISODay]]).
+ 1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], *"iso8601"*, _result_.[[ReferenceISODay]]).
@@ -1049,7 +1134,7 @@ Temporal.Calendar.prototype.monthDayFromFields ( _fields_ [ , _options_ ] )<
1. Set _fields_ to ? PrepareTemporalFields(_fields_, « *"day"*, *"month"*, *"monthCode"*, *"year"* », « *"day"* »).
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _result_ be ? ISOMonthDayFromFields(_fields_, _overflow_).
- 1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _result_.[[ReferenceISOYear]]).
+ 1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], *"iso8601"*, _result_.[[ReferenceISOYear]]).
@@ -1072,7 +1157,7 @@ Temporal.Calendar.prototype.dateAdd ( _date_, _duration_ [ , _options_ ] )
1. Let _overflow_ be ? ToTemporalOverflow(_options_).
1. Let _balanceResult_ be ? BalanceDuration(_duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], *"day"*).
1. Let _result_ be ? AddISODate(_date_.[[ISOYear]], _date_.[[ISOMonth]], _date_.[[ISODay]], _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]], _overflow_).
- 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
+ 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], *"iso8601"*).
diff --git a/spec/instant.html b/spec/instant.html
index 033031098f..15877b5fd6 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -656,7 +656,7 @@ TemporalInstantToString ( _instant_, _timeZone_, _precision_ )
1. Set _outputTimeZone_ to ! CreateTemporalTimeZone(*"UTC"*).
1. Let _isoCalendar_ be ! GetISO8601Calendar().
1. Let _dateTime_ be ? GetPlainDateTimeFor(_outputTimeZone_, _instant_, _isoCalendar_).
- 1. Let _dateTimeString_ be ! TemporalDateTimeToString(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], *undefined*, _precision_, *"never"*).
+ 1. Let _dateTimeString_ be ! TemporalDateTimeToString(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], *"iso8601"*, _precision_, *"never"*).
1. If _timeZone_ is *undefined*, then
1. Let _timeZoneString_ be *"Z"*.
1. Else,
diff --git a/spec/intl.html b/spec/intl.html
index d59d6bef69..fcb9b84126 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -1829,7 +1829,7 @@ Temporal.Calendar.prototype.dateFromFields ( _fields_ [ , _options_ ] )
1. Else,
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~date~).
1. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _overflow_).
- 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
+ 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_.[[Identifier]]).
@@ -1859,7 +1859,7 @@ Temporal.Calendar.prototype.yearMonthFromFields ( _fields_ [ , _options_ ] )
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~year-month~).
1. Let _result_ be ? CalendarDateToISO(_calendar_.[[Identifier]], _fields_, _overflow_).
1. Set _result_.[[ReferenceISODay]] to _result_.[[Day]].
- 1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_, _result_.[[ReferenceISODay]]).
+ 1. Return ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_.[[Identifier]], _result_.[[ReferenceISODay]]).
@@ -1886,7 +1886,7 @@ Temporal.Calendar.prototype.monthDayFromFields ( _fields_ [ , _options_ ] )<
1. Else,
1. Perform ? CalendarResolveFields(_calendar_.[[Identifier]], _fields_, ~month-day~).
1. Let _result_ be ? CalendarMonthDayToISOReferenceDate(_calendar_.[[Identifier]], _fields_, _overflow_).
- 1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _result_.[[ReferenceISOYear]]).
+ 1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_.[[Identifier]], _result_.[[ReferenceISOYear]]).
@@ -1909,7 +1909,7 @@ Temporal.Calendar.prototype.dateAdd ( _date_, _duration_ [ , _options_ ] )
1. Else,
1. Let _balancedDuration_ be ! CreateDateDurationRecord(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _balanceResult_.[[Days]]).
1. Let _result_ be ? CalendarDateAddition(_calendar_.[[Identifier]], _date_, _balancedDuration_, _overflow_).
- 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
+ 1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_.[[Identifier]]).
diff --git a/spec/plaindate.html b/spec/plaindate.html
index cb9d2568d4..be1c8f3214 100644
--- a/spec/plaindate.html
+++ b/spec/plaindate.html
@@ -111,16 +111,16 @@ Temporal.PlainDate.prototype[ @@toStringTag ]
-
- get Temporal.PlainDate.prototype.calendar
+
+ get Temporal.PlainDate.prototype.calendarId
- `Temporal.PlainDate.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.PlainDate.prototype.calendarId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
- 1. Return _temporalDate_.[[Calendar]].
+ 1. Return ? ToTemporalCalendarIdentifier(_temporalDate_.[[Calendar]]).
@@ -355,6 +355,18 @@ Temporal.PlainDate.prototype.getISOFields ( )
+
+ Temporal.PlainDate.prototype.getCalendar ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _temporalDate_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
+ 1. Return ToTemporalCalendarObject(_temporalDate_.[[Calendar]]).
+
+
+
Temporal.PlainDate.prototype.add ( _temporalDurationLike_ [ , _options_ ] )
@@ -696,7 +708,7 @@
_isoYear_: an integer,
_isoMonth_: an integer,
_isoDay_: an integer,
- _calendar_: an Object,
+ _calendar_: a String or Object,
optional _newTarget_: a constructor,
): either a normal completion containing a Temporal.PlainDate, or an abrupt completion
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index afd052217b..90659058d5 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -114,16 +114,16 @@ Temporal.PlainDateTime.prototype[ @@toStringTag ]
-
- get Temporal.PlainDateTime.prototype.calendar
+
+ get Temporal.PlainDateTime.prototype.calendarId
- `Temporal.PlainDateTime.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.PlainDateTime.prototype.calendarId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _dateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
- 1. Return _dateTime_.[[Calendar]].
+ 1. Return ? ToTemporalCalendarIdentifier(_dateTime_.[[Calendar]]).
@@ -706,6 +706,18 @@ Temporal.PlainDateTime.prototype.getISOFields ( )
1. Return _fields_.
+
+
+ Temporal.PlainDateTime.prototype.getCalendar ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _dateTime_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
+ 1. Return ToTemporalCalendarObject(_dateTime_).
+
+
@@ -945,7 +957,7 @@
_millisecond_: an integer,
_microsecond_: an integer,
_nanosecond_: an integer,
- _calendar_: an Object,
+ _calendar_: a String or Object,
optional _newTarget_: a constructor,
): either a normal completion containing a Temporal.PlainDateTime instance, or an abrupt completion
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index 78278e703e..448559358c 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -98,16 +98,16 @@ Temporal.PlainMonthDay.prototype[ @@toStringTag ]
-
- get Temporal.PlainMonthDay.prototype.calendar
+
+ get Temporal.PlainMonthDay.prototype.calendarId
- `Temporal.PlainMonthDay.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.PlainMonthDay.prototype.calendarId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _monthDay_ be the *this* value.
1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
- 1. Return _monthDay_.[[Calendar]].
+ 1. Return ? ToTemporalCalendarIdentifier(_monthDay_.[[Calendar]]).
@@ -272,6 +272,18 @@ Temporal.PlainMonthDay.prototype.getISOFields ( )
1. Return _fields_.
+
+
+ Temporal.PlainMonthDay.prototype.getCalendar ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _monthDay_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_monthDay_, [[InitializedTemporalMonthDay]]).
+ 1. Return ToTemporalCalendarObject(_monthDay_.[[Calendar]]).
+
+
@@ -387,7 +399,7 @@
CreateTemporalMonthDay (
_isoMonth_: an integer,
_isoDay_: an integer,
- _calendar_: an Object,
+ _calendar_: a String or Object,
_referenceISOYear_: an integer,
optional _newTarget_: a constructor,
): either a normal completion containing a Temporal.PlainMonthDay, or an abrupt completion
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index d5fd7895bd..384ae23d8e 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -109,16 +109,16 @@ Temporal.PlainYearMonth.prototype[ @@toStringTag ]
-
- get Temporal.PlainYearMonth.prototype.calendar
+
+ get Temporal.PlainYearMonth.prototype.calendarId
- `Temporal.PlainYearMonth.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.PlainYearMonth.prototype.calendarId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _yearMonth_ be the *this* value.
1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
- 1. Return _yearMonth_.[[Calendar]].
+ 1. Return ? ToTemporalCalendarIdentifier(_yearMonth_.[[Calendar]]).
@@ -401,6 +401,18 @@ Temporal.PlainYearMonth.prototype.getISOFields ( )
1. Return _fields_.
+
+
+ Temporal.PlainYearMonth.prototype.getCalendar ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _yearMonth_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_yearMonth_, [[InitializedTemporalYearMonth]]).
+ 1. Return ToTemporalCalendarObject(_yearMonth_.[[Calendar]]).
+
+
@@ -556,7 +568,7 @@
CreateTemporalYearMonth (
_isoYear_: an integer,
_isoMonth_: an integer,
- _calendar_: an Object,
+ _calendar_: a String or Object,
_referenceISODay_: an integer,
optional _newTarget_: a constructor,
): either a normal completion containing a Temporal.PlainYearMonth, or an abrupt completion
diff --git a/spec/timezone.html b/spec/timezone.html
index 2d8f948799..16f397aeb8 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -610,7 +610,7 @@
GetPlainDateTimeFor (
_timeZone_: an Object,
_instant_: a Temporal.Instant,
- _calendar_: an Object,
+ _calendar_: a String or Object,
): either a normal completion containing a Temporal.PlainDateTime, or an abrupt completion
-
- get Temporal.ZonedDateTime.prototype.calendar
+
+ get Temporal.ZonedDateTime.prototype.calendarId
- `Temporal.ZonedDateTime.prototype.calendar` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.ZonedDateTime.prototype.calendarId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _zonedDateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
- 1. Return _zonedDateTime_.[[Calendar]].
+ 1. Return ? ToTemporalCalendarIdentifier(_zonedDateTime_.[[Calendar]]).
@@ -990,6 +990,18 @@ Temporal.ZonedDateTime.prototype.getISOFields ( )
1. Return _fields_.
+
+
+ Temporal.ZonedDateTime.prototype.getCalendar ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _zonedDateTime_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
+ 1. Return ToTemporalCalendarObject(_zonedDateTime_.[[Calendar]]).
+
+
@@ -1180,7 +1192,7 @@
CreateTemporalZonedDateTime (
_epochNanoseconds_: a BigInt,
_timeZone_: an Object,
- _calendar_: an Object,
+ _calendar_: a String or Object,
optional _newTarget_: a constructor,
): either a normal completion containing a Temporal.ZonedDateTime, or an abrupt completion
From 0e088200713ec217f132c9c6bd99ec83c574b33b Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Mon, 16 Jan 2023 17:06:45 -0800
Subject: [PATCH 05/14] Normative: Use string calendar values internally
everywhere possible
When creating Temporal objects with a builtin ISO 8601 calendar, we want
them to be created with a string in the internal slot, not a Calendar
instance. (For example, when parsing a calendar name out of a string or
using ISO 8601 as a default.) Therefore we don't need the
GetISO8601Calendar and GetBuiltinCalendar AOs anymore.
See: #1808
---
polyfill/lib/ecmascript.mjs | 34 ++++++++++++++-------------------
polyfill/lib/instant.mjs | 3 +--
polyfill/lib/now.mjs | 5 ++---
polyfill/lib/plaindate.mjs | 2 +-
polyfill/lib/plaindatetime.mjs | 2 +-
polyfill/lib/plainmonthday.mjs | 2 +-
polyfill/lib/plainyearmonth.mjs | 2 +-
polyfill/lib/timezone.mjs | 2 +-
polyfill/lib/zoneddatetime.mjs | 2 +-
spec/abstractops.html | 3 ++-
spec/calendar.html | 17 +----------------
spec/instant.html | 6 ++----
spec/intl.html | 5 ++---
spec/plaindatetime.html | 3 ++-
spec/plainmonthday.html | 3 ++-
spec/plainyearmonth.html | 3 ++-
spec/temporal.html | 14 +++++---------
spec/zoneddatetime.html | 21 +++++++++-----------
18 files changed, 50 insertions(+), 79 deletions(-)
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index a92778593a..fc2ed28671 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -939,7 +939,7 @@ export const ES = ObjectAssign({}, ES2022, {
'Z designator not supported for PlainDate relativeTo; either remove the Z or add a bracketed time zone'
);
}
- if (!calendar) calendar = ES.GetISO8601Calendar();
+ if (!calendar) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
}
if (timeZone === undefined) return ES.CreateTemporalDate(year, month, day, calendar);
@@ -1139,7 +1139,7 @@ export const ES = ObjectAssign({}, ES2022, {
ES.ParseTemporalDateTimeString(ES.ToString(item)));
if (z) throw new RangeError('Z designator not supported for PlainDateTime');
ES.RejectDateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond);
- if (calendar === undefined) calendar = ES.GetISO8601Calendar();
+ if (calendar === undefined) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
}
return ES.CreateTemporalDateTime(
@@ -1193,7 +1193,7 @@ export const ES = ObjectAssign({}, ES2022, {
} else {
calendar = item.calendar;
calendarAbsent = calendar === undefined;
- if (calendar === undefined) calendar = ES.GetISO8601Calendar();
+ if (calendar === undefined) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
}
const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']);
@@ -1209,7 +1209,7 @@ export const ES = ObjectAssign({}, ES2022, {
ES.ToTemporalOverflow(options); // validate and ignore
let { month, day, referenceISOYear, calendar } = ES.ParseTemporalMonthDayString(ES.ToString(item));
- if (calendar === undefined) calendar = ES.GetISO8601Calendar();
+ if (calendar === undefined) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
if (referenceISOYear === undefined) {
@@ -1265,7 +1265,7 @@ export const ES = ObjectAssign({}, ES2022, {
ES.ToTemporalOverflow(options); // validate and ignore
let { year, month, referenceISODay, calendar } = ES.ParseTemporalYearMonthString(ES.ToString(item));
- if (calendar === undefined) calendar = ES.GetISO8601Calendar();
+ if (calendar === undefined) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
if (referenceISODay === undefined) {
@@ -1391,7 +1391,7 @@ export const ES = ObjectAssign({}, ES2022, {
}
const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
timeZone = new TemporalTimeZone(ianaName);
- if (!calendar) calendar = ES.GetISO8601Calendar();
+ if (!calendar) calendar = 'iso8601';
calendar = ES.ToTemporalCalendar(calendar);
matchMinute = true; // ISO strings may specify offset with less precision
disambiguation = ES.ToTemporalDisambiguation(options);
@@ -1440,7 +1440,7 @@ export const ES = ObjectAssign({}, ES2022, {
});
}
},
- CreateTemporalDate: (isoYear, isoMonth, isoDay, calendar = ES.GetISO8601Calendar()) => {
+ CreateTemporalDate: (isoYear, isoMonth, isoDay, calendar = 'iso8601') => {
const TemporalPlainDate = GetIntrinsic('%Temporal.PlainDate%');
const result = ObjectCreate(TemporalPlainDate.prototype);
ES.CreateTemporalDateSlots(result, isoYear, isoMonth, isoDay, calendar);
@@ -1471,7 +1471,7 @@ export const ES = ObjectAssign({}, ES2022, {
});
}
},
- CreateTemporalDateTime: (isoYear, isoMonth, isoDay, h, min, s, ms, µs, ns, calendar = ES.GetISO8601Calendar()) => {
+ CreateTemporalDateTime: (isoYear, isoMonth, isoDay, h, min, s, ms, µs, ns, calendar = 'iso8601') => {
const TemporalPlainDateTime = GetIntrinsic('%Temporal.PlainDateTime%');
const result = ObjectCreate(TemporalPlainDateTime.prototype);
ES.CreateTemporalDateTimeSlots(result, isoYear, isoMonth, isoDay, h, min, s, ms, µs, ns, calendar);
@@ -1497,7 +1497,7 @@ export const ES = ObjectAssign({}, ES2022, {
});
}
},
- CreateTemporalMonthDay: (isoMonth, isoDay, calendar = ES.GetISO8601Calendar(), referenceISOYear = 1972) => {
+ CreateTemporalMonthDay: (isoMonth, isoDay, calendar = 'iso8601', referenceISOYear = 1972) => {
const TemporalPlainMonthDay = GetIntrinsic('%Temporal.PlainMonthDay%');
const result = ObjectCreate(TemporalPlainMonthDay.prototype);
ES.CreateTemporalMonthDaySlots(result, isoMonth, isoDay, calendar, referenceISOYear);
@@ -1523,7 +1523,7 @@ export const ES = ObjectAssign({}, ES2022, {
});
}
},
- CreateTemporalYearMonth: (isoYear, isoMonth, calendar = ES.GetISO8601Calendar(), referenceISODay = 1) => {
+ CreateTemporalYearMonth: (isoYear, isoMonth, calendar = 'iso8601', referenceISODay = 1) => {
const TemporalPlainYearMonth = GetIntrinsic('%Temporal.PlainYearMonth%');
const result = ObjectCreate(TemporalPlainYearMonth.prototype);
ES.CreateTemporalYearMonthSlots(result, isoYear, isoMonth, calendar, referenceISODay);
@@ -1550,17 +1550,13 @@ export const ES = ObjectAssign({}, ES2022, {
});
}
},
- CreateTemporalZonedDateTime: (epochNanoseconds, timeZone, calendar = ES.GetISO8601Calendar()) => {
+ CreateTemporalZonedDateTime: (epochNanoseconds, timeZone, calendar = 'iso8601') => {
const TemporalZonedDateTime = GetIntrinsic('%Temporal.ZonedDateTime%');
const result = ObjectCreate(TemporalZonedDateTime.prototype);
ES.CreateTemporalZonedDateTimeSlots(result, epochNanoseconds, timeZone, calendar);
return result;
},
- GetISO8601Calendar: () => {
- const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
- return new TemporalCalendar('iso8601');
- },
CalendarFields: (calendar, fieldNames) => {
if (typeof calendar === 'string') {
const TemporalCalendar = GetIntrinsic('%Temporal.Calendar%');
@@ -1892,7 +1888,7 @@ export const ES = ObjectAssign({}, ES2022, {
GetTemporalCalendarWithISODefault: (item) => {
if (HasSlot(item, CALENDAR)) return GetSlot(item, CALENDAR);
const { calendar } = item;
- if (calendar === undefined) return ES.GetISO8601Calendar();
+ if (calendar === undefined) return 'iso8601';
return ES.ToTemporalCalendar(calendar);
},
ToTemporalCalendarIdentifier: (slotValue) => {
@@ -2244,8 +2240,7 @@ export const ES = ObjectAssign({}, ES2022, {
const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
outputTimeZone = new TemporalTimeZone('UTC');
}
- const iso = ES.GetISO8601Calendar();
- const dateTime = ES.GetPlainDateTimeFor(outputTimeZone, instant, iso);
+ const dateTime = ES.GetPlainDateTimeFor(outputTimeZone, instant, 'iso8601');
const year = ES.ISOYearString(GetSlot(dateTime, ISO_YEAR));
const month = ES.ISODateTimePartString(GetSlot(dateTime, ISO_MONTH));
const day = ES.ISODateTimePartString(GetSlot(dateTime, ISO_DAY));
@@ -2418,8 +2413,7 @@ export const ES = ObjectAssign({}, ES2022, {
}
const tz = GetSlot(zdt, TIME_ZONE);
- const iso = ES.GetISO8601Calendar();
- const dateTime = ES.GetPlainDateTimeFor(tz, instant, iso);
+ const dateTime = ES.GetPlainDateTimeFor(tz, instant, 'iso8601');
const year = ES.ISOYearString(GetSlot(dateTime, ISO_YEAR));
const month = ES.ISODateTimePartString(GetSlot(dateTime, ISO_MONTH));
diff --git a/polyfill/lib/instant.mjs b/polyfill/lib/instant.mjs
index 337fe21da0..606c805cee 100644
--- a/polyfill/lib/instant.mjs
+++ b/polyfill/lib/instant.mjs
@@ -148,8 +148,7 @@ export class Instant {
toZonedDateTimeISO(timeZone) {
if (!ES.IsTemporalInstant(this)) throw new TypeError('invalid receiver');
timeZone = ES.ToTemporalTimeZone(timeZone);
- const calendar = ES.GetISO8601Calendar();
- return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), timeZone, calendar);
+ return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), timeZone, 'iso8601');
}
static fromEpochSeconds(epochSeconds) {
diff --git a/polyfill/lib/now.mjs b/polyfill/lib/now.mjs
index 2b600cafc0..74b9e7a68b 100644
--- a/polyfill/lib/now.mjs
+++ b/polyfill/lib/now.mjs
@@ -13,9 +13,8 @@ const plainDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()
};
const plainDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
- const calendar = ES.GetISO8601Calendar();
const inst = instant();
- return ES.GetPlainDateTimeFor(timeZone, inst, calendar);
+ return ES.GetPlainDateTimeFor(timeZone, inst, 'iso8601');
};
const zonedDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
@@ -23,7 +22,7 @@ const zonedDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()
return ES.CreateTemporalZonedDateTime(ES.SystemUTCEpochNanoSeconds(), timeZone, calendar);
};
const zonedDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
- return zonedDateTime(ES.GetISO8601Calendar(), temporalTimeZoneLike);
+ return zonedDateTime('iso8601', temporalTimeZoneLike);
};
const plainDate = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
return ES.TemporalDateTimeToDate(plainDateTime(calendarLike, temporalTimeZoneLike));
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 8dbf88fce8..693da71afb 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -17,7 +17,7 @@ import {
} from './slots.mjs';
export class PlainDate {
- constructor(isoYear, isoMonth, isoDay, calendar = ES.GetISO8601Calendar()) {
+ constructor(isoYear, isoMonth, isoDay, calendar = 'iso8601') {
isoYear = ES.ToIntegerWithTruncation(isoYear);
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
isoDay = ES.ToIntegerWithTruncation(isoDay);
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index a09871d3a1..f540e4653d 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -30,7 +30,7 @@ export class PlainDateTime {
millisecond = 0,
microsecond = 0,
nanosecond = 0,
- calendar = ES.GetISO8601Calendar()
+ calendar = 'iso8601'
) {
isoYear = ES.ToIntegerWithTruncation(isoYear);
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
diff --git a/polyfill/lib/plainmonthday.mjs b/polyfill/lib/plainmonthday.mjs
index 200aa0cf5d..8665a5b330 100644
--- a/polyfill/lib/plainmonthday.mjs
+++ b/polyfill/lib/plainmonthday.mjs
@@ -9,7 +9,7 @@ const SetPrototypeAdd = Set.prototype.add;
const SetPrototypeForEach = Set.prototype.forEach;
export class PlainMonthDay {
- constructor(isoMonth, isoDay, calendar = ES.GetISO8601Calendar(), referenceISOYear = 1972) {
+ constructor(isoMonth, isoDay, calendar = 'iso8601', referenceISOYear = 1972) {
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
isoDay = ES.ToIntegerWithTruncation(isoDay);
calendar = ES.ToTemporalCalendar(calendar);
diff --git a/polyfill/lib/plainyearmonth.mjs b/polyfill/lib/plainyearmonth.mjs
index 0ff3d8f862..22980ebd82 100644
--- a/polyfill/lib/plainyearmonth.mjs
+++ b/polyfill/lib/plainyearmonth.mjs
@@ -9,7 +9,7 @@ const SetPrototypeAdd = Set.prototype.add;
const SetPrototypeForEach = Set.prototype.forEach;
export class PlainYearMonth {
- constructor(isoYear, isoMonth, calendar = ES.GetISO8601Calendar(), referenceISODay = 1) {
+ constructor(isoYear, isoMonth, calendar = 'iso8601', referenceISODay = 1) {
isoYear = ES.ToIntegerWithTruncation(isoYear);
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
calendar = ES.ToTemporalCalendar(calendar);
diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs
index 205656c191..a4d59fb6ec 100644
--- a/polyfill/lib/timezone.mjs
+++ b/polyfill/lib/timezone.mjs
@@ -60,7 +60,7 @@ export class TimeZone {
instant = ES.ToTemporalInstant(instant);
return ES.GetOffsetStringFor(this, instant);
}
- getPlainDateTimeFor(instant, calendar = ES.GetISO8601Calendar()) {
+ getPlainDateTimeFor(instant, calendar = 'iso8601') {
if (!ES.IsTemporalTimeZone(this)) throw new TypeError('invalid receiver');
instant = ES.ToTemporalInstant(instant);
calendar = ES.ToTemporalCalendar(calendar);
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index d0f2ab3526..11f2a39bae 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -24,7 +24,7 @@ const ArrayPrototypePush = Array.prototype.push;
const ObjectCreate = Object.create;
export class ZonedDateTime {
- constructor(epochNanoseconds, timeZone, calendar = ES.GetISO8601Calendar()) {
+ constructor(epochNanoseconds, timeZone, calendar = 'iso8601') {
// Note: if the argument is not passed, ToBigInt(undefined) will throw. This check exists only
// to improve the error message.
// ToTemporalTimeZone(undefined) will end up calling TimeZone.from("undefined"), which
diff --git a/spec/abstractops.html b/spec/abstractops.html
index eac484169c..c3aaffe79b 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -499,7 +499,8 @@ ToRelativeTemporalObject ( _options_ )
1. Else,
1. Let _string_ be ? ToString(_value_).
1. Let _result_ be ? ParseTemporalRelativeToString(_string_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be _result_.[[Calendar]].
+ 1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. Let _offsetString_ be _result_.[[TimeZone]].[[OffsetString]].
1. Let _timeZoneName_ be _result_.[[TimeZone]].[[Name]].
1. If _timeZoneName_ is *undefined*, then
diff --git a/spec/calendar.html b/spec/calendar.html
index 06cae60e80..b953ef5887 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -86,21 +86,6 @@
-
- GetBuiltinCalendar ( _id_ )
-
- 1. If IsBuiltinCalendar(_id_) is *false*, throw a *RangeError* exception.
- 1. Return ! CreateTemporalCalendar(_id_).
-
-
-
-
- GetISO8601Calendar ( )
-
- 1. Return ! GetBuiltinCalendar(*"iso8601"*).
-
-
-
CalendarFields (
@@ -530,7 +515,7 @@ ToTemporalCalendarWithISODefault ( _temporalCalendarLike_ )
1. If _temporalCalendarLike_ is *undefined*, then
- 1. Return ! GetISO8601Calendar().
+ 1. Return *"iso8601"*.
1. Return ? ToTemporalCalendar(_temporalCalendarLike_).
diff --git a/spec/instant.html b/spec/instant.html
index 15877b5fd6..cd1f1341cc 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -408,8 +408,7 @@ Temporal.Instant.prototype.toZonedDateTimeISO ( _timeZone_ )
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Return ! CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, _calendar_).
+ 1. Return ! CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, *"iso8601"*).
@@ -654,8 +653,7 @@ TemporalInstantToString ( _instant_, _timeZone_, _precision_ )
1. Let _outputTimeZone_ be _timeZone_.
1. If _outputTimeZone_ is *undefined*, then
1. Set _outputTimeZone_ to ! CreateTemporalTimeZone(*"UTC"*).
- 1. Let _isoCalendar_ be ! GetISO8601Calendar().
- 1. Let _dateTime_ be ? GetPlainDateTimeFor(_outputTimeZone_, _instant_, _isoCalendar_).
+ 1. Let _dateTime_ be ? GetPlainDateTimeFor(_outputTimeZone_, _instant_, *"iso8601"*).
1. Let _dateTimeString_ be ! TemporalDateTimeToString(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], *"iso8601"*, _precision_, *"never"*).
1. If _timeZone_ is *undefined*, then
1. Let _timeZoneString_ be *"Z"*.
diff --git a/spec/intl.html b/spec/intl.html
index fcb9b84126..b10ee66d8f 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -760,7 +760,7 @@ HandleDateTimeTemporalDate ( _dateTimeFormat_, _temporalDate_ )
1. If _calendar_ is _dateTimeFormat_.[[Calendar]], then
1. Let _calendarOverride_ be _temporalDate_.[[Calendar]].
1. Else if _calendar_ is *"iso8601"*, then
- 1. Let _calendarOverride_ be ? GetBuiltinCalendar(_dateTimeFormat_.[[Calendar]]).
+ 1. Let _calendarOverride_ be _dateTimeFormat_.[[Calendar]].
1. Else,
1. Throw a *RangeError* exception.
1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 12, 0, 0, 0, 0, 0, _calendarOverride_).
@@ -840,8 +840,7 @@ HandleDateTimeTemporalTime ( _dateTimeFormat_, _temporalTime_ )
1. Assert: _temporalTime_ has an [[InitializedTemporalTime]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainTimePattern]].
- 1. Let _isoCalendar_ be ! GetISO8601Calendar().
- 1. Let _plainDateTime_ be ? CreateTemporalDateTime(1970, 1, 1, _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _isoCalendar_).
+ 1. Let _plainDateTime_ be ? CreateTemporalDateTime(1970, 1, 1, _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], *"iso8601"*).
1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index 90659058d5..321b737f99 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -920,7 +920,8 @@ ToTemporalDateTime ( _item_ [ , _options_ ] )
1. Let _result_ be ? ParseTemporalDateTimeString(_string_).
1. Assert: IsValidISODate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]]) is *true*.
1. Assert: IsValidTime(_result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]]) is *true*.
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be _result_.[[Calendar]].
+ 1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. Return ? CreateTemporalDateTime(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _result_.[[Hour]], _result_.[[Minute]], _result_.[[Second]], _result_.[[Millisecond]], _result_.[[Microsecond]], _result_.[[Nanosecond]], _calendar_).
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index 448559358c..f50aaa02c6 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -385,7 +385,8 @@ ToTemporalMonthDay ( _item_ [ , _options_ ] )
1. Perform ? ToTemporalOverflow(_options_).
1. Let _string_ be ? ToString(_item_).
1. Let _result_ be ? ParseTemporalMonthDayString(_string_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be _result_.[[Calendar]].
+ 1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. If _result_.[[Year]] is *undefined*, then
1. Return ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _referenceISOYear_).
1. Set _result_ to ? CreateTemporalMonthDay(_result_.[[Month]], _result_.[[Day]], _calendar_, _referenceISOYear_).
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index 384ae23d8e..38ee85f929 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -499,7 +499,8 @@ ToTemporalYearMonth ( _item_ [ , _options_ ] )
1. Perform ? ToTemporalOverflow(_options_).
1. Let _string_ be ? ToString(_item_).
1. Let _result_ be ? ParseTemporalYearMonthString(_string_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be _result_.[[Calendar]].
+ 1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. Set _result_ to ? CreateTemporalYearMonth(_result_.[[Year]], _result_.[[Month]], _calendar_, _result_.[[Day]]).
1. NOTE: The following operation is called without _options_, in order for the calendar to store a canonical value in the [[ISODay]] internal slot of the result.
1. Return ? CalendarYearMonthFromFields(_calendar_, _result_).
diff --git a/spec/temporal.html b/spec/temporal.html
index f49755fedd..a3ff783295 100644
--- a/spec/temporal.html
+++ b/spec/temporal.html
@@ -127,8 +127,7 @@ Temporal.Now.plainDateTimeISO ( [ _temporalTimeZoneLike_ ] )
This function performs the following steps when called:
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Return ? SystemDateTime(_temporalTimeZoneLike_, _calendar_).
+ 1. Return ? SystemDateTime(_temporalTimeZoneLike_, *"iso8601"*).
@@ -148,8 +147,7 @@ Temporal.Now.zonedDateTimeISO ( [ _temporalTimeZoneLike_ ] )
This function performs the following steps when called:
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Return ? SystemZonedDateTime(_temporalTimeZoneLike_, _calendar_).
+ 1. Return ? SystemZonedDateTime(_temporalTimeZoneLike_, *"iso8601"*).
@@ -170,9 +168,8 @@ Temporal.Now.plainDateISO ( [ _temporalTimeZoneLike_ ] )
This function performs the following steps when called:
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Let _dateTime_ be ? SystemDateTime(_temporalTimeZoneLike_, _calendar_).
- 1. Return ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[Calendar]]).
+ 1. Let _dateTime_ be ? SystemDateTime(_temporalTimeZoneLike_, *"iso8601"*).
+ 1. Return ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], *"iso8601"*).
@@ -182,8 +179,7 @@ Temporal.Now.plainTimeISO ( [ _temporalTimeZoneLike_ ] )
This function performs the following steps when called:
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Let _dateTime_ be ? SystemDateTime(_temporalTimeZoneLike_, _calendar_).
+ 1. Let _dateTime_ be ? SystemDateTime(_temporalTimeZoneLike_, *"iso8601"*).
1. Return ! CreateTemporalTime(_dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]]).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 8d8df98979..0aa423e420 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -445,14 +445,13 @@ get Temporal.ZonedDateTime.prototype.hoursInDay
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
1. Let _timeZone_ be _zonedDateTime_.[[TimeZone]].
1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
- 1. Let _isoCalendar_ be ! GetISO8601Calendar().
- 1. Let _temporalDateTime_ be ? GetPlainDateTimeFor(_timeZone_, _instant_, _isoCalendar_).
+ 1. Let _temporalDateTime_ be ? GetPlainDateTimeFor(_timeZone_, _instant_, *"iso8601"*).
1. Let _year_ be _temporalDateTime_.[[ISOYear]].
1. Let _month_ be _temporalDateTime_.[[ISOMonth]].
1. Let _day_ be _temporalDateTime_.[[ISODay]].
- 1. Let _today_ be ? CreateTemporalDateTime(_year_, _month_, _day_, 0, 0, 0, 0, 0, 0, _isoCalendar_).
+ 1. Let _today_ be ? CreateTemporalDateTime(_year_, _month_, _day_, 0, 0, 0, 0, 0, 0, *"iso8601"*).
1. Let _tomorrowFields_ be BalanceISODate(_year_, _month_, _day_ + 1).
- 1. Let _tomorrow_ be ? CreateTemporalDateTime(_tomorrowFields_.[[Year]], _tomorrowFields_.[[Month]], _tomorrowFields_.[[Day]], 0, 0, 0, 0, 0, 0, _isoCalendar_).
+ 1. Let _tomorrow_ be ? CreateTemporalDateTime(_tomorrowFields_.[[Year]], _tomorrowFields_.[[Month]], _tomorrowFields_.[[Day]], 0, 0, 0, 0, 0, 0, *"iso8601"*).
1. Let _todayInstant_ be ? GetInstantFor(_timeZone_, _today_, *"compatible"*).
1. Let _tomorrowInstant_ be ? GetInstantFor(_timeZone_, _tomorrow_, *"compatible"*).
1. Let _diffNs_ be _tomorrowInstant_.[[Nanoseconds]] - _todayInstant_.[[Nanoseconds]].
@@ -754,8 +753,7 @@ Temporal.ZonedDateTime.prototype.round ( _roundTo_ )
1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
1. Let _calendar_ be _zonedDateTime_.[[Calendar]].
1. Let _temporalDateTime_ be ? GetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
- 1. Let _isoCalendar_ be ! GetISO8601Calendar().
- 1. Let _dtStart_ be ? CreateTemporalDateTime(_temporalDateTime_.[[ISOYear]], _temporalDateTime_.[[ISOMonth]], _temporalDateTime_.[[ISODay]], 0, 0, 0, 0, 0, 0, _isoCalendar_).
+ 1. Let _dtStart_ be ? CreateTemporalDateTime(_temporalDateTime_.[[ISOYear]], _temporalDateTime_.[[ISOMonth]], _temporalDateTime_.[[ISODay]], 0, 0, 0, 0, 0, 0, *"iso8601"*).
1. Let _instantStart_ be ? GetInstantFor(_timeZone_, _dtStart_, *"compatible"*).
1. Let _startNs_ be _instantStart_.[[Nanoseconds]].
1. Let _endNs_ be ? AddZonedDateTime(_startNs_, _timeZone_, _calendar_, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0).
@@ -1096,8 +1094,7 @@
1. Assert: IsValidISODate(_year_, _month_, _day_) is *true*.
- 1. Let _calendar_ be ! GetISO8601Calendar().
- 1. Let _dateTime_ be ? CreateTemporalDateTime(_year_, _month_, _day_, _hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _calendar_).
+ 1. Let _dateTime_ be ? CreateTemporalDateTime(_year_, _month_, _day_, _hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, *"iso8601"*).
1. If _offsetBehaviour_ is ~wall~ or _offsetOption_ is *"ignore"*, then
1. Let _instant_ be ? GetInstantFor(_timeZone_, _dateTime_, _disambiguation_).
1. Return _instant_.[[Nanoseconds]].
@@ -1173,7 +1170,8 @@
1. Else if _offsetString_ is *undefined*, then
1. Set _offsetBehaviour_ to ~wall~.
1. Let _timeZone_ be ! CreateTemporalTimeZone(_timeZoneName_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be _result_.[[Calendar]].
+ 1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. Set _matchBehaviour_ to ~match minutes~.
1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
1. Let _offsetOption_ be ? ToTemporalOffset(_options_, *"reject"*).
@@ -1237,9 +1235,8 @@
1. Let _ns_ be RoundTemporalInstant(_zonedDateTime_.[[Nanoseconds]], _increment_, _unit_, _roundingMode_).
1. Let _timeZone_ be _zonedDateTime_.[[TimeZone]].
1. Let _instant_ be ! CreateTemporalInstant(_ns_).
- 1. Let _isoCalendar_ be ! GetISO8601Calendar().
- 1. Let _temporalDateTime_ be ? GetPlainDateTimeFor(_timeZone_, _instant_, _isoCalendar_).
- 1. Let _dateTimeString_ be ! TemporalDateTimeToString(_temporalDateTime_.[[ISOYear]], _temporalDateTime_.[[ISOMonth]], _temporalDateTime_.[[ISODay]], _temporalDateTime_.[[ISOHour]], _temporalDateTime_.[[ISOMinute]], _temporalDateTime_.[[ISOSecond]], _temporalDateTime_.[[ISOMillisecond]], _temporalDateTime_.[[ISOMicrosecond]], _temporalDateTime_.[[ISONanosecond]], _isoCalendar_, _precision_, *"never"*).
+ 1. Let _temporalDateTime_ be ? GetPlainDateTimeFor(_timeZone_, _instant_, *"iso8601"*).
+ 1. Let _dateTimeString_ be ! TemporalDateTimeToString(_temporalDateTime_.[[ISOYear]], _temporalDateTime_.[[ISOMonth]], _temporalDateTime_.[[ISODay]], _temporalDateTime_.[[ISOHour]], _temporalDateTime_.[[ISOMinute]], _temporalDateTime_.[[ISOSecond]], _temporalDateTime_.[[ISOMillisecond]], _temporalDateTime_.[[ISOMicrosecond]], _temporalDateTime_.[[ISONanosecond]], *"iso8601"*, _precision_, *"never"*).
1. If _showOffset_ is *"never"*, then
1. Let _offsetString_ be the empty String.
1. Else,
From 3580461c6597d5d66deada276fe96a3bb99525c8 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Mon, 16 Jan 2023 17:37:31 -0800
Subject: [PATCH 06/14] Normative: Change calendar compare semantics to use .id
Previously algorithms such as CalendarEquals used ToString to get the
identifier of a calendar object. Instead, use ToTemporalCalendarIdentifier
which observably gets the .id property of a custom calendar instead of
getting and calling the .toString property.
See: #1808
---
docs/calendar.md | 8 ++++----
polyfill/index.d.ts | 4 ++--
polyfill/lib/ecmascript.mjs | 18 +++++++++---------
polyfill/lib/intl.mjs | 10 +++++-----
spec/calendar.html | 15 +++++++--------
spec/intl.html | 23 +++++++++--------------
spec/plainmonthday.html | 6 +++---
spec/plainyearmonth.html | 6 +++---
8 files changed, 42 insertions(+), 48 deletions(-)
diff --git a/docs/calendar.md b/docs/calendar.md
index 33d20fe0de..105f91796f 100644
--- a/docs/calendar.md
+++ b/docs/calendar.md
@@ -108,16 +108,16 @@ There are two ways to do this.
The recommended way is to create a class inheriting from `Temporal.Calendar`.
You must use one of the built-in calendars as the "base calendar".
In the class's constructor, call `super()` with the identifier of a built-in calendar to serve as a base.
-The class must override `toString()` to return its own identifier.
+The class must override the `id` prototype property, and should also override `toString()` and `toJSON()` to match.
Overriding all the other properties of `Temporal.Calendar.prototype` is optional.
Any property that's not overridden will behave as in the base calendar.
It's recommended to override `dateFromFields()`, `monthDayFromFields()`, `yearMonthFromFields()`, and `dateAdd()`so that they return Temporal objects with the custom calendar and not the base calendar.
The other, more difficult, way to create a custom calendar is to create a plain object implementing the `Temporal.Calendar` protocol, without subclassing.
-The object must implement all of the `Temporal.Calendar` properties and methods except for `id`, `fields()`, `mergeFields()`, and `toJSON()`.
+The object must implement all of the `Temporal.Calendar` properties and methods except for `fields()`, `mergeFields()`, `toString()`, and `toJSON()`.
Any object with the required methods will return the correct output from any Temporal property or method.
However, most other code will assume that custom calendars act like built-in `Temporal.Calendar` objects.
-To interoperate with libraries or other code that you didn't write, then you should implement the `id` property and the `fields()`, `mergeFields()`, and `toJSON()` methods as well.
+To interoperate with libraries or other code that you didn't write, then you should implement the `fields()`, `mergeFields()`, `toString()`, and `toJSON()` methods as well.
Your object must not have a `calendar` property, so that it can be distinguished in `Temporal.Calendar.from()` from other Temporal objects that have a calendar.
The identifier of a custom calendar must consist of one or more components of between 3 and 8 ASCII alphanumeric characters each, separated by dashes, as described in [Unicode Technical Standard 35](https://unicode.org/reports/tr35/tr35.html#Unicode_locale_identifier).
@@ -236,7 +236,7 @@ cal2 = Temporal.Calendar.from(cal);
The `id` property gives an unambiguous identifier for the calendar.
Effectively, this is whatever `calendarIdentifier` was passed as a parameter to the constructor.
-When subclassing `Temporal.Calendar`, this property doesn't need to be overridden because the default implementation gives the result of calling `toString()`.
+When subclassing `Temporal.Calendar`, this property must be overridden to provide an identifier for the custom calendar.
## Methods
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index 22bd600c1a..d3f5475ad2 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -613,7 +613,7 @@ export namespace Temporal {
type MonthOrMonthCode = { month: number } | { monthCode: string };
export interface CalendarProtocol {
- id?: string;
+ id: string;
calendar?: never;
year(date: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.PlainYearMonth | PlainDateLike | string): number;
month(
@@ -677,7 +677,7 @@ export namespace Temporal {
): Temporal.Duration;
fields?(fields: Iterable): Iterable;
mergeFields?(fields: Record, additionalFields: Record): Record;
- toString(): string;
+ toString?(): string;
toJSON?(): string;
}
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index fc2ed28671..34fd3f1b10 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -341,7 +341,7 @@ export const ES = ObjectAssign({}, ES2022, {
},
MaybeFormatCalendarAnnotation: (calendar, showCalendar) => {
if (showCalendar === 'never') return '';
- return ES.FormatCalendarAnnotation(ES.ToString(ES.ToTemporalCalendarObject(calendar)), showCalendar);
+ return ES.FormatCalendarAnnotation(ES.ToTemporalCalendarIdentifier(calendar), showCalendar);
},
FormatCalendarAnnotation: (id, showCalendar) => {
if (showCalendar === 'never') return '';
@@ -1904,8 +1904,8 @@ export const ES = ObjectAssign({}, ES2022, {
},
CalendarEquals: (one, two) => {
if (one === two) return true;
- const cal1 = ES.ToString(one);
- const cal2 = ES.ToString(two);
+ const cal1 = ES.ToTemporalCalendarIdentifier(one);
+ const cal2 = ES.ToTemporalCalendarIdentifier(two);
return cal1 === cal2;
},
// This operation is not in the spec, it implements the following:
@@ -1914,16 +1914,16 @@ export const ES = ObjectAssign({}, ES2022, {
// re-getting the .id properties.
CalendarEqualsOrThrow: (one, two, errorMessageAction) => {
if (one === two) return true;
- const cal1 = ES.ToString(one);
- const cal2 = ES.ToString(two);
+ const cal1 = ES.ToTemporalCalendarIdentifier(one);
+ const cal2 = ES.ToTemporalCalendarIdentifier(two);
if (cal1 !== cal2) {
throw new RangeError(`cannot ${errorMessageAction} of ${cal1} and ${cal2} calendars`);
}
},
ConsolidateCalendars: (one, two) => {
if (one === two) return two;
- const sOne = ES.ToString(one);
- const sTwo = ES.ToString(two);
+ const sOne = ES.ToTemporalCalendarIdentifier(one);
+ const sTwo = ES.ToTemporalCalendarIdentifier(two);
if (sOne === sTwo || sOne === 'iso8601') {
return two;
} else if (sTwo === 'iso8601') {
@@ -2372,7 +2372,7 @@ export const ES = ObjectAssign({}, ES2022, {
const day = ES.ISODateTimePartString(GetSlot(monthDay, ISO_DAY));
let resultString = `${month}-${day}`;
const calendar = GetSlot(monthDay, CALENDAR);
- const calendarID = ES.ToString(calendar);
+ const calendarID = ES.ToTemporalCalendarIdentifier(calendar);
if (showCalendar === 'always' || showCalendar === 'critical' || calendarID !== 'iso8601') {
const year = ES.ISOYearString(GetSlot(monthDay, ISO_YEAR));
resultString = `${year}-${resultString}`;
@@ -2386,7 +2386,7 @@ export const ES = ObjectAssign({}, ES2022, {
const month = ES.ISODateTimePartString(GetSlot(yearMonth, ISO_MONTH));
let resultString = `${year}-${month}`;
const calendar = GetSlot(yearMonth, CALENDAR);
- const calendarID = ES.ToString(calendar);
+ const calendarID = ES.ToTemporalCalendarIdentifier(calendar);
if (showCalendar === 'always' || showCalendar === 'critical' || calendarID !== 'iso8601') {
const day = ES.ISODateTimePartString(GetSlot(yearMonth, ISO_DAY));
resultString += `-${day}`;
diff --git a/polyfill/lib/intl.mjs b/polyfill/lib/intl.mjs
index 3d471b4bc1..60297c9529 100644
--- a/polyfill/lib/intl.mjs
+++ b/polyfill/lib/intl.mjs
@@ -392,7 +392,7 @@ function extractOverrides(temporalObj, main) {
const isoYear = GetSlot(temporalObj, ISO_YEAR);
const isoMonth = GetSlot(temporalObj, ISO_MONTH);
const referenceISODay = GetSlot(temporalObj, ISO_DAY);
- const calendar = ES.ToString(GetSlot(temporalObj, CALENDAR));
+ const calendar = ES.ToTemporalCalendarIdentifier(GetSlot(temporalObj, CALENDAR));
if (calendar !== main[CAL_ID]) {
throw new RangeError(
`cannot format PlainYearMonth with calendar ${calendar} in locale with calendar ${main[CAL_ID]}`
@@ -409,7 +409,7 @@ function extractOverrides(temporalObj, main) {
const referenceISOYear = GetSlot(temporalObj, ISO_YEAR);
const isoMonth = GetSlot(temporalObj, ISO_MONTH);
const isoDay = GetSlot(temporalObj, ISO_DAY);
- const calendar = ES.ToString(GetSlot(temporalObj, CALENDAR));
+ const calendar = ES.ToTemporalCalendarIdentifier(GetSlot(temporalObj, CALENDAR));
if (calendar !== main[CAL_ID]) {
throw new RangeError(
`cannot format PlainMonthDay with calendar ${calendar} in locale with calendar ${main[CAL_ID]}`
@@ -426,7 +426,7 @@ function extractOverrides(temporalObj, main) {
const isoYear = GetSlot(temporalObj, ISO_YEAR);
const isoMonth = GetSlot(temporalObj, ISO_MONTH);
const isoDay = GetSlot(temporalObj, ISO_DAY);
- const calendar = ES.ToString(GetSlot(temporalObj, CALENDAR));
+ const calendar = ES.ToTemporalCalendarIdentifier(GetSlot(temporalObj, CALENDAR));
if (calendar !== 'iso8601' && calendar !== main[CAL_ID]) {
throw new RangeError(`cannot format PlainDate with calendar ${calendar} in locale with calendar ${main[CAL_ID]}`);
}
@@ -447,7 +447,7 @@ function extractOverrides(temporalObj, main) {
const millisecond = GetSlot(temporalObj, ISO_MILLISECOND);
const microsecond = GetSlot(temporalObj, ISO_MICROSECOND);
const nanosecond = GetSlot(temporalObj, ISO_NANOSECOND);
- const calendar = ES.ToString(GetSlot(temporalObj, CALENDAR));
+ const calendar = ES.ToTemporalCalendarIdentifier(GetSlot(temporalObj, CALENDAR));
if (calendar !== 'iso8601' && calendar !== main[CAL_ID]) {
throw new RangeError(
`cannot format PlainDateTime with calendar ${calendar} in locale with calendar ${main[CAL_ID]}`
@@ -475,7 +475,7 @@ function extractOverrides(temporalObj, main) {
}
if (ES.IsTemporalZonedDateTime(temporalObj)) {
- const calendar = ES.ToString(GetSlot(temporalObj, CALENDAR));
+ const calendar = ES.ToTemporalCalendarIdentifier(GetSlot(temporalObj, CALENDAR));
if (calendar !== 'iso8601' && calendar !== main[CAL_ID]) {
throw new RangeError(
`cannot format ZonedDateTime with calendar ${calendar} in locale with calendar ${main[CAL_ID]}`
diff --git a/spec/calendar.html b/spec/calendar.html
index b953ef5887..5d80e7411c 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -651,14 +651,13 @@
It returns a string with a calendar annotation suitable for concatenating to the end of an ISO 8601 string.
Depending on the given _calendar_ and the value of _showCalendar_, the string may be empty if no calendar annotation need be included.
- This operation may invoke an observable ToString operation on _calendarObject_, but not if _showCalendar_ is *"never"*.
+ This operation may invoke an observable Get operation on _calendar_ if it is a custom calendar, but not if _showCalendar_ is *"never"*.
1. If _showCalendar_ is *"never"*, return the empty String.
- 1. Let _calendarObject_ be ToTemporalCalendarObject(_calendar_).
- 1. Let _calendarID_ be ? ToString(_calendarObject_).
- 1. Return FormatCalendarAnnotation(_calendarID_, _showCalendar_).
+ 1. Let _calendarIdentifier_ be ? ToTemporalCalendarIdentifier(_calendar_).
+ 1. Return FormatCalendarAnnotation(_calendarIdentifier_, _showCalendar_).
@@ -693,8 +692,8 @@ CalendarEquals ( _one_, _two_ )
1. If _one_ and _two_ are the same Object value, return *true*.
- 1. Let _calendarOne_ be ? ToString(_one_).
- 1. Let _calendarTwo_ be ? ToString(_two_).
+ 1. Let _calendarOne_ be ? ToTemporalCalendarIdentifier(_one_).
+ 1. Let _calendarTwo_ be ? ToTemporalCalendarIdentifier(_two_).
1. If _calendarOne_ is _calendarTwo_, return *true*.
1. Return *false*.
@@ -709,8 +708,8 @@ ConsolidateCalendars ( _one_, _two_ )
1. If _one_ and _two_ are the same Object value, return _two_.
- 1. Let _calendarOne_ be ? ToString(_one_).
- 1. Let _calendarTwo_ be ? ToString(_two_).
+ 1. Let _calendarOne_ be ? ToTemporalCalendarIdentifier(_one_).
+ 1. Let _calendarTwo_ be ? ToTemporalCalendarIdentifier(_two_).
1. If _calendarOne_ is _calendarTwo_, return _two_.
1. If _calendarOne_ is *"iso8601"*, return _two_.
1. If _calendarTwo_ is *"iso8601"*, return _one_.
diff --git a/spec/intl.html b/spec/intl.html
index b10ee66d8f..ceac000a13 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -756,14 +756,9 @@ HandleDateTimeTemporalDate ( _dateTimeFormat_, _temporalDate_ )
1. Assert: _temporalDate_ has an [[InitializedTemporalDate]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainDatePattern]].
- 1. Let _calendar_ be ? ToString(_temporalDate_.[[Calendar]]).
- 1. If _calendar_ is _dateTimeFormat_.[[Calendar]], then
- 1. Let _calendarOverride_ be _temporalDate_.[[Calendar]].
- 1. Else if _calendar_ is *"iso8601"*, then
- 1. Let _calendarOverride_ be _dateTimeFormat_.[[Calendar]].
- 1. Else,
- 1. Throw a *RangeError* exception.
- 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 12, 0, 0, 0, 0, 0, _calendarOverride_).
+ 1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_temporalDate_.[[Calendar]]).
+ 1. If _calendar_ is not _dateTimeFormat_.[[Calendar]] or *"iso8601"*, throw a *RangeError* exception.
+ 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 12, 0, 0, 0, 0, 0, _dateTimeFormat_.[[Calendar]]).
1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
@@ -786,10 +781,10 @@ HandleDateTimeTemporalYearMonth ( _dateTimeFormat_, _temporalYearMonth_ )
1. Assert: _temporalYearMonth_ has an [[InitializedTemporalYearMonth]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainYearMonthPattern]].
- 1. Let _calendar_ be ? ToString(_temporalYearMonth_.[[Calendar]]).
+ 1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_temporalYearMonth_.[[Calendar]]).
1. If _calendar_ is not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
- 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalYearMonth_.[[ISOYear]], _temporalYearMonth_.[[ISOMonth]], _temporalYearMonth_.[[ISODay]], 12, 0, 0, 0, 0, 0, _temporalYearMonth_.[[Calendar]]).
+ 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalYearMonth_.[[ISOYear]], _temporalYearMonth_.[[ISOMonth]], _temporalYearMonth_.[[ISODay]], 12, 0, 0, 0, 0, 0, _dateTimeFormat_.[[Calendar]]).
1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
@@ -813,10 +808,10 @@ HandleDateTimeTemporalMonthDay ( _dateTimeFormat_, _temporalMonthDay_ )
1. Assert: _temporalMonthDay_ has an [[InitializedTemporalMonthDay]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainMonthDayPattern]].
- 1. Let _calendar_ be ? ToString(_temporalMonthDay_.[[Calendar]]).
+ 1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_temporalMonthDay_.[[Calendar]]).
1. If _calendar_ is not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
- 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalMonthDay_.[[ISOYear]], _temporalMonthDay_.[[ISOMonth]], _temporalMonthDay_.[[ISODay]], 12, 0, 0, 0, 0, 0, _temporalMonthDay_.[[Calendar]]).
+ 1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalMonthDay_.[[ISOYear]], _temporalMonthDay_.[[ISOMonth]], _temporalMonthDay_.[[ISODay]], 12, 0, 0, 0, 0, 0, _dateTimeFormat_.[[Calendar]]).
1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
@@ -864,7 +859,7 @@ HandleDateTimeTemporalDateTime ( _dateTimeFormat_, _dateTime_ )
1. Assert: _dateTime_ has an [[InitializedTemporalDateTime]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainDateTimePattern]].
- 1. Let _calendar_ be ? ToString(_dateTime_.[[Calendar]]).
+ 1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_dateTime_.[[Calendar]]).
1. If _calendar_ is not *"iso8601"* and not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
@@ -910,7 +905,7 @@ HandleDateTimeTemporalZonedDateTime ( _dateTimeFormat_, _zonedDateTime_ )
1. Assert: _zonedDateTime_ has an [[InitializedTemporalZonedDateTime]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalZonedDateTimePattern]].
- 1. Let _calendar_ be ? ToString(_zonedDateTime_.[[Calendar]]).
+ 1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_zonedDateTime_.[[Calendar]]).
1. If _calendar_ is not *"iso8601"* and not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
1. Let _timeZone_ be ? ToString(_zonedDateTime_.[[TimeZone]]).
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index f50aaa02c6..170a0d7ec5 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -433,11 +433,11 @@ TemporalMonthDayToString ( _monthDay_, _showCalendar_ )
1. Let _month_ be ToZeroPaddedDecimalString(_monthDay_.[[ISOMonth]], 2).
1. Let _day_ be ToZeroPaddedDecimalString(_monthDay_.[[ISODay]], 2).
1. Let _result_ be the string-concatenation of _month_, the code unit 0x002D (HYPHEN-MINUS), and _day_.
- 1. Let _calendarID_ be ? ToString(_monthDay_.[[Calendar]]).
- 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarID_ is not *"iso8601"*, then
+ 1. Let _calendarIdentifier_ be ? ToTemporalCalendarIdentifier(_monthDay_.[[Calendar]]).
+ 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarIdentifier_ is not *"iso8601"*, then
1. Let _year_ be ! PadISOYear(_monthDay_.[[ISOYear]]).
1. Set _result_ to the string-concatenation of _year_, the code unit 0x002D (HYPHEN-MINUS), and _result_.
- 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarID_, _showCalendar_).
+ 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarIdentifier_, _showCalendar_).
1. Set _result_ to the string-concatenation of _result_ and _calendarString_.
1. Return _result_.
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index 38ee85f929..b8f455932f 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -599,11 +599,11 @@ TemporalYearMonthToString ( _yearMonth_, _showCalendar_ )
1. Let _year_ be ! PadISOYear(_yearMonth_.[[ISOYear]]).
1. Let _month_ be ToZeroPaddedDecimalString(_yearMonth_.[[ISOMonth]], 2).
1. Let _result_ be the string-concatenation of _year_, the code unit 0x002D (HYPHEN-MINUS), and _month_.
- 1. Let _calendarID_ be ? ToString(_yearMonth_.[[Calendar]]).
- 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarID_ is not *"iso8601"*, then
+ 1. Let _calendarIdentifier_ be ? ToTemporalCalendarIdentifier(_yearMonth_.[[Calendar]]).
+ 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarIdentifier_ is not *"iso8601"*, then
1. Let _day_ be ToZeroPaddedDecimalString(_yearMonth_.[[ISODay]], 2).
1. Set _result_ to the string-concatenation of _result_, the code unit 0x002D (HYPHEN-MINUS), and _day_.
- 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarID_, _showCalendar_).
+ 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarIdentifier_, _showCalendar_).
1. Set _result_ to the string-concatenation of _result_ and _calendarString_.
1. Return _result_.
From facbe426cf6bb69d4f3c660601e10ee62a8f27bf Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Tue, 17 Jan 2023 16:36:35 -0800
Subject: [PATCH 07/14] =?UTF-8?q?Editorial:=20Rename=20ToTemporalCalendar?=
=?UTF-8?q?=20=E2=86=92=20ToTemporalCalendarSlotValue?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Likewise with GetTemporalCalendarWithISODefault. This reflects that what
comes out of these operations is not necessarily a Calendar object, but
could be a string identifier of a built-in calendar. It's described as "a
value suitable for storing in a Temporal object's [[Calendar]] slot".
ToTemporalCalendarWithISODefault is subsumed into
ToTemporalCalendarSlotValue.
---
polyfill/lib/calendar.mjs | 2 +-
polyfill/lib/ecmascript.mjs | 28 +++++++++----------
polyfill/lib/instant.mjs | 2 +-
polyfill/lib/now.mjs | 4 +--
polyfill/lib/plaindate.mjs | 4 +--
polyfill/lib/plaindatetime.mjs | 4 +--
polyfill/lib/plainmonthday.mjs | 2 +-
polyfill/lib/plainyearmonth.mjs | 2 +-
polyfill/lib/timezone.mjs | 2 +-
polyfill/lib/zoneddatetime.mjs | 4 +--
spec/abstractops.html | 2 +-
spec/calendar.html | 49 +++++++++++++++++----------------
spec/instant.html | 2 +-
spec/plaindate.html | 8 +++---
spec/plaindatetime.html | 6 ++--
spec/plainmonthday.html | 4 +--
spec/plainyearmonth.html | 4 +--
spec/temporal.html | 4 +--
spec/timezone.html | 2 +-
spec/zoneddatetime.html | 6 ++--
20 files changed, 71 insertions(+), 70 deletions(-)
diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs
index f11fbf2ff4..0b583a9be1 100644
--- a/polyfill/lib/calendar.mjs
+++ b/polyfill/lib/calendar.mjs
@@ -253,7 +253,7 @@ export class Calendar {
return ES.ToString(this);
}
static from(item) {
- const calendarSlotValue = ES.ToTemporalCalendar(item);
+ const calendarSlotValue = ES.ToTemporalCalendarSlotValue(item);
return ES.ToTemporalCalendarObject(calendarSlotValue);
}
}
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 34fd3f1b10..6c01faee6d 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -900,7 +900,7 @@ export const ES = ObjectAssign({}, ES2022, {
if (ES.Type(relativeTo) === 'Object') {
if (ES.IsTemporalZonedDateTime(relativeTo) || ES.IsTemporalDate(relativeTo)) return relativeTo;
if (ES.IsTemporalDateTime(relativeTo)) return ES.TemporalDateTimeToDate(relativeTo);
- calendar = ES.GetTemporalCalendarWithISODefault(relativeTo);
+ calendar = ES.GetTemporalCalendarSlotValueWithISODefault(relativeTo);
const fieldNames = ES.CalendarFields(calendar, [
'day',
'hour',
@@ -940,7 +940,7 @@ export const ES = ObjectAssign({}, ES2022, {
);
}
if (!calendar) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
}
if (timeZone === undefined) return ES.CreateTemporalDate(year, month, day, calendar);
timeZone = ES.ToTemporalTimeZone(timeZone);
@@ -1063,7 +1063,7 @@ export const ES = ObjectAssign({}, ES2022, {
GetSlot(item, CALENDAR)
);
}
- const calendar = ES.GetTemporalCalendarWithISODefault(item);
+ const calendar = ES.GetTemporalCalendarSlotValueWithISODefault(item);
const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']);
const fields = ES.PrepareTemporalFields(item, fieldNames, []);
return ES.CalendarDateFromFields(calendar, fields, options);
@@ -1116,7 +1116,7 @@ export const ES = ObjectAssign({}, ES2022, {
);
}
- calendar = ES.GetTemporalCalendarWithISODefault(item);
+ calendar = ES.GetTemporalCalendarSlotValueWithISODefault(item);
const fieldNames = ES.CalendarFields(calendar, [
'day',
'hour',
@@ -1140,7 +1140,7 @@ export const ES = ObjectAssign({}, ES2022, {
if (z) throw new RangeError('Z designator not supported for PlainDateTime');
ES.RejectDateTime(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond);
if (calendar === undefined) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
}
return ES.CreateTemporalDateTime(
year,
@@ -1194,7 +1194,7 @@ export const ES = ObjectAssign({}, ES2022, {
calendar = item.calendar;
calendarAbsent = calendar === undefined;
if (calendar === undefined) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
}
const fieldNames = ES.CalendarFields(calendar, ['day', 'month', 'monthCode', 'year']);
const fields = ES.PrepareTemporalFields(item, fieldNames, []);
@@ -1210,7 +1210,7 @@ export const ES = ObjectAssign({}, ES2022, {
ES.ToTemporalOverflow(options); // validate and ignore
let { month, day, referenceISOYear, calendar } = ES.ParseTemporalMonthDayString(ES.ToString(item));
if (calendar === undefined) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
if (referenceISOYear === undefined) {
ES.RejectISODate(1972, month, day);
@@ -1257,7 +1257,7 @@ export const ES = ObjectAssign({}, ES2022, {
ToTemporalYearMonth: (item, options) => {
if (ES.Type(item) === 'Object') {
if (ES.IsTemporalYearMonth(item)) return item;
- const calendar = ES.GetTemporalCalendarWithISODefault(item);
+ const calendar = ES.GetTemporalCalendarSlotValueWithISODefault(item);
const fieldNames = ES.CalendarFields(calendar, ['month', 'monthCode', 'year']);
const fields = ES.PrepareTemporalFields(item, fieldNames, []);
return ES.CalendarYearMonthFromFields(calendar, fields, options);
@@ -1266,7 +1266,7 @@ export const ES = ObjectAssign({}, ES2022, {
ES.ToTemporalOverflow(options); // validate and ignore
let { year, month, referenceISODay, calendar } = ES.ParseTemporalYearMonthString(ES.ToString(item));
if (calendar === undefined) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
if (referenceISODay === undefined) {
ES.RejectISODate(year, month, 1);
@@ -1356,7 +1356,7 @@ export const ES = ObjectAssign({}, ES2022, {
let offsetBehaviour = 'option';
if (ES.Type(item) === 'Object') {
if (ES.IsTemporalZonedDateTime(item)) return item;
- calendar = ES.GetTemporalCalendarWithISODefault(item);
+ calendar = ES.GetTemporalCalendarSlotValueWithISODefault(item);
const fieldNames = ES.CalendarFields(calendar, [
'day',
'hour',
@@ -1392,7 +1392,7 @@ export const ES = ObjectAssign({}, ES2022, {
const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
timeZone = new TemporalTimeZone(ianaName);
if (!calendar) calendar = 'iso8601';
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
matchMinute = true; // ISO strings may specify offset with less precision
disambiguation = ES.ToTemporalDisambiguation(options);
offsetOpt = ES.ToTemporalOffset(options, 'reject');
@@ -1847,7 +1847,7 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
- ToTemporalCalendar: (calendarLike) => {
+ ToTemporalCalendarSlotValue: (calendarLike) => {
if (ES.Type(calendarLike) === 'Object') {
if (ES.IsTemporalCalendar(calendarLike)) return calendarLike;
if (HasSlot(calendarLike, CALENDAR)) return GetSlot(calendarLike, CALENDAR);
@@ -1885,11 +1885,11 @@ export const ES = ObjectAssign({}, ES2022, {
if (!ES.IsBuiltinCalendar(calendar)) throw new RangeError(`invalid calendar identifier ${calendar}`);
return ES.ASCIILowercase(calendar);
},
- GetTemporalCalendarWithISODefault: (item) => {
+ GetTemporalCalendarSlotValueWithISODefault: (item) => {
if (HasSlot(item, CALENDAR)) return GetSlot(item, CALENDAR);
const { calendar } = item;
if (calendar === undefined) return 'iso8601';
- return ES.ToTemporalCalendar(calendar);
+ return ES.ToTemporalCalendarSlotValue(calendar);
},
ToTemporalCalendarIdentifier: (slotValue) => {
if (typeof slotValue === 'string') return slotValue;
diff --git a/polyfill/lib/instant.mjs b/polyfill/lib/instant.mjs
index 606c805cee..2dc2409395 100644
--- a/polyfill/lib/instant.mjs
+++ b/polyfill/lib/instant.mjs
@@ -137,7 +137,7 @@ export class Instant {
if (calendarLike === undefined) {
throw new TypeError('missing calendar property in toZonedDateTime');
}
- const calendar = ES.ToTemporalCalendar(calendarLike);
+ const calendar = ES.ToTemporalCalendarSlotValue(calendarLike);
const temporalTimeZoneLike = item.timeZone;
if (temporalTimeZoneLike === undefined) {
throw new TypeError('missing timeZone property in toZonedDateTime');
diff --git a/polyfill/lib/now.mjs b/polyfill/lib/now.mjs
index 74b9e7a68b..ad43b13d2c 100644
--- a/polyfill/lib/now.mjs
+++ b/polyfill/lib/now.mjs
@@ -7,7 +7,7 @@ const instant = () => {
};
const plainDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
- const calendar = ES.ToTemporalCalendar(calendarLike);
+ const calendar = ES.ToTemporalCalendarSlotValue(calendarLike);
const inst = instant();
return ES.GetPlainDateTimeFor(timeZone, inst, calendar);
};
@@ -18,7 +18,7 @@ const plainDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
};
const zonedDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
- const calendar = ES.ToTemporalCalendar(calendarLike);
+ const calendar = ES.ToTemporalCalendarSlotValue(calendarLike);
return ES.CreateTemporalZonedDateTime(ES.SystemUTCEpochNanoSeconds(), timeZone, calendar);
};
const zonedDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 693da71afb..6b809e1203 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -21,7 +21,7 @@ export class PlainDate {
isoYear = ES.ToIntegerWithTruncation(isoYear);
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
isoDay = ES.ToIntegerWithTruncation(isoDay);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
ES.CreateTemporalDateSlots(this, isoYear, isoMonth, isoDay, calendar);
}
@@ -108,7 +108,7 @@ export class PlainDate {
}
withCalendar(calendar) {
if (!ES.IsTemporalDate(this)) throw new TypeError('invalid receiver');
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
return new PlainDate(GetSlot(this, ISO_YEAR), GetSlot(this, ISO_MONTH), GetSlot(this, ISO_DAY), calendar);
}
add(temporalDurationLike, options = undefined) {
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index f540e4653d..ffb7dc4b61 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -41,7 +41,7 @@ export class PlainDateTime {
millisecond = millisecond === undefined ? 0 : ES.ToIntegerWithTruncation(millisecond);
microsecond = microsecond === undefined ? 0 : ES.ToIntegerWithTruncation(microsecond);
nanosecond = nanosecond === undefined ? 0 : ES.ToIntegerWithTruncation(nanosecond);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
ES.CreateTemporalDateTimeSlots(
this,
@@ -248,7 +248,7 @@ export class PlainDateTime {
}
withCalendar(calendar) {
if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
return new PlainDateTime(
GetSlot(this, ISO_YEAR),
GetSlot(this, ISO_MONTH),
diff --git a/polyfill/lib/plainmonthday.mjs b/polyfill/lib/plainmonthday.mjs
index 8665a5b330..f1265a2a19 100644
--- a/polyfill/lib/plainmonthday.mjs
+++ b/polyfill/lib/plainmonthday.mjs
@@ -12,7 +12,7 @@ export class PlainMonthDay {
constructor(isoMonth, isoDay, calendar = 'iso8601', referenceISOYear = 1972) {
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
isoDay = ES.ToIntegerWithTruncation(isoDay);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
referenceISOYear = ES.ToIntegerWithTruncation(referenceISOYear);
ES.CreateTemporalMonthDaySlots(this, isoMonth, isoDay, calendar, referenceISOYear);
diff --git a/polyfill/lib/plainyearmonth.mjs b/polyfill/lib/plainyearmonth.mjs
index 22980ebd82..78968daddd 100644
--- a/polyfill/lib/plainyearmonth.mjs
+++ b/polyfill/lib/plainyearmonth.mjs
@@ -12,7 +12,7 @@ export class PlainYearMonth {
constructor(isoYear, isoMonth, calendar = 'iso8601', referenceISODay = 1) {
isoYear = ES.ToIntegerWithTruncation(isoYear);
isoMonth = ES.ToIntegerWithTruncation(isoMonth);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
referenceISODay = ES.ToIntegerWithTruncation(referenceISODay);
ES.CreateTemporalYearMonthSlots(this, isoYear, isoMonth, calendar, referenceISODay);
diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs
index a4d59fb6ec..1c21f8b8b0 100644
--- a/polyfill/lib/timezone.mjs
+++ b/polyfill/lib/timezone.mjs
@@ -63,7 +63,7 @@ export class TimeZone {
getPlainDateTimeFor(instant, calendar = 'iso8601') {
if (!ES.IsTemporalTimeZone(this)) throw new TypeError('invalid receiver');
instant = ES.ToTemporalInstant(instant);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
return ES.GetPlainDateTimeFor(this, instant, calendar);
}
getInstantFor(dateTime, options = undefined) {
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 11f2a39bae..1668af3157 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -34,7 +34,7 @@ export class ZonedDateTime {
}
epochNanoseconds = ES.ToBigInt(epochNanoseconds);
timeZone = ES.ToTemporalTimeZone(timeZone);
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
ES.CreateTemporalZonedDateTimeSlots(this, epochNanoseconds, timeZone, calendar);
}
@@ -305,7 +305,7 @@ export class ZonedDateTime {
}
withCalendar(calendar) {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
- calendar = ES.ToTemporalCalendar(calendar);
+ calendar = ES.ToTemporalCalendarSlotValue(calendar);
return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), GetSlot(this, TIME_ZONE), calendar);
}
add(temporalDurationLike, options = undefined) {
diff --git a/spec/abstractops.html b/spec/abstractops.html
index c3aaffe79b..6d3b3f6db8 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -482,7 +482,7 @@ ToRelativeTemporalObject ( _options_ )
1. Return _value_.
1. If _value_ has an [[InitializedTemporalDateTime]] internal slot, then
1. Return ! CreateTemporalDate(_value_.[[ISOYear]], _value_.[[ISOMonth]], _value_.[[ISODay]], _value_.[[Calendar]]).
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_value_).
+ 1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_value_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »).
1. Append *"timeZone"* to _fieldNames_.
1. Append *"offset"* to _fieldNames_.
diff --git a/spec/calendar.html b/spec/calendar.html
index 5d80e7411c..ed0333bb78 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -478,17 +478,24 @@
-
+
- ToTemporalCalendar (
+ ToTemporalCalendarSlotValue (
_temporalCalendarLike_: an ECMAScript value,
+ optional _default_: a String,
): either a normal completion containing either a String or an Object, or a throw completion
+ 1. If _temporalCalendarLike_ is *undefined* and _default_ is present, then
+ 1. Assert: IsBuiltinCalendar(_default_) is *true*.
+ 1. Return _default_.
1. If Type(_temporalCalendarLike_) is Object, then
1. If _temporalCalendarLike_ has an [[InitializedTemporalCalendar]] internal slot, then
1. Return _temporalCalendarLike_.
@@ -507,30 +514,24 @@
-
- ToTemporalCalendarWithISODefault ( _temporalCalendarLike_ )
-
- The abstract operation ToTemporalCalendarWithISODefault converts a value into an Object suitable for use as a calendar.
- If the value is *undefined*, the ISO 8601 calendar is returned.
-
-
- 1. If _temporalCalendarLike_ is *undefined*, then
- 1. Return *"iso8601"*.
- 1. Return ? ToTemporalCalendar(_temporalCalendarLike_).
-
-
-
-
- GetTemporalCalendarWithISODefault ( _item_ )
-
- The abstract operation GetTemporalCalendarWithISODefault looks for a `calendar` property on the given _item_ and converts its value to an Object suitable for use as a calendar.
- If no such property is present, the ISO 8601 calendar is returned.
-
+
+
+ GetTemporalCalendarSlotValueWithISODefault (
+ _item_: an Object,
+ ): either a normal completion containing either a String or an Object, or a throw completion
+
+
1. If _item_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _item_.[[Calendar]].
1. Let _calendarLike_ be ? Get(_item_, *"calendar"*).
- 1. Return ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Return ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
@@ -1008,7 +1009,7 @@ Temporal.Calendar.from ( _calendarLike_ )
The `Temporal.Calendar.from` function performs the following steps when called:
- 1. Let _calendarSlotValue_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendarSlotValue_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Return ToTemporalCalendarObject(_calendarSlotValue_).
diff --git a/spec/instant.html b/spec/instant.html
index cd1f1341cc..7ae7bd51a3 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -390,7 +390,7 @@ Temporal.Instant.prototype.toZonedDateTime ( _item_ )
1. Let _calendarLike_ be ? Get(_item_, *"calendar"*).
1. If _calendarLike_ is *undefined*, then
1. Throw a *TypeError* exception.
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Let _temporalTimeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Throw a *TypeError* exception.
diff --git a/spec/plaindate.html b/spec/plaindate.html
index be1c8f3214..8a12abb68a 100644
--- a/spec/plaindate.html
+++ b/spec/plaindate.html
@@ -35,7 +35,7 @@ Temporal.PlainDate ( _isoYear_, _isoMonth_, _isoDay_ [ , _calendarLike_ ] )<
1. Let _y_ be ? ToIntegerWithTruncation(_isoYear_).
1. Let _m_ be ? ToIntegerWithTruncation(_isoMonth_).
1. Let _d_ be ? ToIntegerWithTruncation(_isoDay_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Return ? CreateTemporalDate(_y_, _m_, _d_, _calendar_, NewTarget).
@@ -426,7 +426,7 @@ Temporal.PlainDate.prototype.withCalendar ( _calendarLike_ )
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Return ! CreateTemporalDate(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], _calendar_).
@@ -751,7 +751,7 @@ ToTemporalDate ( _item_ [ , _options_ ] )
1. If _item_ has an [[InitializedTemporalDateTime]] internal slot, then
1. Perform ? ToTemporalOverflow(_options_).
1. Return ! CreateTemporalDate(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], _item_.[[Calendar]]).
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ 1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_item_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»).
1. Return ? CalendarDateFromFields(_calendar_, _fields_, _options_).
@@ -759,7 +759,7 @@ ToTemporalDate ( _item_ [ , _options_ ] )
1. Let _string_ be ? ToString(_item_).
1. Let _result_ be ? ParseTemporalDateString(_string_).
1. Assert: IsValidISODate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]]) is *true*.
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_result_.[[Calendar]]).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_result_.[[Calendar]], *"iso8601"*).
1. Return ? CreateTemporalDate(_result_.[[Year]], _result_.[[Month]], _result_.[[Day]], _calendar_).
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index 321b737f99..81d97372bc 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -40,7 +40,7 @@ Temporal.PlainDateTime ( _isoYear_, _isoMonth_, _isoDay_ [ , _hour_ [ , _min
1. If _millisecond_ is *undefined*, set _millisecond_ to 0; else set _millisecond_ to ? ToIntegerWithTruncation(_millisecond_).
1. If _microsecond_ is *undefined*, set _microsecond_ to 0; else set _microsecond_ to ? ToIntegerWithTruncation(_microsecond_).
1. If _nanosecond_ is *undefined*, set _nanosecond_ to 0; else set _nanosecond_ to ? ToIntegerWithTruncation(_nanosecond_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Return ? CreateTemporalDateTime(_isoYear_, _isoMonth_, _isoDay_, _hour_, _minute_, _second_, _millisecond_, _microsecond_, _nanosecond_, _calendar_, NewTarget).
@@ -449,7 +449,7 @@ Temporal.PlainDateTime.prototype.withCalendar ( _calendarLike_ )
1. Let _dateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Return ? CreateTemporalDateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _calendar_).
@@ -910,7 +910,7 @@ ToTemporalDateTime ( _item_ [ , _options_ ] )
1. If _item_ has an [[InitializedTemporalDate]] internal slot, then
1. Perform ? ToTemporalOverflow(_options_).
1. Return ? CreateTemporalDateTime(_item_.[[ISOYear]], _item_.[[ISOMonth]], _item_.[[ISODay]], 0, 0, 0, 0, 0, 0, _item_.[[Calendar]]).
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ 1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_item_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »).
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»).
1. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html
index 170a0d7ec5..dea7491fe3 100644
--- a/spec/plainmonthday.html
+++ b/spec/plainmonthday.html
@@ -35,7 +35,7 @@ Temporal.PlainMonthDay ( _isoMonth_, _isoDay_ [ , _calendarLike_ [ , _refere
1. Set _referenceISOYear_ to *1972*𝔽.
1. Let _m_ be ? ToIntegerWithTruncation(_isoMonth_).
1. Let _d_ be ? ToIntegerWithTruncation(_isoDay_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Let _ref_ be ? ToIntegerWithTruncation(_referenceISOYear_).
1. Return ? CreateTemporalMonthDay(_m_, _d_, _calendar_, _ref_, NewTarget).
@@ -373,7 +373,7 @@ ToTemporalMonthDay ( _item_ [ , _options_ ] )
1. Let _calendarAbsent_ be *true*.
1. Else,
1. Let _calendarAbsent_ be *false*.
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»).
1. Let _month_ be ? Get(_fields_, *"month"*).
diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html
index b8f455932f..c0bec3c945 100644
--- a/spec/plainyearmonth.html
+++ b/spec/plainyearmonth.html
@@ -35,7 +35,7 @@ Temporal.PlainYearMonth ( _isoYear_, _isoMonth_ [ , _calendarLike_ [ , _refe
1. Set _referenceISODay_ to *1*𝔽.
1. Let _y_ be ? ToIntegerWithTruncation(_isoYear_).
1. Let _m_ be ? ToIntegerWithTruncation(_isoMonth_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Let _ref_ be ? ToIntegerWithTruncation(_referenceISODay_).
1. Return ? CreateTemporalYearMonth(_y_, _m_, _calendar_, _ref_, NewTarget).
@@ -492,7 +492,7 @@ ToTemporalYearMonth ( _item_ [ , _options_ ] )
1. If Type(_item_) is Object, then
1. If _item_ has an [[InitializedTemporalYearMonth]] internal slot, then
1. Return _item_.
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ 1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_item_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"month"*, *"monthCode"*, *"year"* »).
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, «»).
1. Return ? CalendarYearMonthFromFields(_calendar_, _fields_, _options_).
diff --git a/spec/temporal.html b/spec/temporal.html
index a3ff783295..b9ca518d36 100644
--- a/spec/temporal.html
+++ b/spec/temporal.html
@@ -223,7 +223,7 @@ SystemDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. Let _timeZone_ be DefaultTimeZone().
1. Else,
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Let _instant_ be ! SystemInstant().
1. Return ? GetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
@@ -236,7 +236,7 @@ SystemZonedDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. Let _timeZone_ be DefaultTimeZone().
1. Else,
1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Let _ns_ be ! SystemUTCEpochNanoseconds().
1. Return ! CreateTemporalZonedDateTime(_ns_, _timeZone_, _calendar_).
diff --git a/spec/timezone.html b/spec/timezone.html
index 16f397aeb8..e057791b75 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -230,7 +230,7 @@ Temporal.TimeZone.prototype.getPlainDateTimeFor ( _instant_ [ , _calendarLik
1. Let _timeZone_ be the *this* value.
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
1. Set _instant_ to ? ToTemporalInstant(_instant_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Return ? GetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 0aa423e420..2a247efe6a 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -36,7 +36,7 @@ Temporal.ZonedDateTime ( _epochNanoseconds_, _timeZoneLike_ [ , _calendarLik
1. Set _epochNanoseconds_ to ? ToBigInt(_epochNanoseconds_).
1. If ! IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneLike_).
- 1. Let _calendar_ be ? ToTemporalCalendarWithISODefault(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Return ? CreateTemporalZonedDateTime(_epochNanoseconds_, _timeZone_, _calendar_, NewTarget).
@@ -668,7 +668,7 @@ Temporal.ZonedDateTime.prototype.withCalendar ( _calendarLike_ )
1. Let _zonedDateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
- 1. Let _calendar_ be ? ToTemporalCalendar(_calendarLike_).
+ 1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Return ! CreateTemporalZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _calendar_).
@@ -1141,7 +1141,7 @@
1. If Type(_item_) is Object, then
1. If _item_ has an [[InitializedTemporalZonedDateTime]] internal slot, then
1. Return _item_.
- 1. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
+ 1. Let _calendar_ be ? GetTemporalCalendarSlotValueWithISODefault(_item_).
1. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"hour"*, *"microsecond"*, *"millisecond"*, *"minute"*, *"month"*, *"monthCode"*, *"nanosecond"*, *"second"*, *"year"* »).
1. Append *"timeZone"* to _fieldNames_.
1. Append *"offset"* to _fieldNames_.
From e9f3efa01eadd33d35d8031b561ca20260683c57 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Fri, 20 Jan 2023 13:32:24 -0800
Subject: [PATCH 08/14] Normative: Change Calendar.prototype.toJSON not to call
toString
The toJSON method should return the value in the internal slot, instead of
making an observable call to toString.
See: #1808
---
polyfill/lib/calendar.mjs | 2 +-
spec/calendar.html | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/polyfill/lib/calendar.mjs b/polyfill/lib/calendar.mjs
index 0b583a9be1..7b9121406c 100644
--- a/polyfill/lib/calendar.mjs
+++ b/polyfill/lib/calendar.mjs
@@ -250,7 +250,7 @@ export class Calendar {
}
toJSON() {
if (!ES.IsTemporalCalendar(this)) throw new TypeError('invalid receiver');
- return ES.ToString(this);
+ return GetSlot(this, CALENDAR_ID);
}
static from(item) {
const calendarSlotValue = ES.ToTemporalCalendarSlotValue(item);
diff --git a/spec/calendar.html b/spec/calendar.html
index ed0333bb78..42edf0e41c 100644
--- a/spec/calendar.html
+++ b/spec/calendar.html
@@ -1511,7 +1511,7 @@ Temporal.Calendar.prototype.toJSON ( )
1. Let _calendar_ be the *this* value.
1. Perform ? RequireInternalSlot(_calendar_, [[InitializedTemporalCalendar]]).
- 1. Return ? ToString(_calendar_).
+ 1. Return _calendar_.[[Identifier]].
From f8f99ac224083b69a94e9f73658d3c7149b857fc Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Wed, 18 Jan 2023 12:17:16 -0800
Subject: [PATCH 09/14] Normative: Store strings or objects in time zone slot,
remove getter
Refactor so that ZonedDateTime's [[TimeZone]] internal slot can now store
either a string (builtin time zone) or an object (custom time zone).
The .timeZone getter is replaced with a .timeZoneId getter that always
returns a string, and a .getTimeZone() method that always returns a new
object if the slot stored a string.
The operations ToTemporalTimeZoneIdentifier and ToTemporalTimeZoneObject
convert a [[TimeZone]] slot value to one or the other.
See: #1808
---
docs/cookbook.md | 3 +-
docs/cookbook/calculateDailyOccurrence.mjs | 4 +-
docs/cookbook/fromLegacyDate.mjs | 2 +-
docs/cookbook/getBusinessOpenStateText.mjs | 5 +-
docs/cookbook/localTimeForFutureEvents.mjs | 2 +-
docs/cookbook/meetingPlanner.js | 6 +-
docs/cookbook/nextWeeklyOccurrence.mjs | 4 +-
docs/cookbook/stockExchangeTimeZone.mjs | 8 +--
docs/cookbook/storageTank.js | 2 +-
docs/timezone.md | 7 +-
docs/zoneddatetime.md | 40 +++++++-----
polyfill/index.d.ts | 5 +-
polyfill/lib/ecmascript.mjs | 29 +++++++--
polyfill/lib/timezone.mjs | 4 +-
polyfill/lib/zoneddatetime.mjs | 8 ++-
spec/timezone.html | 74 ++++++++++++++++++----
spec/zoneddatetime.html | 20 ++++--
17 files changed, 159 insertions(+), 64 deletions(-)
diff --git a/docs/cookbook.md b/docs/cookbook.md
index fb02a4847c..68973846e5 100644
--- a/docs/cookbook.md
+++ b/docs/cookbook.md
@@ -84,7 +84,8 @@ Legacy `Date` represents an exact time, so it's straightforward to convert a `Te
### Time zone object from name
-`Temporal.TimeZone.from()` can convert an IANA time zone name into a `Temporal.TimeZone` object.
+`Temporal.TimeZone.from()` can convert an IANA time zone name into a `Temporal.TimeZone` object, if you need to call `Temporal.TimeZone` methods.
+Usually this is not necessary.
```javascript
diff --git a/docs/cookbook/calculateDailyOccurrence.mjs b/docs/cookbook/calculateDailyOccurrence.mjs
index 570f00f69a..afbad53541 100644
--- a/docs/cookbook/calculateDailyOccurrence.mjs
+++ b/docs/cookbook/calculateDailyOccurrence.mjs
@@ -5,7 +5,7 @@
*
* @param {Temporal.PlainDate} startDate - Starting date
* @param {Temporal.PlainTime} plainTime - Local time that event occurs at
- * @param {Temporal.TimeZone} timeZone - Time zone in which event is defined
+ * @param {string} timeZone - Time zone in which event is defined
*/
function* calculateDailyOccurrence(startDate, plainTime, timeZone) {
for (let date = startDate; ; date = date.add({ days: 1 })) {
@@ -16,7 +16,7 @@ function* calculateDailyOccurrence(startDate, plainTime, timeZone) {
// Daily meeting at 8 AM California time
const startDate = Temporal.PlainDate.from('2017-03-10');
const time = Temporal.PlainTime.from('08:00');
-const timeZone = Temporal.TimeZone.from('America/Los_Angeles');
+const timeZone = 'America/Los_Angeles';
const iter = calculateDailyOccurrence(startDate, time, timeZone);
assert.equal(iter.next().value.toString(), '2017-03-10T16:00:00Z');
diff --git a/docs/cookbook/fromLegacyDate.mjs b/docs/cookbook/fromLegacyDate.mjs
index 1626081a75..b6fdb202cc 100644
--- a/docs/cookbook/fromLegacyDate.mjs
+++ b/docs/cookbook/fromLegacyDate.mjs
@@ -32,7 +32,7 @@ assert.equal(zoned.epochMilliseconds, legacyDate.getTime());
const zoned2 = instant.toZonedDateTimeISO('Asia/Shanghai');
assert.equal(zoned2.epochMilliseconds, legacyDate.getTime());
-assert.equal(zoned2.timeZone.id, 'Asia/Shanghai');
+assert.equal(zoned2.timeZoneId, 'Asia/Shanghai');
// (And if the legacy Date instance was accessed using the
// getUTCFullYear(), getUTCMonth(), etc. methods, consider just
diff --git a/docs/cookbook/getBusinessOpenStateText.mjs b/docs/cookbook/getBusinessOpenStateText.mjs
index f8d34c2d68..18c6085dca 100644
--- a/docs/cookbook/getBusinessOpenStateText.mjs
+++ b/docs/cookbook/getBusinessOpenStateText.mjs
@@ -31,11 +31,12 @@ function getBusinessOpenStateText(now, businessHours, soonWindow) {
const index = (openDate.dayOfWeek + 7) % 7;
if (!businessHours[index]) continue;
+ const timeZone = now.timeZoneId;
const { open: openTime, close: closeTime } = businessHours[index];
- const open = openDate.toZonedDateTime({ plainTime: openTime, timeZone: now.timeZone });
+ const open = openDate.toZonedDateTime({ plainTime: openTime, timeZone });
const isWrap = Temporal.PlainTime.compare(closeTime, openTime) < 0;
const closeDate = isWrap ? openDate.add({ days: 1 }) : openDate;
- const close = closeDate.toZonedDateTime({ plainTime: closeTime, timeZone: now.timeZone });
+ const close = closeDate.toZonedDateTime({ plainTime: closeTime, timeZone });
if (inRange(now, open, close)) {
return compare(now, close.subtract(soonWindow)) >= 0 ? 'closing soon' : 'open';
diff --git a/docs/cookbook/localTimeForFutureEvents.mjs b/docs/cookbook/localTimeForFutureEvents.mjs
index eaa2f762c4..b11968c4ce 100644
--- a/docs/cookbook/localTimeForFutureEvents.mjs
+++ b/docs/cookbook/localTimeForFutureEvents.mjs
@@ -28,7 +28,7 @@ const tc39meetings = [
// To follow the meetings remotely from Tokyo, calculate the times you would
// need to join:
-const localTimeZone = Temporal.TimeZone.from('Asia/Tokyo');
+const localTimeZone = 'Asia/Tokyo';
const localTimes = tc39meetings.map(({ dateTime, timeZone }) => {
return Temporal.PlainDateTime.from(dateTime)
.toZonedDateTime(timeZone, { disambiguation: 'reject' })
diff --git a/docs/cookbook/meetingPlanner.js b/docs/cookbook/meetingPlanner.js
index bfa76fbc17..7e46c2d80d 100644
--- a/docs/cookbook/meetingPlanner.js
+++ b/docs/cookbook/meetingPlanner.js
@@ -3,9 +3,9 @@ const browserCalendar = new Intl.DateTimeFormat().resolvedOptions().calendar;
const now = Temporal.Now.zonedDateTime(browserCalendar);
const timeZones = [
{ name: 'Here', tz: now.timeZone },
- { name: 'New York', tz: Temporal.TimeZone.from('America/New_York') },
- { name: 'London', tz: Temporal.TimeZone.from('Europe/London') },
- { name: 'Tokyo', tz: Temporal.TimeZone.from('Asia/Tokyo') }
+ { name: 'New York', tz: 'America/New_York' },
+ { name: 'London', tz: 'Europe/London' },
+ { name: 'Tokyo', tz: 'Asia/Tokyo' }
];
// Start the table at midnight local time
diff --git a/docs/cookbook/nextWeeklyOccurrence.mjs b/docs/cookbook/nextWeeklyOccurrence.mjs
index 5c7284dbe0..3529aa5767 100644
--- a/docs/cookbook/nextWeeklyOccurrence.mjs
+++ b/docs/cookbook/nextWeeklyOccurrence.mjs
@@ -18,13 +18,13 @@ function nextWeeklyOccurrence(now, weekday, eventTime, eventTimeZone) {
nextOccurrence = nextOccurrence.add({ weeks: 1 });
}
- return nextOccurrence.withTimeZone(now.timeZone);
+ return nextOccurrence.withTimeZone(now.timeZoneId);
}
// "Weekly on Thursdays at 08:45 California time":
const weekday = 4;
const eventTime = Temporal.PlainTime.from('08:45');
-const eventTimeZone = Temporal.TimeZone.from('America/Los_Angeles');
+const eventTimeZone = 'America/Los_Angeles';
const rightBefore = Temporal.ZonedDateTime.from('2020-03-26T15:30+00:00[Europe/London]');
let next = nextWeeklyOccurrence(rightBefore, weekday, eventTime, eventTimeZone);
diff --git a/docs/cookbook/stockExchangeTimeZone.mjs b/docs/cookbook/stockExchangeTimeZone.mjs
index ee01a5de19..34a47e0e97 100644
--- a/docs/cookbook/stockExchangeTimeZone.mjs
+++ b/docs/cookbook/stockExchangeTimeZone.mjs
@@ -15,7 +15,7 @@
* market day.
* */
-const tz = Temporal.TimeZone.from('America/New_York');
+const tz = 'America/New_York';
const openTime = Temporal.PlainTime.from('09:30');
const closeTime = Temporal.PlainTime.from('16:00');
function isMarketOpenDate(date) {
@@ -187,20 +187,20 @@ zdt = Temporal.ZonedDateTime.from('2020-11-12T18:50-08:00[America/Los_Angeles]')
inNYSE = zdt.withTimeZone(tzNYSE);
isOpen = inNYSE.toPlainDateTime().toZonedDateTime(tzNYSE).equals(inNYSE);
assert.equal(isOpen, false);
-nextOpen = inNYSE.timeZone.getNextTransition(zdt.toInstant()).toZonedDateTimeISO(zdt.timeZone);
+nextOpen = inNYSE.getTimeZone().getNextTransition(zdt.toInstant()).toZonedDateTimeISO(zdt.timeZoneId);
assert.equal(nextOpen.toString(), '2020-11-13T06:30:00-08:00[America/Los_Angeles]');
zdt = Temporal.ZonedDateTime.from('2020-11-12T12:50-08:00[America/Los_Angeles]');
inNYSE = zdt.withTimeZone(tzNYSE);
isOpen = inNYSE.toPlainDateTime().toZonedDateTime(tzNYSE).equals(inNYSE);
assert.equal(isOpen, true);
-todayClose = inNYSE.timeZone.getNextTransition(zdt.toInstant()).toZonedDateTimeISO(zdt.timeZone);
+todayClose = inNYSE.getTimeZone().getNextTransition(zdt.toInstant()).toZonedDateTimeISO(zdt.timeZoneId);
assert.equal(todayClose.toString(), '2020-11-12T13:00:00-08:00[America/Los_Angeles]');
// 5. For any particular market date, what were the opening and closing clock times in NYC?
date = Temporal.PlainDate.from('2020-11-09');
openInstant = date.toZonedDateTime(tzNYSE).toInstant();
-closeInstant = date.toZonedDateTime(tzNYSE).timeZone.getNextTransition(openInstant);
+closeInstant = date.toZonedDateTime(tzNYSE).getTimeZone().getNextTransition(openInstant);
assert.equal(openInstant.toZonedDateTimeISO('America/New_York').toPlainTime().toString(), '09:30:00');
assert.equal(closeInstant.toZonedDateTimeISO('America/New_York').toPlainTime().toString(), '16:00:00');
diff --git a/docs/cookbook/storageTank.js b/docs/cookbook/storageTank.js
index 3a2698bbb9..708142cab1 100644
--- a/docs/cookbook/storageTank.js
+++ b/docs/cookbook/storageTank.js
@@ -3,7 +3,7 @@
// tankDataX is an array of Temporal.Instant, and tankDataY is an array of numbers.
// Show data starting from the most recent midnight in the tank's location (Stockholm)
-const tankTimeZone = Temporal.TimeZone.from('Europe/Stockholm');
+const tankTimeZone = 'Europe/Stockholm';
const labelFormatter = new Intl.DateTimeFormat(undefined, {
weekday: 'short',
hour: 'numeric',
diff --git a/docs/timezone.md b/docs/timezone.md
index 704cecdd9e..c1dbf58447 100644
--- a/docs/timezone.md
+++ b/docs/timezone.md
@@ -19,11 +19,10 @@ There are two ways to do this.
The recommended way is to create a class inheriting from `Temporal.TimeZone`.
You must use one of the built-in time zones as the "base time zone".
-In the class's constructor, call `super()` with the identifier of the base time zone.
+In the class's constructor, call `super()` with the identifier of a built-in time zone to serve as a base.
The class must override `toString()` to return its own identifier.
-Overriding `getOffsetNanosecondsFor()`, `getPossibleInstantsFor()`, `getNextTransition()`, and `getPreviousTransition()` is optional.
-If you don't override the optional members, then they will behave as in the base time zone.
-You don't need to override any other methods such as `getOffsetStringFor()` because they will call `getOffsetNanosecondsFor()`, `getPossibleInstantsFor()`, and `toString()` internally.
+Overriding all the other properties of `Temporal.TimeZone.prototype` is optional.
+Any property that is not overridden will behave as in the base time zone.
The other, more difficult, way to create a custom time zone is to create a plain object implementing the `Temporal.TimeZone` protocol, without subclassing.
The object must have at least `getOffsetNanosecondsFor()`, `getPossibleInstantsFor()`, and `toString()` methods.
diff --git a/docs/zoneddatetime.md b/docs/zoneddatetime.md
index 756b85b31a..f2ca9739e6 100644
--- a/docs/zoneddatetime.md
+++ b/docs/zoneddatetime.md
@@ -30,7 +30,7 @@ The `Temporal.ZonedDateTime` API is a superset of `Temporal.PlainDateTime`, whic
**Parameters:**
- `epochNanoseconds` (bigint): A number of nanoseconds.
-- `timeZone` (`Temporal.TimeZone` or plain object): The time zone in which the event takes place.
+- `timeZone` (string, `Temporal.TimeZone` instance, or plain object): The time zone in which the event takes place.
- `calendar` (optional string, `Temporal.Calendar` instance, or plain object): Calendar used to interpret dates and times.
**Returns:** a new `Temporal.ZonedDateTime` object.
@@ -41,15 +41,16 @@ Instead of the constructor, `Temporal.ZonedDateTime.from()` is preferred instead
The range of allowed values for this type is the same as the old-style JavaScript `Date`: 100 million (108) days before or after the Unix epoch.
This range covers approximately half a million years. If `epochNanoseconds` is outside of this range, a `RangeError` will be thrown.
+Usually `timeZone` will be a string containing the identifier of a built-in time zone, such as `'UTC'`, `'Europe/Madrid'`, or `'+05:30'`.
Usually `calendar` will be a string containing the identifier of a built-in calendar, such as `'islamic'` or `'gregory'`.
-Use an object if you need to supply [custom calendar behaviour](./calendar.md#custom-calendars).
+Use an object if you need to supply [custom calendar](./calendar.md#custom-calendars) or [custom time zone](./timezone.md#custom-time-zones) behaviour.
Usage examples:
```javascript
// UNIX epoch in California
-new Temporal.ZonedDateTime(0n, Temporal.TimeZone.from('America/Los_Angeles'), 'iso8601');
+new Temporal.ZonedDateTime(0n, 'America/Los_Angeles', 'iso8601');
// => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
new Temporal.ZonedDateTime(0n, 'America/Los_Angeles');
// => 1969-12-31T16:00:00-08:00[America/Los_Angeles]
@@ -413,9 +414,11 @@ Calendar-specific date/time values are NOT used in only a few places:
- In the values returned by the `getISOFields()` method which is explicitly used to provide ISO 8601 calendar values
- In arguments to the `Temporal.ZonedDateTime` constructor which is used for advanced use cases only
-### zonedDateTime.**timeZone** : Temporal.TimeZoneProtocol
+### zonedDateTime.**timeZoneId** : string
+
+The `timeZoneId` read-only property is the identifier of the persistent time zone of `zonedDateTime`.
+If `zonedDateTime` was created with a custom time zone object, this gives the `id` property of that object.
-The `timeZone` read-only property represents the persistent time zone of `zonedDateTime`.
By storing its time zone, `Temporal.ZonedDateTime` is able to use that time zone when deriving other values, e.g. to automatically perform DST adjustment when adding or subtracting time.
If a non-canonical time zone ID is used, it will be normalized by `Temporal` into its canonical name listed in the [IANA time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
@@ -437,29 +440,27 @@ To change the time zone while keeping the exact time constant, use `.withTimeZon
The time zone is a required property when creating `Temporal.ZonedDateTime` instances.
If you don't know the time zone of your underlying data, please use `Temporal.Instant` and/or `Temporal.PlainDateTime`, neither of which have awareness of time zones.
-Although this property is a `Temporal.TimeZoneProtocol` object (which is usually a `Temporal.TimeZone` except custom timezones), it will be automatically coerced to its string form (e.g. `"Europe/Paris"`) when displayed by `console.log()`, `JSON.stringify()`, `` `${zonedDateTime.timeZone}` ``, or other similar APIs.
-
Usage example:
```javascript
zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24-08:00[America/Los_Angeles]');
-`Time zone is: ${zdt.timeZone}`;
+`Time zone is: ${zdt.timeZoneId}`;
// => 'Time zone is: America/Los_Angeles'
-zdt.withTimeZone('Asia/Singapore').timeZone;
+zdt.withTimeZone('Asia/Singapore').timeZoneId;
// => Asia/Singapore
-zdt.withTimeZone('Asia/Chongqing').timeZone;
+zdt.withTimeZone('Asia/Chongqing').timeZoneId;
// => Asia/Shanghai
// (time zone IDs are normalized, e.g. Asia/Chongqing -> Asia/Shanghai)
-zdt.withTimeZone('+05:00').timeZone;
+zdt.withTimeZone('+05:00').timeZoneId;
// => +05:00
-zdt.withTimeZone('+05').timeZone;
+zdt.withTimeZone('+05').timeZoneId;
// => +05:00
// (normalized to canonical form)
-zdt.withTimeZone('utc').timeZone;
+zdt.withTimeZone('utc').timeZoneId;
// => UTC
// (normalized to canonical form which is uppercase)
-zdt.withTimeZone('GMT').timeZone;
+zdt.withTimeZone('GMT').timeZoneId;
// => UTC
// (normalized to canonical form)
```
@@ -1445,9 +1446,16 @@ zdt.toPlainTime(); // => 03:24:30
This method is mainly useful if you need an object on which to call calendar methods.
Most code will not need to use it.
-### zonedDateTime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, hour: number, minute: number, second: number, millisecond: number, microsecond: number, nanosecond: number, offset: string, timeZone: object, calendar: string | object }
+### zonedDateTime.**getTimeZone**(): object
+
+**Returns:** a `Temporal.TimeZone` instance or plain object representing the time zone in which `zonedDateTime` is reckoned.
+
+This method is mainly useful if you need an object on which to call time zone methods.
+Most code will not need to use it.
+
+### zonedDateTime.**getISOFields**(): { isoYear: number, isoMonth: number, isoDay: number, hour: number, minute: number, second: number, millisecond: number, microsecond: number, nanosecond: number, offset: string, timeZone: string | object, calendar: string | object }
-**Returns:** a plain object with properties expressing `zonedDateTime` in the ISO 8601 calendar, including all date/time fields as well as the `timeZone`, and `offset` properties, and the calendar in which `zonedDateTime` is reckoned.
+**Returns:** a plain object with properties expressing `zonedDateTime` in the ISO 8601 calendar, including all date/time fields as well as the `offset` property, and the calendar and time zone (which are usually strings, but may be objects) in which `zonedDateTime` is reckoned.
This is an advanced method that's mainly useful if you are implementing a custom calendar.
Most developers will not need to use it.
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index d3f5475ad2..091d573bd7 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -1230,7 +1230,7 @@ export namespace Temporal {
isoMicrosecond: number;
isoNanosecond: number;
offset: string;
- timeZone: TimeZoneProtocol;
+ timeZone: string | TimeZoneProtocol;
calendar: string | CalendarProtocol;
};
@@ -1256,7 +1256,7 @@ export namespace Temporal {
readonly millisecond: number;
readonly microsecond: number;
readonly nanosecond: number;
- readonly timeZone: TimeZoneProtocol;
+ readonly timeZoneId: string;
readonly calendarId: string;
readonly dayOfWeek: number;
readonly dayOfYear: number;
@@ -1307,6 +1307,7 @@ export namespace Temporal {
toPlainMonthDay(): Temporal.PlainMonthDay;
toPlainTime(): Temporal.PlainTime;
getCalendar(): CalendarProtocol;
+ getTimeZone(): TimeZoneProtocol;
getISOFields(): ZonedDateTimeISOFields;
toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;
toJSON(): string;
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 6c01faee6d..50c4f209b6 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -337,7 +337,9 @@ export const ES = ObjectAssign({}, ES2022, {
const { ianaName, offset, z } = ES.ParseTemporalTimeZoneString(stringIdent);
if (ianaName) return ES.GetCanonicalTimeZoneIdentifier(ianaName);
if (z) return 'UTC';
- return offset; // if !ianaName && !z then offset must be present
+ // if !ianaName && !z then offset must be present
+ const offsetNs = ES.ParseTimeZoneOffsetString(offset);
+ return ES.FormatTimeZoneOffsetString(offsetNs);
},
MaybeFormatCalendarAnnotation: (calendar, showCalendar) => {
if (showCalendar === 'never') return '';
@@ -1983,9 +1985,18 @@ export const ES = ObjectAssign({}, ES2022, {
}
}
const identifier = ES.ToString(temporalTimeZoneLike);
- const timeZone = ES.ParseTemporalTimeZone(identifier);
+ return ES.ParseTemporalTimeZone(identifier);
+ },
+ ToTemporalTimeZoneIdentifier: (slotValue) => {
+ if (typeof slotValue === 'string') return slotValue;
+ const result = slotValue.id;
+ if (typeof result !== 'string') throw new TypeError('timeZone.id should be a string');
+ return result;
+ },
+ ToTemporalTimeZoneObject: (slotValue) => {
+ if (ES.Type(slotValue) === 'Object') return slotValue;
const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
- return new TemporalTimeZone(timeZone);
+ return new TemporalTimeZone(slotValue);
},
TimeZoneEquals: (one, two) => {
if (one === two) return true;
@@ -2013,6 +2024,11 @@ export const ES = ObjectAssign({}, ES2022, {
);
},
GetOffsetNanosecondsFor: (timeZone, instant) => {
+ if (typeof timeZone === 'string') {
+ const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
+ timeZone = new TemporalTimeZone(timeZone);
+ return ES.Call(GetIntrinsic('%Temporal.TimeZone.prototype.getOffsetNanosecondsFor%'), timeZone, [instant]);
+ }
const getOffsetNanosecondsFor = ES.GetMethod(timeZone, 'getOffsetNanosecondsFor');
const offsetNs = ES.Call(getOffsetNanosecondsFor, timeZone, [instant]);
if (typeof offsetNs !== 'number') {
@@ -2195,7 +2211,12 @@ export const ES = ObjectAssign({}, ES2022, {
throw new Error(`assertion failed: invalid disambiguation value ${disambiguation}`);
},
GetPossibleInstantsFor: (timeZone, dateTime) => {
- let getPossibleInstantsFor = ES.GetMethod(timeZone, 'getPossibleInstantsFor');
+ if (typeof timeZone === 'string') {
+ const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
+ timeZone = new TemporalTimeZone(timeZone);
+ return ES.Call(GetIntrinsic('%Temporal.TimeZone.prototype.getPossibleInstantsFor%'), timeZone, [dateTime]);
+ }
+ const getPossibleInstantsFor = ES.GetMethod(timeZone, 'getPossibleInstantsFor');
const possibleInstants = ES.Call(getPossibleInstantsFor, timeZone, [dateTime]);
const result = [];
for (const instant of possibleInstants) {
diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs
index 1c21f8b8b0..7e5ebbda71 100644
--- a/polyfill/lib/timezone.mjs
+++ b/polyfill/lib/timezone.mjs
@@ -149,9 +149,11 @@ export class TimeZone {
return ES.ToString(this);
}
static from(item) {
- return ES.ToTemporalTimeZone(item);
+ const timeZoneSlotValue = ES.ToTemporalTimeZone(item);
+ return ES.ToTemporalTimeZoneObject(timeZoneSlotValue);
}
}
MakeIntrinsicClass(TimeZone, 'Temporal.TimeZone');
DefineIntrinsic('Temporal.TimeZone.prototype.getOffsetNanosecondsFor', TimeZone.prototype.getOffsetNanosecondsFor);
+DefineIntrinsic('Temporal.TimeZone.prototype.getPossibleInstantsFor', TimeZone.prototype.getPossibleInstantsFor);
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 1668af3157..7689e83ee9 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -42,9 +42,9 @@ export class ZonedDateTime {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
return ES.ToTemporalCalendarIdentifier(GetSlot(this, CALENDAR));
}
- get timeZone() {
+ get timeZoneId() {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
- return GetSlot(this, TIME_ZONE);
+ return ES.ToTemporalTimeZoneIdentifier(GetSlot(this, TIME_ZONE));
}
get year() {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
@@ -526,6 +526,10 @@ export class ZonedDateTime {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
return ES.ToTemporalCalendarObject(GetSlot(this, CALENDAR));
}
+ getTimeZone() {
+ if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
+ return ES.ToTemporalTimeZoneObject(GetSlot(this, TIME_ZONE));
+ }
static from(item, options = undefined) {
options = ES.GetOptionsObject(options);
diff --git a/spec/timezone.html b/spec/timezone.html
index e057791b75..3a7895f08b 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -151,7 +151,8 @@ Temporal.TimeZone.from ( _item_ )
This function performs the following steps when called:
- 1. Return ? ToTemporalTimeZone(_item_).
+ 1. Let _slotValue_ be ? ToTemporalTimeZone(_item_).
+ 1. Return ToTemporalTimeZoneObject(_slotValue_).
@@ -563,18 +564,59 @@ ToTemporalTimeZone ( _temporalTimeZoneLike_ )
1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_identifier_).
1. If _parseResult_.[[Name]] is not *undefined*, then
1. Let _name_ be _parseResult_.[[Name]].
- 1. If IsTimeZoneOffsetString(_name_) is *false*, then
- 1. If IsAvailableTimeZoneName(_name_) is *false*, throw a *RangeError* exception.
- 1. Set _name_ to ! CanonicalizeTimeZoneName(_name_).
- 1. Return ! CreateTemporalTimeZone(_name_).
- 1. If _parseResult_.[[Z]] is *true*, return ! CreateTemporalTimeZone(*"UTC"*).
- 1. Return ! CreateTemporalTimeZone(_parseResult_.[[OffsetString]]).
+ 1. If IsTimeZoneOffsetString(_name_) is *true*, then
+ 1. Let _offsetNanoseconds_ be ParseTimeZoneOffsetString(_name_).
+ 1. Return ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
+ 1. If IsAvailableTimeZoneName(_name_) is *false*, throw a *RangeError* exception.
+ 1. Return ! CanonicalizeTimeZoneName(_name_).
+ 1. If _parseResult_.[[Z]] is *true*, return *"UTC"*.
+ 1. Let _offsetNanoseconds_ be ParseTimeZoneOffsetString(_parseResult_.[[OffsetString]]).
+ 1. Return ! FormatTimeZoneOffsetString(_offsetNanoseconds_).
+
+
+
+
+
+ ToTemporalTimeZoneIdentifier (
+ _timeZoneSlotValue_: a String or Object,
+ ): either a normal completion containing a String, or a throw completion
+
+
+
+ 1. If _timeZoneSlotValue_ is a String, then
+ 1. Assert: IsAvailableTimeZoneName(_timeZoneSlotValue_) is *true*.
+ 1. Return _timeZoneSlotValue_.
+ 1. Let _identifier_ be ? Get(_timeZoneSlotValue_, *"id"*).
+ 1. If _identifier_ is not a String, throw a *TypeError* exception.
+ 1. Return _identifier_.
+
+
+
+
+
+ ToTemporalTimeZoneObject (
+ _timeZoneSlotValue_: a String or Object,
+ ): an Object
+
+
+
+ 1. If _timeZoneSlotValue_ is an Object, return _timeZoneSlotValue_.
+ 1. Return ! CreateTemporalTimeZone(_timeZoneSlotValue_).
GetOffsetNanosecondsFor ( _timeZone_, _instant_ )
+ 1. If _timeZone_ is a String, then
+ 1. Set _timeZone_ to ! CreateTemporalTimeZone(_timeZone_).
+ 1. Return ? Call(%Temporal.TimeZone.prototype.getOffsetNanosecondsFor%, _timeZone_, « _instant_ »).
1. Let _getOffsetNanosecondsFor_ be ? GetMethod(_timeZone_, *"getOffsetNanosecondsFor"*).
1. Let _offsetNanoseconds_ be ? Call(_getOffsetNanosecondsFor_, _timeZone_, « _instant_ »).
1. If Type(_offsetNanoseconds_) is not Number, throw a *TypeError* exception.
@@ -588,7 +630,7 @@ GetOffsetNanosecondsFor ( _timeZone_, _instant_ )
GetOffsetStringFor (
- _timeZone_: an Object,
+ _timeZone_: a String or Object,
_instant_: a Temporal.Instant,
): either a normal completion containing a String, or an abrupt completion
@@ -596,7 +638,7 @@
description
This operation is the internal implementation of the `Temporal.TimeZone.prototype.getOffsetStringFor` method.
- It observably calls the given _timeZone_'s `getOffsetNanosecondsFor` method.
+ If the given _timeZone_ is an Object, it observably calls _timeZone_'s `getOffsetNanosecondsFor` method.
@@ -608,7 +650,7 @@
GetPlainDateTimeFor (
- _timeZone_: an Object,
+ _timeZone_: a String or Object,
_instant_: a Temporal.Instant,
_calendar_: a String or Object,
): either a normal completion containing a Temporal.PlainDateTime, or an abrupt completion
@@ -617,7 +659,7 @@
description
This operation is the internal implementation if the `Temporal.TimeZone.prototype.getPlainDateTimeFor` method.
- It observably calls the given _timeZone_'s `getOffsetNanosecondsFor` method.
+ If the given _timeZone_ is an Object, it observably calls _timeZone_'s `getOffsetNanosecondsFor` method.
@@ -631,7 +673,7 @@
GetInstantFor (
- _timeZone_: an Object,
+ _timeZone_: a String or Object,
_dateTime_: a Temporal.PlainDateTime,
_disambiguation_: *"compatible"*, *"earlier"*, *"later"*, or *"reject"*,
): either a normal completion containing a Temporal.Instant, or an abrupt completion
@@ -640,7 +682,7 @@
description
It is the internal implementation of the `Temporal.TimeZone.prototype.getInstantFor` method.
- It observably calls the given _timeZone_'s `getPossibleInstantsFor` method at least once.
+ If the given _timeZone_ is an Object, it observably calls _timeZone_'s `getPossibleInstantsFor` method at least once.
If that call returns an empty array and _disambiguation_ is not *"reject"*, it observably calls the time zone's `getOffsetNanosecondsFor` method twice, and `getPossibleInstantsFor` an additional time.
@@ -656,7 +698,7 @@ DisambiguatePossibleInstants ( _possibleInstants_, _timeZone_, _dateTime_, _
The abstract operation DisambiguatePossibleInstants chooses from a List of possible `Temporal.Instant` instances the one indicated by the _disambiguation_ parameter.
- The _possibleInstants_ List may be empty, in which case it observably calls the time zone's `getOffsetNanosecondsFor` method twice, and `getPossibleInstantsFor` once, if _disambiguation_ is not *"reject"*.
+ The _possibleInstants_ List may be empty, in which case it observably calls the time zone's `getOffsetNanosecondsFor` method twice, and `getPossibleInstantsFor` once, if _disambiguation_ is not *"reject"* and the given _timeZone_ is an Object.
1. Assert: _dateTime_ has an [[InitializedTemporalDateTime]] internal slot.
@@ -703,6 +745,10 @@ DisambiguatePossibleInstants ( _possibleInstants_, _timeZone_, _dateTime_, _
GetPossibleInstantsFor ( _timeZone_, _dateTime_ )
1. Assert: _dateTime_ has an [[InitializedTemporalDateTime]] internal slot.
+ 1. If _timeZone_ is a String, then
+ 1. Set _timeZone_ to ! CreateTemporalTimeZone(_timeZone_).
+ 1. Let _array_ be ? Call(%Temporal.TimeZone.prototype.getPossibleInstantsFor%, _timeZone_, « _dateTime_ »).
+ 1. Return ! CreateListFromArrayLike(_array_, « Object »).
1. Let _possibleInstants_ be ? Invoke(_timeZone_, *"getPossibleInstantsFor"*, « _dateTime_ »).
1. Let _iteratorRecord_ be ? GetIterator(_possibleInstants_, ~sync~).
1. Let _list_ be a new empty List.
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 2a247efe6a..1e1b6828aa 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -125,16 +125,16 @@ get Temporal.ZonedDateTime.prototype.calendarId
-
- get Temporal.ZonedDateTime.prototype.timeZone
+
+ get Temporal.ZonedDateTime.prototype.timeZoneId
- `Temporal.ZonedDateTime.prototype.timeZone` is an accessor property whose set accessor function is *undefined*.
+ `Temporal.ZonedDateTime.prototype.timeZoneId` is an accessor property whose set accessor function is *undefined*.
Its get accessor function performs the following steps:
1. Let _zonedDateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
- 1. Return _zonedDateTime_.[[TimeZone]].
+ 1. Return ? ToTemporalTimeZoneIdentifier(_zonedDateTime_.[[TimeZone]]).
@@ -1000,6 +1000,18 @@ Temporal.ZonedDateTime.prototype.getCalendar ( )
1. Return ToTemporalCalendarObject(_zonedDateTime_.[[Calendar]]).
+
+
+ Temporal.ZonedDateTime.prototype.getTimeZone ( )
+
+ This method performs the following steps when called:
+
+
+ 1. Let _zonedDateTime_ be the *this* value.
+ 1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
+ 1. Return ToTemporalTimeZoneObject(_zonedDateTime_.[[TimeZone]]).
+
+
From 1f4c074517c8006645fec270d5c7f44e42f87778 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Wed, 18 Jan 2023 14:30:19 -0800
Subject: [PATCH 10/14] Normative: Use string time zone values internally
wherever possible
When creating Temporal objects with a builtin time zone, we want them to
be created with a string in the internal slot, not a TimeZone instance.
(For example, when parsing an IANA time zone name out of a string or using
UTC as a default.)
See: #1808
---
polyfill/lib/ecmascript.mjs | 12 ++++--------
polyfill/lib/intl.mjs | 20 +++++---------------
spec/abstractops.html | 5 +----
spec/instant.html | 3 +--
spec/intl.html | 15 +++++----------
spec/zoneddatetime.html | 5 +----
6 files changed, 17 insertions(+), 43 deletions(-)
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 50c4f209b6..72e2d21a5f 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -924,12 +924,13 @@ export const ES = ObjectAssign({}, ES2022, {
offset = fields.offset;
if (offset === undefined) offsetBehaviour = 'wall';
timeZone = fields.timeZone;
+ if (timeZone !== undefined) timeZone = ES.ToTemporalTimeZone(timeZone);
} else {
let ianaName, z;
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, ianaName, offset, z } =
ES.ParseISODateTime(ES.ToString(relativeTo)));
if (ianaName) {
- timeZone = ianaName;
+ timeZone = ES.ToTemporalTimeZone(ianaName);
if (z) {
offsetBehaviour = 'exact';
} else if (!offset) {
@@ -945,7 +946,6 @@ export const ES = ObjectAssign({}, ES2022, {
calendar = ES.ToTemporalCalendarSlotValue(calendar);
}
if (timeZone === undefined) return ES.CreateTemporalDate(year, month, day, calendar);
- timeZone = ES.ToTemporalTimeZone(timeZone);
const offsetNs = offsetBehaviour === 'option' ? ES.ParseTimeZoneOffsetString(offset) : 0;
const epochNanoseconds = ES.InterpretISODateTimeOffset(
year,
@@ -1386,13 +1386,12 @@ export const ES = ObjectAssign({}, ES2022, {
let ianaName, z;
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, ianaName, offset, z, calendar } =
ES.ParseTemporalZonedDateTimeString(ES.ToString(item)));
+ timeZone = ES.ToTemporalTimeZone(ianaName);
if (z) {
offsetBehaviour = 'exact';
} else if (!offset) {
offsetBehaviour = 'wall';
}
- const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
- timeZone = new TemporalTimeZone(ianaName);
if (!calendar) calendar = 'iso8601';
calendar = ES.ToTemporalCalendarSlotValue(calendar);
matchMinute = true; // ISO strings may specify offset with less precision
@@ -2257,10 +2256,7 @@ export const ES = ObjectAssign({}, ES2022, {
},
TemporalInstantToString: (instant, timeZone, precision) => {
let outputTimeZone = timeZone;
- if (outputTimeZone === undefined) {
- const TemporalTimeZone = GetIntrinsic('%Temporal.TimeZone%');
- outputTimeZone = new TemporalTimeZone('UTC');
- }
+ if (outputTimeZone === undefined) outputTimeZone = 'UTC';
const dateTime = ES.GetPlainDateTimeFor(outputTimeZone, instant, 'iso8601');
const year = ES.ISOYearString(GetSlot(dateTime, ISO_YEAR));
const month = ES.ISODateTimePartString(GetSlot(dateTime, ISO_MONTH));
diff --git a/polyfill/lib/intl.mjs b/polyfill/lib/intl.mjs
index 60297c9529..3feada85e7 100644
--- a/polyfill/lib/intl.mjs
+++ b/polyfill/lib/intl.mjs
@@ -15,7 +15,6 @@ import {
CALENDAR,
TIME_ZONE
} from './slots.mjs';
-import { TimeZone } from './timezone.mjs';
const DATE = Symbol('date');
const YM = Symbol('ym');
@@ -54,15 +53,6 @@ function getPropLazy(obj, prop) {
}
return val;
}
-// Similarly, lazy-init TimeZone instances.
-function getResolvedTimeZoneLazy(obj) {
- let val = obj[TZ_RESOLVED];
- if (typeof val === 'string') {
- val = new TimeZone(val);
- obj[TZ_RESOLVED] = val;
- }
- return val;
-}
export function DateTimeFormat(locale = undefined, options = undefined) {
if (!(this instanceof DateTimeFormat)) return new DateTimeFormat(locale, options);
@@ -383,7 +373,7 @@ function extractOverrides(temporalObj, main) {
const nanosecond = GetSlot(temporalObj, ISO_NANOSECOND);
const datetime = new DateTime(1970, 1, 1, hour, minute, second, millisecond, microsecond, nanosecond, main[CAL_ID]);
return {
- instant: ES.GetInstantFor(getResolvedTimeZoneLazy(main), datetime, 'compatible'),
+ instant: ES.GetInstantFor(main[TZ_RESOLVED], datetime, 'compatible'),
formatter: getPropLazy(main, TIME)
};
}
@@ -400,7 +390,7 @@ function extractOverrides(temporalObj, main) {
}
const datetime = new DateTime(isoYear, isoMonth, referenceISODay, 12, 0, 0, 0, 0, 0, calendar);
return {
- instant: ES.GetInstantFor(getResolvedTimeZoneLazy(main), datetime, 'compatible'),
+ instant: ES.GetInstantFor(main[TZ_RESOLVED], datetime, 'compatible'),
formatter: getPropLazy(main, YM)
};
}
@@ -417,7 +407,7 @@ function extractOverrides(temporalObj, main) {
}
const datetime = new DateTime(referenceISOYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0, calendar);
return {
- instant: ES.GetInstantFor(getResolvedTimeZoneLazy(main), datetime, 'compatible'),
+ instant: ES.GetInstantFor(main[TZ_RESOLVED], datetime, 'compatible'),
formatter: getPropLazy(main, MD)
};
}
@@ -432,7 +422,7 @@ function extractOverrides(temporalObj, main) {
}
const datetime = new DateTime(isoYear, isoMonth, isoDay, 12, 0, 0, 0, 0, 0, main[CAL_ID]);
return {
- instant: ES.GetInstantFor(getResolvedTimeZoneLazy(main), datetime, 'compatible'),
+ instant: ES.GetInstantFor(main[TZ_RESOLVED], datetime, 'compatible'),
formatter: getPropLazy(main, DATE)
};
}
@@ -469,7 +459,7 @@ function extractOverrides(temporalObj, main) {
);
}
return {
- instant: ES.GetInstantFor(getResolvedTimeZoneLazy(main), datetime, 'compatible'),
+ instant: ES.GetInstantFor(main[TZ_RESOLVED], datetime, 'compatible'),
formatter: getPropLazy(main, DATETIME)
};
}
diff --git a/spec/abstractops.html b/spec/abstractops.html
index 6d3b3f6db8..f1efe4ddb9 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -506,10 +506,7 @@ ToRelativeTemporalObject ( _options_ )
1. If _timeZoneName_ is *undefined*, then
1. Let _timeZone_ be *undefined*.
1. Else,
- 1. If IsTimeZoneOffsetString(_timeZoneName_) is *false*, then
- 1. If IsAvailableTimeZoneName(_timeZoneName_) is *false*, throw a *RangeError* exception.
- 1. Set _timeZoneName_ to ! CanonicalizeTimeZoneName(_timeZoneName_).
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_timeZoneName_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneName_).
1. If _result_.[[TimeZone]].[[Z]] is *true*, then
1. Set _offsetBehaviour_ to ~exact~.
1. Else if _offsetString_ is *undefined*, then
diff --git a/spec/instant.html b/spec/instant.html
index 7ae7bd51a3..712a88174e 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -651,8 +651,7 @@ TemporalInstantToString ( _instant_, _timeZone_, _precision_ )
1. Assert: Type(_instant_) is Object.
1. Assert: _instant_ has an [[InitializedTemporalInstant]] internal slot.
1. Let _outputTimeZone_ be _timeZone_.
- 1. If _outputTimeZone_ is *undefined*, then
- 1. Set _outputTimeZone_ to ! CreateTemporalTimeZone(*"UTC"*).
+ 1. If _outputTimeZone_ is *undefined*, set _outputTimeZone_ to *"UTC"*.
1. Let _dateTime_ be ? GetPlainDateTimeFor(_outputTimeZone_, _instant_, *"iso8601"*).
1. Let _dateTimeString_ be ! TemporalDateTimeToString(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], *"iso8601"*, _precision_, *"never"*).
1. If _timeZone_ is *undefined*, then
diff --git a/spec/intl.html b/spec/intl.html
index ceac000a13..76b2cbf83a 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -759,8 +759,7 @@ HandleDateTimeTemporalDate ( _dateTimeFormat_, _temporalDate_ )
1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_temporalDate_.[[Calendar]]).
1. If _calendar_ is not _dateTimeFormat_.[[Calendar]] or *"iso8601"*, throw a *RangeError* exception.
1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 12, 0, 0, 0, 0, 0, _dateTimeFormat_.[[Calendar]]).
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
- 1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
+ 1. Let _instant_ be ? GetInstantFor(_dateTimeFormat_.[[TimeZone]], _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
1. Return the Record {
[[pattern]]: _pattern_.[[pattern]],
@@ -785,8 +784,7 @@ HandleDateTimeTemporalYearMonth ( _dateTimeFormat_, _temporalYearMonth_ )HandleDateTimeTemporalMonthDay ( _dateTimeFormat_, _temporalMonthDay_ )
1. If _calendar_ is not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
1. Let _plainDateTime_ be ? CreateTemporalDateTime(_temporalMonthDay_.[[ISOYear]], _temporalMonthDay_.[[ISOMonth]], _temporalMonthDay_.[[ISODay]], 12, 0, 0, 0, 0, 0, _dateTimeFormat_.[[Calendar]]).
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
- 1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
+ 1. Let _instant_ be ? GetInstantFor(_dateTimeFormat_.[[TimeZone]], _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
1. Return the Record {
[[pattern]]: _pattern_.[[pattern]],
@@ -836,8 +833,7 @@ HandleDateTimeTemporalTime ( _dateTimeFormat_, _temporalTime_ )
1. Assert: _temporalTime_ has an [[InitializedTemporalTime]] internal slot.
1. Let _pattern_ be _dateTimeFormat_.[[TemporalPlainTimePattern]].
1. Let _plainDateTime_ be ? CreateTemporalDateTime(1970, 1, 1, _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], *"iso8601"*).
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
- 1. Let _instant_ be ? GetInstantFor(_timeZone_, _plainDateTime_, *"compatible"*).
+ 1. Let _instant_ be ? GetInstantFor(_dateTimeFormat_.[[TimeZone]], _plainDateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
1. Return the Record {
[[pattern]]: _pattern_.[[pattern]],
@@ -862,8 +858,7 @@ HandleDateTimeTemporalDateTime ( _dateTimeFormat_, _dateTime_ )
1. Let _calendar_ be ? ToTemporalCalendarIdentifier(_dateTime_.[[Calendar]]).
1. If _calendar_ is not *"iso8601"* and not equal to _dateTimeFormat_.[[Calendar]], then
1. Throw a *RangeError* exception.
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_dateTimeFormat_.[[TimeZone]]).
- 1. Let _instant_ be ? GetInstantFor(_timeZone_, _dateTime_, *"compatible"*).
+ 1. Let _instant_ be ? GetInstantFor(_dateTimeFormat_.[[TimeZone]], _dateTime_, *"compatible"*).
1. If _pattern_ is *null*, throw a *TypeError* exception.
1. Return the Record {
[[pattern]]: _pattern_.[[pattern]],
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 1e1b6828aa..b7732d4691 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -1173,15 +1173,12 @@
1. Let _result_ be ? ParseTemporalZonedDateTimeString(_string_).
1. Let _timeZoneName_ be _result_.[[TimeZone]].[[Name]].
1. Assert: _timeZoneName_ is not *undefined*.
- 1. If IsTimeZoneOffsetString(_timeZoneName_) is *false*, then
- 1. If IsAvailableTimeZoneName(_timeZoneName_) is *false*, throw a *RangeError* exception.
- 1. Set _timeZoneName_ to ! CanonicalizeTimeZoneName(_timeZoneName_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneName_).
1. Let _offsetString_ be _result_.[[TimeZone]].[[OffsetString]].
1. If _result_.[[TimeZone]].[[Z]] is *true*, then
1. Set _offsetBehaviour_ to ~exact~.
1. Else if _offsetString_ is *undefined*, then
1. Set _offsetBehaviour_ to ~wall~.
- 1. Let _timeZone_ be ! CreateTemporalTimeZone(_timeZoneName_).
1. Let _calendar_ be _result_.[[Calendar]].
1. If _calendar_ is *undefined*, set _calendar_ to *"iso8601"*.
1. Set _matchBehaviour_ to ~match minutes~.
From 12001baf1deb721bd4f6ae8e2500c9eb236887ca Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Wed, 18 Jan 2023 14:49:09 -0800
Subject: [PATCH 11/14] Normative: Change time zone compare semantics to use
.id
Previously algorithms such as TimeZoneEquals used ToString to get the
identifier of a time zone object. Instead, use
ToTemporalTimeZoneIdentifier which observably gets the .id property of a
custom time zone instead of getting and calling the .toString property.
See: #1808
---
docs/cookbook/stockExchangeTimeZone.mjs | 6 +++++-
docs/timezone.md | 8 ++++----
polyfill/index.d.ts | 4 ++--
polyfill/lib/ecmascript.mjs | 7 ++++---
polyfill/lib/intl.mjs | 2 +-
spec/intl.html | 2 +-
spec/timezone.html | 4 ++--
spec/zoneddatetime.html | 4 ++--
8 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/docs/cookbook/stockExchangeTimeZone.mjs b/docs/cookbook/stockExchangeTimeZone.mjs
index 34a47e0e97..f780140d96 100644
--- a/docs/cookbook/stockExchangeTimeZone.mjs
+++ b/docs/cookbook/stockExchangeTimeZone.mjs
@@ -80,6 +80,7 @@ function getPreviousMarketClose(instant) {
}
class NYSETimeZone extends Temporal.TimeZone {
+ #id = 'NYSE';
constructor() {
super('America/New_York');
}
@@ -124,8 +125,11 @@ class NYSETimeZone extends Temporal.TimeZone {
const ns = zdt.offsetNanoseconds + zdt.until(zdtWhenMarketIsOpen, { largestUnit: 'nanosecond' }).nanoseconds;
return ns;
}
+ get id() {
+ return this.#id;
+ }
toString() {
- return 'NYSE';
+ return this.#id;
}
}
diff --git a/docs/timezone.md b/docs/timezone.md
index c1dbf58447..628efb67de 100644
--- a/docs/timezone.md
+++ b/docs/timezone.md
@@ -20,15 +20,15 @@ There are two ways to do this.
The recommended way is to create a class inheriting from `Temporal.TimeZone`.
You must use one of the built-in time zones as the "base time zone".
In the class's constructor, call `super()` with the identifier of a built-in time zone to serve as a base.
-The class must override `toString()` to return its own identifier.
+The class must override the `id` prototype property, and should override `toString()` and `toJSON()` to match.
Overriding all the other properties of `Temporal.TimeZone.prototype` is optional.
Any property that is not overridden will behave as in the base time zone.
The other, more difficult, way to create a custom time zone is to create a plain object implementing the `Temporal.TimeZone` protocol, without subclassing.
-The object must have at least `getOffsetNanosecondsFor()`, `getPossibleInstantsFor()`, and `toString()` methods.
+The object must have at least `getOffsetNanosecondsFor()` and `getPossibleInstantsFor()` methods, and an `id` property.
Any object with those three methods will return the correct output from any Temporal property or method.
However, most other code will assume that custom time zones act like built-in `Temporal.TimeZone` objects.
-To interoperate with libraries or other code that you didn't write, then you should implement all the other `Temporal.TimeZone` members as well: `id`, `getOffsetStringFor()`, `getPlainDateTimeFor()`, `getInstantFor()`, `getNextTransition()`, `getPreviousTransition()`, and `toJSON()`.
+To interoperate with libraries or other code that you didn't write, then you should implement all the other `Temporal.TimeZone` members as well: `toString()`, `toJSON()`, `getOffsetStringFor()`, `getPlainDateTimeFor()`, `getInstantFor()`, `getNextTransition()`, `getPreviousTransition()`, and `toJSON()`.
Your object must not have a `timeZone` property, so that it can be distinguished in `Temporal.TimeZone.from()` from other Temporal objects that have a time zone.
The identifier of a custom time zone must consist of one or more components separated by slashes (`/`), as described in the [tzdata documentation](https://htmlpreview.github.io/?https://github.com/eggert/tz/blob/master/theory.html#naming).
@@ -136,7 +136,7 @@ tz2 = Temporal.TimeZone.from(tz);
The `id` property gives an unambiguous identifier for the time zone.
Effectively, this is the canonicalized version of whatever `timeZoneIdentifier` was passed as a parameter to the constructor.
-When subclassing `Temporal.TimeZone`, this property doesn't need to be overridden because the default implementation gives the result of calling `toString()`.
+When subclassing `Temporal.TimeZone`, this property must be overridden to provide an identifier for the custom time zone.
## Methods
diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts
index 091d573bd7..98c4fa6115 100644
--- a/polyfill/index.d.ts
+++ b/polyfill/index.d.ts
@@ -1090,7 +1090,7 @@ export namespace Temporal {
* A plain object implementing the protocol for a custom time zone.
*/
export interface TimeZoneProtocol {
- id?: string;
+ id: string;
timeZone?: never;
getOffsetNanosecondsFor(instant: Temporal.Instant | string): number;
getOffsetStringFor?(instant: Temporal.Instant | string): string;
@@ -1102,7 +1102,7 @@ export namespace Temporal {
getNextTransition?(startingPoint: Temporal.Instant | string): Temporal.Instant | null;
getPreviousTransition?(startingPoint: Temporal.Instant | string): Temporal.Instant | null;
getPossibleInstantsFor(dateTime: Temporal.PlainDateTime | PlainDateTimeLike | string): Temporal.Instant[];
- toString(): string;
+ toString?(): string;
toJSON?(): string;
}
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 72e2d21a5f..22a0c1f74d 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -1999,8 +1999,8 @@ export const ES = ObjectAssign({}, ES2022, {
},
TimeZoneEquals: (one, two) => {
if (one === two) return true;
- const tz1 = ES.ToString(one);
- const tz2 = ES.ToString(two);
+ const tz1 = ES.ToTemporalTimeZoneIdentifier(one);
+ const tz2 = ES.ToTemporalTimeZoneIdentifier(two);
return tz1 === tz2;
},
TemporalDateTimeToDate: (dateTime) => {
@@ -2450,8 +2450,9 @@ export const ES = ObjectAssign({}, ES2022, {
result += ES.FormatISOTimeZoneOffsetString(offsetNs);
}
if (showTimeZone !== 'never') {
+ const identifier = ES.ToTemporalTimeZoneIdentifier(tz);
const flag = showTimeZone === 'critical' ? '!' : '';
- result += `[${flag}${tz}]`;
+ result += `[${flag}${identifier}]`;
}
result += ES.MaybeFormatCalendarAnnotation(GetSlot(zdt, CALENDAR), showCalendar);
return result;
diff --git a/polyfill/lib/intl.mjs b/polyfill/lib/intl.mjs
index 3feada85e7..a0ee6899a5 100644
--- a/polyfill/lib/intl.mjs
+++ b/polyfill/lib/intl.mjs
@@ -473,7 +473,7 @@ function extractOverrides(temporalObj, main) {
}
let timeZone = GetSlot(temporalObj, TIME_ZONE);
- const objTimeZone = ES.ToString(timeZone);
+ const objTimeZone = ES.ToTemporalTimeZoneIdentifier(timeZone);
if (main[TZ_GIVEN] && main[TZ_GIVEN] !== objTimeZone) {
throw new RangeError(`timeZone option ${main[TZ_GIVEN]} doesn't match actual time zone ${objTimeZone}`);
}
diff --git a/spec/intl.html b/spec/intl.html
index 76b2cbf83a..4e4952ef38 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -903,7 +903,7 @@ HandleDateTimeTemporalZonedDateTime ( _dateTimeFormat_, _zonedDateTime_ )TimeZoneEquals ( _one_, _two_ )
1. If _one_ and _two_ are the same Object value, return *true*.
- 1. Let _timeZoneOne_ be ? ToString(_one_).
- 1. Let _timeZoneTwo_ be ? ToString(_two_).
+ 1. Let _timeZoneOne_ be ? ToTemporalTimeZoneIdentifier(_one_).
+ 1. Let _timeZoneTwo_ be ? ToTemporalTimeZoneIdentifier(_two_).
1. If _timeZoneOne_ is _timeZoneTwo_, return *true*.
1. Return *false*.
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index b7732d4691..91c6554d53 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -1254,9 +1254,9 @@
1. If _showTimeZone_ is *"never"*, then
1. Let _timeZoneString_ be the empty String.
1. Else,
- 1. Let _timeZoneID_ be ? ToString(_timeZone_).
+ 1. Let _timeZoneIdentifier_ be ? ToTemporalTimeZoneIdentifier(_timeZone_).
1. If _showTimeZone_ is *"critical"*, let _flag_ be *"!"*; else let _flag_ be the empty String.
- 1. Let _timeZoneString_ be the string-concatenation of the code unit 0x005B (LEFT SQUARE BRACKET), _flag_, _timeZoneID_, and the code unit 0x005D (RIGHT SQUARE BRACKET).
+ 1. Let _timeZoneString_ be the string-concatenation of the code unit 0x005B (LEFT SQUARE BRACKET), _flag_, _timeZoneIdentifier_, and the code unit 0x005D (RIGHT SQUARE BRACKET).
1. Let _calendarString_ be ? MaybeFormatCalendarAnnotation(_zonedDateTime_.[[Calendar]], _showCalendar_).
1. Return the string-concatenation of _dateTimeString_, _offsetString_, _timeZoneString_, and _calendarString_.
From 12987e5687753cd8974e7e6f33f087668f3858a5 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Wed, 18 Jan 2023 15:47:16 -0800
Subject: [PATCH 12/14] =?UTF-8?q?Editorial:=20Rename=20ToTemporalTimeZone?=
=?UTF-8?q?=20=E2=86=92=20ToTemporalTimeZoneSlotValue?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reflects that what comes out of these operations is not necessarily a
TimeZone object, but could be a string identifier of a built-in time zone.
It's described as "a value suitable for storing in a
Temporal.ZonedDateTime's [[TimeZone]] slot".
---
polyfill/lib/ecmascript.mjs | 10 +++++-----
polyfill/lib/instant.mjs | 6 +++---
polyfill/lib/now.mjs | 6 +++---
polyfill/lib/plaindate.mjs | 6 +++---
polyfill/lib/plaindatetime.mjs | 2 +-
polyfill/lib/plaintime.mjs | 2 +-
polyfill/lib/timezone.mjs | 2 +-
polyfill/lib/zoneddatetime.mjs | 7 +++----
spec/abstractops.html | 4 ++--
spec/instant.html | 6 +++---
spec/plaindate.html | 6 +++---
spec/plaindatetime.html | 2 +-
spec/plaintime.html | 2 +-
spec/temporal.html | 4 ++--
spec/timezone.html | 14 +++++++++++---
spec/zoneddatetime.html | 8 ++++----
16 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 22a0c1f74d..04ab8755bb 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -924,13 +924,13 @@ export const ES = ObjectAssign({}, ES2022, {
offset = fields.offset;
if (offset === undefined) offsetBehaviour = 'wall';
timeZone = fields.timeZone;
- if (timeZone !== undefined) timeZone = ES.ToTemporalTimeZone(timeZone);
+ if (timeZone !== undefined) timeZone = ES.ToTemporalTimeZoneSlotValue(timeZone);
} else {
let ianaName, z;
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, ianaName, offset, z } =
ES.ParseISODateTime(ES.ToString(relativeTo)));
if (ianaName) {
- timeZone = ES.ToTemporalTimeZone(ianaName);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(ianaName);
if (z) {
offsetBehaviour = 'exact';
} else if (!offset) {
@@ -1373,7 +1373,7 @@ export const ES = ObjectAssign({}, ES2022, {
]);
ES.Call(ArrayPrototypePush, fieldNames, ['timeZone', 'offset']);
const fields = ES.PrepareTemporalFields(item, fieldNames, ['timeZone']);
- timeZone = ES.ToTemporalTimeZone(fields.timeZone);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(fields.timeZone);
offset = fields.offset;
if (offset === undefined) {
offsetBehaviour = 'wall';
@@ -1386,7 +1386,7 @@ export const ES = ObjectAssign({}, ES2022, {
let ianaName, z;
({ year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, ianaName, offset, z, calendar } =
ES.ParseTemporalZonedDateTimeString(ES.ToString(item)));
- timeZone = ES.ToTemporalTimeZone(ianaName);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(ianaName);
if (z) {
offsetBehaviour = 'exact';
} else if (!offset) {
@@ -1967,7 +1967,7 @@ export const ES = ObjectAssign({}, ES2022, {
return result;
},
- ToTemporalTimeZone: (temporalTimeZoneLike) => {
+ ToTemporalTimeZoneSlotValue: (temporalTimeZoneLike) => {
if (ES.Type(temporalTimeZoneLike) === 'Object') {
if (ES.IsTemporalTimeZone(temporalTimeZoneLike)) return temporalTimeZoneLike;
if (ES.IsTemporalZonedDateTime(temporalTimeZoneLike)) return GetSlot(temporalTimeZoneLike, TIME_ZONE);
diff --git a/polyfill/lib/instant.mjs b/polyfill/lib/instant.mjs
index 2dc2409395..ccaa0f6902 100644
--- a/polyfill/lib/instant.mjs
+++ b/polyfill/lib/instant.mjs
@@ -110,7 +110,7 @@ export class Instant {
const smallestUnit = ES.GetTemporalUnit(options, 'smallestUnit', 'time', undefined);
if (smallestUnit === 'hour') throw new RangeError('smallestUnit must be a time unit other than "hour"');
let timeZone = options.timeZone;
- if (timeZone !== undefined) timeZone = ES.ToTemporalTimeZone(timeZone);
+ if (timeZone !== undefined) timeZone = ES.ToTemporalTimeZoneSlotValue(timeZone);
const { precision, unit, increment } = ES.ToSecondsStringPrecisionRecord(smallestUnit, digits);
const ns = GetSlot(this, EPOCHNANOSECONDS);
const roundedNs = ES.RoundInstant(ns, increment, unit, roundingMode);
@@ -142,12 +142,12 @@ export class Instant {
if (temporalTimeZoneLike === undefined) {
throw new TypeError('missing timeZone property in toZonedDateTime');
}
- const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(temporalTimeZoneLike);
return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), timeZone, calendar);
}
toZonedDateTimeISO(timeZone) {
if (!ES.IsTemporalInstant(this)) throw new TypeError('invalid receiver');
- timeZone = ES.ToTemporalTimeZone(timeZone);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(timeZone);
return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), timeZone, 'iso8601');
}
diff --git a/polyfill/lib/now.mjs b/polyfill/lib/now.mjs
index ad43b13d2c..773631d89a 100644
--- a/polyfill/lib/now.mjs
+++ b/polyfill/lib/now.mjs
@@ -6,18 +6,18 @@ const instant = () => {
return new Instant(ES.SystemUTCEpochNanoSeconds());
};
const plainDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
- const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(temporalTimeZoneLike);
const calendar = ES.ToTemporalCalendarSlotValue(calendarLike);
const inst = instant();
return ES.GetPlainDateTimeFor(timeZone, inst, calendar);
};
const plainDateTimeISO = (temporalTimeZoneLike = ES.DefaultTimeZone()) => {
- const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(temporalTimeZoneLike);
const inst = instant();
return ES.GetPlainDateTimeFor(timeZone, inst, 'iso8601');
};
const zonedDateTime = (calendarLike, temporalTimeZoneLike = ES.DefaultTimeZone()) => {
- const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(temporalTimeZoneLike);
const calendar = ES.ToTemporalCalendarSlotValue(calendarLike);
return ES.CreateTemporalZonedDateTime(ES.SystemUTCEpochNanoSeconds(), timeZone, calendar);
};
diff --git a/polyfill/lib/plaindate.mjs b/polyfill/lib/plaindate.mjs
index 6b809e1203..92088cc55b 100644
--- a/polyfill/lib/plaindate.mjs
+++ b/polyfill/lib/plaindate.mjs
@@ -200,14 +200,14 @@ export class PlainDate {
} else {
let timeZoneLike = item.timeZone;
if (timeZoneLike === undefined) {
- timeZone = ES.ToTemporalTimeZone(item);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(item);
} else {
- timeZone = ES.ToTemporalTimeZone(timeZoneLike);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(timeZoneLike);
temporalTime = item.plainTime;
}
}
} else {
- timeZone = ES.ToTemporalTimeZone(item);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(item);
}
const year = GetSlot(this, ISO_YEAR);
diff --git a/polyfill/lib/plaindatetime.mjs b/polyfill/lib/plaindatetime.mjs
index ffb7dc4b61..5380f547cc 100644
--- a/polyfill/lib/plaindatetime.mjs
+++ b/polyfill/lib/plaindatetime.mjs
@@ -380,7 +380,7 @@ export class PlainDateTime {
toZonedDateTime(temporalTimeZoneLike, options = undefined) {
if (!ES.IsTemporalDateTime(this)) throw new TypeError('invalid receiver');
- const timeZone = ES.ToTemporalTimeZone(temporalTimeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(temporalTimeZoneLike);
options = ES.GetOptionsObject(options);
const disambiguation = ES.ToTemporalDisambiguation(options);
const instant = ES.GetInstantFor(timeZone, this, disambiguation);
diff --git a/polyfill/lib/plaintime.mjs b/polyfill/lib/plaintime.mjs
index d5271362ef..2bfc1c7bc4 100644
--- a/polyfill/lib/plaintime.mjs
+++ b/polyfill/lib/plaintime.mjs
@@ -268,7 +268,7 @@ export class PlainTime {
if (timeZoneLike === undefined) {
throw new TypeError('missing timeZone property');
}
- const timeZone = ES.ToTemporalTimeZone(timeZoneLike);
+ const timeZone = ES.ToTemporalTimeZoneSlotValue(timeZoneLike);
const year = GetSlot(temporalDate, ISO_YEAR);
const month = GetSlot(temporalDate, ISO_MONTH);
diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs
index 7e5ebbda71..b693212524 100644
--- a/polyfill/lib/timezone.mjs
+++ b/polyfill/lib/timezone.mjs
@@ -149,7 +149,7 @@ export class TimeZone {
return ES.ToString(this);
}
static from(item) {
- const timeZoneSlotValue = ES.ToTemporalTimeZone(item);
+ const timeZoneSlotValue = ES.ToTemporalTimeZoneSlotValue(item);
return ES.ToTemporalTimeZoneObject(timeZoneSlotValue);
}
}
diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs
index 7689e83ee9..2f60429a56 100644
--- a/polyfill/lib/zoneddatetime.mjs
+++ b/polyfill/lib/zoneddatetime.mjs
@@ -27,13 +27,12 @@ export class ZonedDateTime {
constructor(epochNanoseconds, timeZone, calendar = 'iso8601') {
// Note: if the argument is not passed, ToBigInt(undefined) will throw. This check exists only
// to improve the error message.
- // ToTemporalTimeZone(undefined) will end up calling TimeZone.from("undefined"), which
- // could succeed.
+ // ToTemporalTimeZoneSlotValue(undefined) has a clear enough message.
if (arguments.length < 1) {
throw new TypeError('missing argument: epochNanoseconds is required');
}
epochNanoseconds = ES.ToBigInt(epochNanoseconds);
- timeZone = ES.ToTemporalTimeZone(timeZone);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(timeZone);
calendar = ES.ToTemporalCalendarSlotValue(calendar);
ES.CreateTemporalZonedDateTimeSlots(this, epochNanoseconds, timeZone, calendar);
@@ -300,7 +299,7 @@ export class ZonedDateTime {
}
withTimeZone(timeZone) {
if (!ES.IsTemporalZonedDateTime(this)) throw new TypeError('invalid receiver');
- timeZone = ES.ToTemporalTimeZone(timeZone);
+ timeZone = ES.ToTemporalTimeZoneSlotValue(timeZone);
return ES.CreateTemporalZonedDateTime(GetSlot(this, EPOCHNANOSECONDS), timeZone, GetSlot(this, CALENDAR));
}
withCalendar(calendar) {
diff --git a/spec/abstractops.html b/spec/abstractops.html
index f1efe4ddb9..c5836e90a4 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -493,7 +493,7 @@ ToRelativeTemporalObject ( _options_ )
1. Let _offsetString_ be ! Get(_fields_, *"offset"*).
1. Let _timeZone_ be ! Get(_fields_, *"timeZone"*).
1. If _timeZone_ is not *undefined*, then
- 1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
+ 1. Set _timeZone_ to ? ToTemporalTimeZoneSlotValue(_timeZone_).
1. If _offsetString_ is *undefined*, then
1. Set _offsetBehaviour_ to ~wall~.
1. Else,
@@ -506,7 +506,7 @@ ToRelativeTemporalObject ( _options_ )
1. If _timeZoneName_ is *undefined*, then
1. Let _timeZone_ be *undefined*.
1. Else,
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneName_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_timeZoneName_).
1. If _result_.[[TimeZone]].[[Z]] is *true*, then
1. Set _offsetBehaviour_ to ~exact~.
1. Else if _offsetString_ is *undefined*, then
diff --git a/spec/instant.html b/spec/instant.html
index 712a88174e..f7b14cf500 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -328,7 +328,7 @@ Temporal.Instant.prototype.toString ( [ _options_ ] )
1. If _smallestUnit_ is *"hour"*, throw a *RangeError* exception.
1. Let _timeZone_ be ? Get(_options_, *"timeZone"*).
1. If _timeZone_ is not *undefined*, then
- 1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
+ 1. Set _timeZone_ to ? ToTemporalTimeZoneSlotValue(_timeZone_).
1. Let _precision_ be ToSecondsStringPrecisionRecord(_smallestUnit_, _digits_).
1. Let _roundedNs_ be RoundTemporalInstant(_instant_.[[Nanoseconds]], _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_).
1. Let _roundedInstant_ be ! CreateTemporalInstant(_roundedNs_).
@@ -394,7 +394,7 @@ Temporal.Instant.prototype.toZonedDateTime ( _item_ )
1. Let _temporalTimeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Throw a *TypeError* exception.
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_temporalTimeZoneLike_).
1. Return ! CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, _calendar_).
@@ -407,7 +407,7 @@ Temporal.Instant.prototype.toZonedDateTimeISO ( _timeZone_ )
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
- 1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
+ 1. Set _timeZone_ to ? ToTemporalTimeZoneSlotValue(_timeZone_).
1. Return ! CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, *"iso8601"*).
diff --git a/spec/plaindate.html b/spec/plaindate.html
index 8a12abb68a..cc43039f33 100644
--- a/spec/plaindate.html
+++ b/spec/plaindate.html
@@ -504,13 +504,13 @@ Temporal.PlainDate.prototype.toZonedDateTime ( _item_ )
1. Else,
1. Let _timeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _timeZoneLike_ is *undefined*, then
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_item_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_item_).
1. Let _temporalTime_ be *undefined*.
1. Else,
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_timeZoneLike_).
1. Let _temporalTime_ be ? Get(_item_, *"plainTime"*).
1. Else,
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_item_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_item_).
1. Let _temporalTime_ be *undefined*.
1. If _temporalTime_ is *undefined*, then
1. Let _temporalDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], 0, 0, 0, 0, 0, 0, _temporalDate_.[[Calendar]]).
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index 81d97372bc..1eb609a4a3 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -620,7 +620,7 @@ Temporal.PlainDateTime.prototype.toZonedDateTime ( _temporalTimeZoneLike_ [
1. Let _dateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_dateTime_, [[InitializedTemporalDateTime]]).
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_temporalTimeZoneLike_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _disambiguation_ be ? ToTemporalDisambiguation(_options_).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _dateTime_, _disambiguation_).
diff --git a/spec/plaintime.html b/spec/plaintime.html
index 8a748549a0..7b684fa08e 100644
--- a/spec/plaintime.html
+++ b/spec/plaintime.html
@@ -356,7 +356,7 @@ Temporal.PlainTime.prototype.toZonedDateTime ( _item_ )
1. Let _temporalTimeZoneLike_ be ? Get(_item_, *"timeZone"*).
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Throw a *TypeError* exception.
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_temporalTimeZoneLike_).
1. Let _temporalDateTime_ be ? CreateTemporalDateTime(_temporalDate_.[[ISOYear]], _temporalDate_.[[ISOMonth]], _temporalDate_.[[ISODay]], _temporalTime_.[[ISOHour]], _temporalTime_.[[ISOMinute]], _temporalTime_.[[ISOSecond]], _temporalTime_.[[ISOMillisecond]], _temporalTime_.[[ISOMicrosecond]], _temporalTime_.[[ISONanosecond]], _temporalDate_.[[Calendar]]).
1. Let _instant_ be ? GetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*).
1. Return ! CreateTemporalZonedDateTime(_instant_.[[Nanoseconds]], _timeZone_, _temporalDate_.[[Calendar]]).
diff --git a/spec/temporal.html b/spec/temporal.html
index b9ca518d36..f13325efec 100644
--- a/spec/temporal.html
+++ b/spec/temporal.html
@@ -222,7 +222,7 @@ SystemDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Let _timeZone_ be DefaultTimeZone().
1. Else,
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_temporalTimeZoneLike_).
1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Let _instant_ be ! SystemInstant().
1. Return ? GetPlainDateTimeFor(_timeZone_, _instant_, _calendar_).
@@ -235,7 +235,7 @@ SystemZonedDateTime ( _temporalTimeZoneLike_, _calendarLike_ )
1. If _temporalTimeZoneLike_ is *undefined*, then
1. Let _timeZone_ be DefaultTimeZone().
1. Else,
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_temporalTimeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_temporalTimeZoneLike_).
1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_).
1. Let _ns_ be ! SystemUTCEpochNanoseconds().
1. Return ! CreateTemporalZonedDateTime(_ns_, _timeZone_, _calendar_).
diff --git a/spec/timezone.html b/spec/timezone.html
index bc9e553ed4..6ece5a7070 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -151,7 +151,7 @@ Temporal.TimeZone.from ( _item_ )
This function performs the following steps when called:
- 1. Let _slotValue_ be ? ToTemporalTimeZone(_item_).
+ 1. Let _slotValue_ be ? ToTemporalTimeZoneSlotValue(_item_).
1. Return ToTemporalTimeZoneObject(_slotValue_).
@@ -546,8 +546,16 @@ FormatISOTimeZoneOffsetString ( _offsetNanoseconds_ )
-
- ToTemporalTimeZone ( _temporalTimeZoneLike_ )
+
+
+ ToTemporalTimeZoneSlotValue (
+ _temporalTimeZoneLike_: an ECMAScript value,
+ ): either a normal completion containing either a String or an Object, or a throw completion
+
+
1. If Type(_temporalTimeZoneLike_) is Object, then
1. If _temporalTimeZoneLike_ has an [[InitializedTemporalTimeZone]] internal slot, then
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index 91c6554d53..7394c8edfc 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -35,7 +35,7 @@ Temporal.ZonedDateTime ( _epochNanoseconds_, _timeZoneLike_ [ , _calendarLik
1. Throw a *TypeError* exception.
1. Set _epochNanoseconds_ to ? ToBigInt(_epochNanoseconds_).
1. If ! IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_timeZoneLike_).
1. Let _calendar_ be ? ToTemporalCalendarSlotValue(_calendarLike_, *"iso8601"*).
1. Return ? CreateTemporalZonedDateTime(_epochNanoseconds_, _timeZone_, _calendar_, NewTarget).
@@ -655,7 +655,7 @@ Temporal.ZonedDateTime.prototype.withTimeZone ( _timeZoneLike_ )
1. Let _zonedDateTime_ be the *this* value.
1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]).
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneLike_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_timeZoneLike_).
1. Return ! CreateTemporalZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _timeZone_, _zonedDateTime_.[[Calendar]]).
@@ -1159,7 +1159,7 @@
1. Append *"offset"* to _fieldNames_.
1. Let _fields_ be ? PrepareTemporalFields(_item_, _fieldNames_, « *"timeZone"* »).
1. Let _timeZone_ be ! Get(_fields_, *"timeZone"*).
- 1. Set _timeZone_ to ? ToTemporalTimeZone(_timeZone_).
+ 1. Set _timeZone_ to ? ToTemporalTimeZoneSlotValue(_timeZone_).
1. Let _offsetString_ be ! Get(_fields_, *"offset"*).
1. Assert: _offsetString_ is a String or *undefined*.
1. If _offsetString_ is *undefined*, then
@@ -1173,7 +1173,7 @@
1. Let _result_ be ? ParseTemporalZonedDateTimeString(_string_).
1. Let _timeZoneName_ be _result_.[[TimeZone]].[[Name]].
1. Assert: _timeZoneName_ is not *undefined*.
- 1. Let _timeZone_ be ? ToTemporalTimeZone(_timeZoneName_).
+ 1. Let _timeZone_ be ? ToTemporalTimeZoneSlotValue(_timeZoneName_).
1. Let _offsetString_ be _result_.[[TimeZone]].[[OffsetString]].
1. If _result_.[[TimeZone]].[[Z]] is *true*, then
1. Set _offsetBehaviour_ to ~exact~.
From 50914daecba2b91eb9d2ba1b6b8ae6b90dc76592 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Fri, 20 Jan 2023 13:30:23 -0800
Subject: [PATCH 13/14] Normative: Change TimeZone.prototype.toJSON not to call
toString
The toJSON method should return the value in the internal slot, instead of
making an observable call to toString.
See: #1808
---
docs/cookbook/stockExchangeTimeZone.mjs | 3 +++
polyfill/lib/timezone.mjs | 2 +-
spec/timezone.html | 2 +-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/docs/cookbook/stockExchangeTimeZone.mjs b/docs/cookbook/stockExchangeTimeZone.mjs
index f780140d96..b8cbb77a45 100644
--- a/docs/cookbook/stockExchangeTimeZone.mjs
+++ b/docs/cookbook/stockExchangeTimeZone.mjs
@@ -131,6 +131,9 @@ class NYSETimeZone extends Temporal.TimeZone {
toString() {
return this.#id;
}
+ toJSON() {
+ return this.#id;
+ }
}
const tzNYSE = Object.freeze(new NYSETimeZone());
diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs
index b693212524..824bd8a343 100644
--- a/polyfill/lib/timezone.mjs
+++ b/polyfill/lib/timezone.mjs
@@ -146,7 +146,7 @@ export class TimeZone {
}
toJSON() {
if (!ES.IsTemporalTimeZone(this)) throw new TypeError('invalid receiver');
- return ES.ToString(this);
+ return GetSlot(this, TIMEZONE_ID);
}
static from(item) {
const timeZoneSlotValue = ES.ToTemporalTimeZoneSlotValue(item);
diff --git a/spec/timezone.html b/spec/timezone.html
index 6ece5a7070..e8c3f39459 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -326,7 +326,7 @@ Temporal.TimeZone.prototype.toJSON ( )
1. Let _timeZone_ be the *this* value.
1. Perform ? RequireInternalSlot(_timeZone_, [[InitializedTemporalTimeZone]]).
- 1. Return ? ToString(_timeZone_).
+ 1. Return _timeZone_.[[Identifier]].
From dd150fe209a45606be57559eba49fc2dbb69a2f4 Mon Sep 17 00:00:00 2001
From: Philip Chimento
Date: Fri, 7 Apr 2023 11:44:33 -0700
Subject: [PATCH 14/14] Update test262
---
polyfill/test262 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/polyfill/test262 b/polyfill/test262
index daefac0814..0178aa2114 160000
--- a/polyfill/test262
+++ b/polyfill/test262
@@ -1 +1 @@
-Subproject commit daefac08146f6a179aa273802878a87b6eca4fb8
+Subproject commit 0178aa2114a6823b04113f3ec5fd96e82ed1680f