Skip to content

Commit

Permalink
Temporal: Rewrite Temporal.ZonedDateTime.p.toLocaleString tests
Browse files Browse the repository at this point in the history
In tc39/proposal-temporal#2522 which reached
consensus at the March 2023 TC39 meeting, the functionality of
Temporal.ZonedDateTime.p.toLocaleString was changed substantially, to not
directly pass the ZonedDateTime to any Intl.DateTimeFormat methods. This
adds rewrites of all existing tests for toLocaleString, as well as a few
tests to verify that Intl.DateTimeFormat methods no longer support
Temporal.ZonedDateTime arguments.

As we are rewriting the tests anyway, this also ports all of the
Temporal.ZonedDateTime.p.toLocaleString tests that were in staging, to the
correct format for the main tree.
  • Loading branch information
ptomato authored and Ms2ger committed Apr 11, 2023
1 parent da56f5e commit cd714a9
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 508 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-datetime-format-functions
description: Temporal.ZonedDateTime is not supported directly in format()
features: [Temporal]
---*/

const formatter = new Intl.DateTimeFormat();

// Check that TypeError would not be thrown for a different reason
const {timeZone, ...options} = formatter.resolvedOptions();
const datetime = new Temporal.ZonedDateTime(0n, timeZone);
assert.sameValue(typeof datetime.toLocaleString(undefined, options), "string", "toLocaleString() with same options succeeds");

assert.throws(TypeError, () => formatter.format(datetime), "format() does not support Temporal.ZonedDateTime");
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-intl.datetimeformat.prototype.formatRangeToParts
description: Temporal.ZonedDateTime is not supported directly in formatRangeToParts()
features: [Temporal]
---*/

const formatter = new Intl.DateTimeFormat();

// Check that TypeError would not be thrown for a different reason
const {timeZone, ...options} = formatter.resolvedOptions();
const datetime1 = new Temporal.ZonedDateTime(0n, timeZone);
assert.sameValue(typeof datetime1.toLocaleString(undefined, options), "string", "toLocaleString() with same options succeeds");

const datetime2 = new Temporal.ZonedDateTime(1_000_000_000n, timeZone);
assert.throws(TypeError, () => formatter.formatRangeToParts(datetime1, datetime2), "formatRangeToParts() does not support Temporal.ZonedDateTime");
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-intl.datetimeformat.prototype.formatRange
description: Temporal.ZonedDateTime is not supported directly in formatRange()
features: [Temporal]
---*/

const formatter = new Intl.DateTimeFormat();

// Check that TypeError would not be thrown for a different reason
const {timeZone, ...options} = formatter.resolvedOptions();
const datetime1 = new Temporal.ZonedDateTime(0n, timeZone);
assert.sameValue(typeof datetime1.toLocaleString(undefined, options), "string", "toLocaleString() with same options succeeds");

const datetime2 = new Temporal.ZonedDateTime(1_000_000_000n, timeZone);
assert.throws(TypeError, () => formatter.formatRange(datetime1, datetime2), "formatRange() does not support Temporal.ZonedDateTime");
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-Intl.DateTimeFormat.prototype.formatToParts
description: Temporal.ZonedDateTime is not supported directly in formatToParts()
features: [Temporal]
---*/

const formatter = new Intl.DateTimeFormat();

// Check that TypeError would not be thrown for a different reason
const {timeZone, ...options} = formatter.resolvedOptions();
const datetime = new Temporal.ZonedDateTime(0n, timeZone);
assert.sameValue(typeof datetime.toLocaleString(undefined, options), "string", "toLocaleString() with same options succeeds");

assert.throws(TypeError, () => formatter.formatToParts(datetime), "formatToParts() does not support Temporal.ZonedDateTime");
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: Calendar must match the locale calendar if not "iso8601"
features: [Temporal, Intl-enumeration]
---*/

const localeCalendar = new Intl.DateTimeFormat().resolvedOptions().calendar;
assert.notSameValue(localeCalendar, "iso8601", "no locale has the ISO calendar");

const sameCalendarInstance = new Temporal.ZonedDateTime(0n, "UTC", localeCalendar);
const result = sameCalendarInstance.toLocaleString();
assert.sameValue(typeof result, "string", "toLocaleString() succeeds when instance has the same calendar as locale");

const isoInstance = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
assert.sameValue(isoInstance.toLocaleString(), result, "toLocaleString() succeeds when instance has the ISO calendar")

// Pick a different calendar that is not ISO and not the locale's calendar
const calendars = new Set(Intl.supportedValuesOf("calendar"));
calendars.delete("iso8601");
calendars.delete(localeCalendar);
const differentCalendar = calendars.values().next().value;

const differentCalendarInstance = new Temporal.ZonedDateTime(0n, "UTC", differentCalendar);
assert.throws(RangeError, () => differentCalendarInstance.toLocaleString(), "calendar mismatch");
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: >
Custom time zones with unofficial names are not supported for locale formatting
features: [Temporal]
---*/

const timeZone = {
id: "Etc/Custom_Zone",
getPossibleInstantsFor() {},
getOffsetNanosecondsFor() {},
};
const datetime = new Temporal.ZonedDateTime(0n, timeZone);
assert.throws(RangeError, () => datetime.toLocaleString(), "Custom time zones with non-IANA identifiers not supported in Intl");
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ features: [BigInt, Temporal]
---*/

const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC");
const defaultFormatter = new Intl.DateTimeFormat([], Object.create(null));
const expected = defaultFormatter.format(datetime);
const defaultFormatter = new Intl.DateTimeFormat([], {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short",
timeZone: "UTC",
});
const expected = defaultFormatter.format(datetime.toInstant());

const actualExplicit = datetime.toLocaleString(undefined);
assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: Offset time zones are not supported yet by Intl
features: [Temporal]
---*/

const datetime = new Temporal.ZonedDateTime(0n, "+00:00");
assert.throws(RangeError, () => datetime.toLocaleString(), "Intl.DateTimeFormat does not yet specify what to do with offset time zones");
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: >
Options must not have a timeZone property, even if it agrees with the
instance's time zone
features: [Temporal]
---*/

const datetime = new Temporal.ZonedDateTime(0n, "UTC");

assert.throws(TypeError, () => datetime.toLocaleString("en-US", { timeZone: "Europe/Vienna" }), "timeZone option disallowed");
assert.throws(TypeError, () => datetime.toLocaleString("en-US", { timeZone: "UTC" }), "timeZone option disallowed even if it agrees with instance's time zone");
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: timeZoneName option affects formatting of the instance's time zone
locale: [en-US]
features: [Temporal]
---*/

const datetime = new Temporal.ZonedDateTime(0n, "Europe/Vienna");

const resultShort = datetime.toLocaleString("en-US", { timeZoneName: "short" });
const resultLong = datetime.toLocaleString("en-US", { timeZoneName: "long" });
assert.notSameValue(resultShort, resultLong, "formats with different timeZoneName options should be different");
assert(resultLong.includes("Central European Standard Time"), "time zone name can be written out in full");
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ features: [BigInt, Temporal]
---*/

const datetime = new Temporal.ZonedDateTime(957270896_987_650_000n, "UTC");
const defaultFormatter = new Intl.DateTimeFormat('en', Object.create(null));
const expected = defaultFormatter.format(datetime);
const defaultFormatter = new Intl.DateTimeFormat('en', {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZoneName: "short",
timeZone: "UTC",
});
const expected = defaultFormatter.format(datetime.toInstant());

const actualExplicit = datetime.toLocaleString('en', undefined);
assert.sameValue(actualExplicit, expected, "default locale is determined by Intl.DateTimeFormat");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-temporal.zoneddatetime.prototype.tolocalestring
description: Custom time zone names are canonicalized
features: [Temporal]
---*/

const timeZone1 = {
id: "Asia/Kolkata",
getPossibleInstantsFor() {},
getOffsetNanosecondsFor() {},
};
const datetime1 = new Temporal.ZonedDateTime(0n, timeZone1);

const timeZone2 = {
id: "Asia/Calcutta",
getPossibleInstantsFor() {},
getOffsetNanosecondsFor() {},
};
const datetime2 = new Temporal.ZonedDateTime(0n, timeZone2);

assert.sameValue(datetime1.toLocaleString(), datetime2.toLocaleString(), "Time zone names are canonicalized before passing to DateTimeFormat");
Loading

0 comments on commit cd714a9

Please sign in to comment.