Temporal: Remove TimeZone.p.equals method

Some of the tests can be removed altogether since they deal with what
forms of input can be passed to ToTemporalTimeZoneSlotValue. Those are
tested on every method that takes a TimeZone as input.

Other tests are still relevant, but need to move to ZonedDateTime.p.equals
where the various quirks of time zone equality can still be tested. (Some
of these still will be removed in a following commit because they use
time zone objects.)

See: #2826
This commit is contained in:
Philip Chimento 2024-05-13 15:33:14 -07:00 committed by Ms2ger
parent 1213ab17ec
commit 6595838b3d
22 changed files with 127 additions and 463 deletions

View File

@ -1,33 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
description: Exceptions thrown if a value is passed that converts to an invalid string
features: [Temporal]
---*/
const primitives = [
undefined,
null,
true,
"string",
"local",
"Z",
"-00:00[UTC]",
"+00:01.1",
"-01.1",
"1994-11-05T08:15:30+25:00",
"1994-11-05T13:15:30-25:00",
7,
4.2,
12n
];
const tzUTC = new Temporal.TimeZone("UTC");
for (const primitive of primitives) {
assert.throws(typeof primitive === "string" ? RangeError : TypeError, () => tzUTC.equals(primitive));
}
const symbol = Symbol();
assert.throws(TypeError, () => tzUTC.equals(symbol));

View File

@ -1,24 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: Throw a TypeError if the receiver is invalid
features: [Symbol, Temporal]
---*/
const equals = Temporal.TimeZone.prototype.equals;
assert.sameValue(typeof equals, "function");
const args = ["UTC"];
assert.throws(TypeError, () => equals.apply(undefined, args), "undefined");
assert.throws(TypeError, () => equals.apply(null, args), "null");
assert.throws(TypeError, () => equals.apply(true, args), "true");
assert.throws(TypeError, () => equals.apply("", args), "empty string");
assert.throws(TypeError, () => equals.apply(Symbol(), args), "symbol");
assert.throws(TypeError, () => equals.apply(1, args), "1");
assert.throws(TypeError, () => equals.apply({}, args), "plain object");
assert.throws(TypeError, () => equals.apply(Temporal.TimeZone, args), "Temporal.TimeZone");
assert.throws(TypeError, () => equals.apply(Temporal.TimeZone.prototype, args), "Temporal.TimeZone.prototype");

View File

@ -1,33 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: >
Tests that Temporal.TimeZone.prototype.equals
meets the requirements for built-in objects defined by the
introduction of chapter 17 of the ECMAScript Language Specification.
info: |
Built-in functions that are not constructors do not have a "prototype" property unless
otherwise specified in the description of a particular function.
Unless specified otherwise, a built-in object that is callable as a function is a built-in
function object with the characteristics described in 10.3. Unless specified otherwise, the
[[Extensible]] internal slot of a built-in object initially has the value true.
Unless otherwise specified every built-in function and every built-in constructor has the
Function prototype object [...] as the value of its [[Prototype]] internal slot.
features: [Temporal]
---*/
assert.sameValue(Object.isExtensible(Temporal.TimeZone.prototype.equals),
true, "Built-in objects must be extensible.");
assert.sameValue(Object.prototype.toString.call(Temporal.TimeZone.prototype.equals),
"[object Function]", "Object.prototype.toString");
assert.sameValue(Object.getPrototypeOf(Temporal.TimeZone.prototype.equals),
Function.prototype, "prototype");
assert.sameValue(Temporal.TimeZone.prototype.equals.hasOwnProperty("prototype"),
false, "prototype property");

View File

@ -1,38 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: TypeError thrown if time zone reports an id that is not a String
features: [Temporal]
---*/
class CustomTimeZone extends Temporal.TimeZone {
constructor(id) {
super("UTC");
this._id = id;
}
get id() {
return this._id;
}
}
[
undefined,
null,
true,
-1000,
Symbol(),
3600_000_000_000n,
{},
{
valueOf() {
return 3600_000_000_000;
}
}
].forEach((wrongId) => {
const timeZoneWrong = new CustomTimeZone(wrongId);
const timeZoneOK = new Temporal.TimeZone('UTC');
assert.throws(TypeError, () => timeZoneWrong.equals(timeZoneOK));
assert.throws(TypeError, () => timeZoneOK.equals(timeZoneWrong));
});

View File

@ -1,25 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: Temporal.TimeZone.prototype.equals.length is 1
info: |
Every built-in function object, including constructors, has a "length" property whose value is
an integer. Unless otherwise specified, this value is equal to the largest number of named
arguments shown in the subclause headings for the function description. Optional parameters
(which are indicated with brackets: [ ]) or rest parameters (which are shown using the form
«...name») are not included in the default argument count.
Unless otherwise specified, the "length" property of a built-in function object has the
attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [Temporal]
---*/
verifyProperty(Temporal.TimeZone.prototype.equals, "length", {
value: 1,
writable: false,
enumerable: false,
configurable: true,
});

View File

@ -1,23 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: Temporal.TimeZone.prototype.equals.name is "equals".
info: |
Every built-in function object, including constructors, that is not identified as an anonymous
function has a "name" property whose value is a String. Unless otherwise specified, this value
is the name that is given to the function in this specification.
Unless otherwise specified, the "name" property of a built-in function object, if it exists,
has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
features: [Temporal]
---*/
verifyProperty(Temporal.TimeZone.prototype.equals, "name", {
value: "equals",
writable: false,
enumerable: false,
configurable: true,
});

View File

@ -1,21 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: >
Temporal.TimeZone.prototype.equals does not implement [[Construct]], is not new-able
info: |
Built-in function objects that are not identified as constructors do not implement the
[[Construct]] internal method unless otherwise specified in the description of a particular
function.
includes: [isConstructor.js]
features: [Reflect.construct, Temporal]
---*/
assert.throws(TypeError, () => {
new Temporal.TimeZone.prototype.equals();
}, "Calling as constructor");
assert.sameValue(isConstructor(Temporal.TimeZone.prototype.equals), false,
"isConstructor(Temporal.TimeZone.prototype.equals)");

View File

@ -1,21 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
description: The "equals" property of Temporal.TimeZone.prototype
includes: [propertyHelper.js]
features: [Temporal]
---*/
assert.sameValue(
typeof Temporal.TimeZone.prototype.equals,
"function",
"`typeof TimeZone.prototype.equals` is `function`"
);
verifyProperty(Temporal.TimeZone.prototype, "equals", {
writable: true,
enumerable: false,
configurable: true,
});

View File

@ -1,13 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.equals
description: Time zone names are case insensitive
features: [Temporal]
---*/
const timeZone = 'UtC';
const result = Temporal.TimeZone.from(timeZone);
assert.sameValue(result.equals(timeZone), true);
assert.sameValue(result.equals("+00:00"), false);

View File

@ -1,61 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.equals
description: Conversion of ISO date-time strings to the argument of Temporal.TimeZone.prototype.equals
features: [Temporal]
---*/
let tzUTC = Temporal.TimeZone.from("UTC");
let arg = "2021-08-19T17:30";
assert.throws(RangeError, () => tzUTC.equals(arg), "bare date-time string is not a time zone");
[
"2021-08-19T17:30-07:00:01",
"2021-08-19T17:30-07:00:00",
"2021-08-19T17:30-07:00:00.1",
"2021-08-19T17:30-07:00:00.0",
"2021-08-19T17:30-07:00:00.01",
"2021-08-19T17:30-07:00:00.00",
"2021-08-19T17:30-07:00:00.001",
"2021-08-19T17:30-07:00:00.000",
"2021-08-19T17:30-07:00:00.0001",
"2021-08-19T17:30-07:00:00.0000",
"2021-08-19T17:30-07:00:00.00001",
"2021-08-19T17:30-07:00:00.00000",
"2021-08-19T17:30-07:00:00.000001",
"2021-08-19T17:30-07:00:00.000000",
"2021-08-19T17:30-07:00:00.0000001",
"2021-08-19T17:30-07:00:00.0000000",
"2021-08-19T17:30-07:00:00.00000001",
"2021-08-19T17:30-07:00:00.00000000",
"2021-08-19T17:30-07:00:00.000000001",
"2021-08-19T17:30-07:00:00.000000000",
].forEach((timeZone) => {
assert.throws(
RangeError,
() => tzUTC.equals(timeZone),
`ISO string ${timeZone} with a sub-minute offset is not a valid time zone`
);
});
arg = "2021-08-19T17:30Z";
tzUTC = Temporal.TimeZone.from(arg);
assert.sameValue(tzUTC.equals(arg), true, "date-time + Z is UTC time zone");
arg = "2021-08-19T17:30-07:00";
tzUTC = Temporal.TimeZone.from(arg);
assert.sameValue(tzUTC.equals(arg), true, "date-time + offset is the offset time zone");
arg = "2021-08-19T17:30[UTC]";
tzUTC = Temporal.TimeZone.from(arg);
assert.sameValue(tzUTC.equals(arg), true, "date-time + IANA annotation is the IANA time zone");
arg = "2021-08-19T17:30Z[UTC]";
tzUTC = Temporal.TimeZone.from(arg);
assert.sameValue(tzUTC.equals(arg), true, "date-time + Z + IANA annotation is the IANA time zone");
arg = "2021-08-19T17:30-07:00[UTC]";
tzUTC = Temporal.TimeZone.from(arg);
assert.sameValue(tzUTC.equals(arg), true, "date-time + offset + IANA annotation is the IANA time zone");

View File

@ -1,13 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
description: Time zone strings with UTC offset fractional part are not confused with time fractional part
features: [Temporal]
---*/
const timeZone = "2021-08-19T17:30:45.123456789-12:12[+01:46]";
const result = Temporal.TimeZone.from(timeZone);
assert.sameValue(result.equals("+01:46"), true, "Time zone string determined from bracket name");

View File

@ -1,43 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
description: >
Appropriate error thrown when argument cannot be converted to a valid string
or object for TimeZone
features: [BigInt, Symbol, Temporal]
---*/
const rangeErrorTests = [
[null, "null"],
[true, "boolean"],
["", "empty string"],
[1, "number that doesn't convert to a valid ISO string"],
[19761118, "number that would convert to a valid ISO string in other contexts"],
[1n, "bigint"]
];
const tzUTC = new Temporal.TimeZone("UTC");
for (const [timeZone, description] of rangeErrorTests) {
assert.throws(
typeof timeZone === "string" ? RangeError : TypeError,
() => tzUTC.equals(timeZone),
`${description} does not convert to a valid ISO string`
);
}
const typeErrorTests = [
[Symbol(), "symbol"],
[{}, "object not implementing time zone protocol"],
[new Temporal.Calendar("iso8601"), "calendar instance"]
];
for (const [timeZone, description] of typeErrorTests) {
assert.throws(
TypeError,
() => tzUTC.equals(timeZone),
`${description} is not a valid object and does not convert to a string`
);
}

View File

@ -2,11 +2,13 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.prototype.equals
esid: sec-temporal.zoneddatetime.prototype.equals
description: Tests that objects can be compared for equality
features: [Temporal]
---*/
const instance = new Temporal.ZonedDateTime(0n, "UTC");
class CustomTimeZone extends Temporal.TimeZone {
constructor(id) {
super("UTC");
@ -27,7 +29,7 @@ const objectsEqualUTC = [
const tzUTC = new Temporal.TimeZone("UTC");
for (const object of objectsEqualUTC) {
const result = tzUTC.equals(object);
const result = instance.withTimeZone(tzUTC).equals(instance.withTimeZone(object));
assert.sameValue(result, true, `Receiver ${tzUTC.id} should equal argument ${object.id}`);
}
@ -60,7 +62,7 @@ const tz0000ToTest = [
for (const arg of objectsEqual0000) {
for (const receiver of tz0000ToTest) {
const result = receiver.equals(arg);
const result = instance.withTimeZone(receiver).equals(instance.withTimeZone(arg));
assert.sameValue(result, true, `Receiver ${receiver.id} should equal argument ${arg.id ?? arg}`);
}
}
@ -80,7 +82,7 @@ const customObjectsToTest = [tzUTC, new CustomTimeZone("YouTeeSee"), new CustomT
for (const arg of objectsNotEqual) {
for (const receiver of customObjectsToTest) {
if (arg === "UTC" && receiver === tzUTC) continue;
const result = receiver.equals(arg);
const result = instance.withTimeZone(receiver).equals(instance.withTimeZone(arg));
assert.sameValue(result, false, `Receiver ${receiver.id} should not equal argument ${arg.id ?? arg}`);
}
}
@ -97,7 +99,7 @@ const plainObjectDifferentCaseCustomId = {
getOffsetNanosecondsFor: null
};
assert.sameValue(classInstanceCustomId.equals(classInstanceSameCaseCustomId), true);
assert.sameValue(classInstanceCustomId.equals(classInstanceDifferentCaseCustomId), false);
assert.sameValue(classInstanceCustomId.equals(plainObjectSameCaseCustomId), true);
assert.sameValue(classInstanceCustomId.equals(plainObjectDifferentCaseCustomId), false);
assert.sameValue(instance.withTimeZone(classInstanceCustomId).equals(instance.withTimeZone(classInstanceSameCaseCustomId)), true);
assert.sameValue(instance.withTimeZone(classInstanceCustomId).equals(instance.withTimeZone(classInstanceDifferentCaseCustomId)), false);
assert.sameValue(instance.withTimeZone(classInstanceCustomId).equals(instance.withTimeZone(plainObjectSameCaseCustomId)), true);
assert.sameValue(instance.withTimeZone(classInstanceCustomId).equals(instance.withTimeZone(plainObjectDifferentCaseCustomId)), false);

View File

@ -2,11 +2,13 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
esid: sec-temporal.zoneddatetime.prototype.equals
description: Built-in time zones are compared correctly out of valid strings
features: [Temporal]
---*/
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const validsEqual = [
["+0330", "+03:30"],
["-0650", "-06:50"],
@ -16,10 +18,8 @@ const validsEqual = [
];
for (const [valid, canonical] of validsEqual) {
const tzValid = Temporal.TimeZone.from(valid);
const tzCanonical = Temporal.TimeZone.from(canonical);
assert.sameValue(tzValid.equals(canonical), true);
assert.sameValue(tzCanonical.equals(valid), true);
assert(instance.withTimeZone(valid).equals(instance.withTimeZone(canonical)), `${valid} time zone equals ${canonical}`);
assert(instance.withTimeZone(canonical).equals(instance.withTimeZone(valid)), `${canonical} time zone equals ${valid}`);
}
const validsNotEqual = [
@ -30,8 +30,6 @@ const validsNotEqual = [
];
for (const [valid, canonical] of validsNotEqual) {
const tzValid = Temporal.TimeZone.from(valid);
const tzCanonical = Temporal.TimeZone.from(canonical);
assert.sameValue(tzValid.equals(canonical), false);
assert.sameValue(tzCanonical.equals(valid), false);
assert(!instance.withTimeZone(valid).equals(instance.withTimeZone(canonical)), `${valid} time zone does not equal ${canonical}`);
assert(!instance.withTimeZone(canonical).equals(instance.withTimeZone(valid)), `${canonical} time zone does not equal ${valid}`);
}

View File

@ -1,47 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
description: Canonicalizes to evaluate time zone equality
features: [Temporal]
---*/
const neverEqual = new Temporal.TimeZone('Asia/Tokyo');
const zdt = new Temporal.ZonedDateTime(0n, 'America/Los_Angeles');
const ids = [
['America/Atka', 'America/Adak'],
['America/Knox_IN', 'America/Indiana/Knox'],
['Asia/Ashkhabad', 'Asia/Ashgabat'],
['Asia/Dacca', 'Asia/Dhaka'],
['Asia/Istanbul', 'Europe/Istanbul'],
['Asia/Macao', 'Asia/Macau'],
['Asia/Thimbu', 'Asia/Thimphu'],
['Asia/Ujung_Pandang', 'Asia/Makassar'],
['Asia/Ulan_Bator', 'Asia/Ulaanbaatar']
];
for (const [identifier, primaryIdentifier] of ids) {
const tz1 = new Temporal.TimeZone(identifier);
const tz2 = new Temporal.TimeZone(primaryIdentifier);
// compare objects
assert.sameValue(tz1.equals(tz2), true);
assert.sameValue(tz2.equals(tz1), true);
assert.sameValue(tz1.equals(neverEqual), false);
// compare string IDs
assert.sameValue(tz1.equals(tz2.id), true);
assert.sameValue(tz2.equals(tz1.id), true);
assert.sameValue(tz1.equals(neverEqual.id), false);
// compare ZonedDateTime instances
assert.sameValue(tz1.equals(zdt.withTimeZone(tz2)), true);
assert.sameValue(tz2.equals(zdt.withTimeZone(tz1)), true);
assert.sameValue(tz1.equals(zdt.withTimeZone(neverEqual)), false);
// compare IXDTF strings
assert.sameValue(tz1.equals(zdt.withTimeZone(tz2).toString()), true);
assert.sameValue(tz2.equals(zdt.withTimeZone(tz1).toString()), true);
assert.sameValue(tz1.equals(zdt.withTimeZone(neverEqual).toString()), false);
}

View File

@ -1,22 +0,0 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: Offset string time zones compare as expected
features: [Temporal]
---*/
const zdt = new Temporal.ZonedDateTime(0n, "America/Los_Angeles");
const otz1 = new Temporal.TimeZone("+05:30");
const otz2 = new Temporal.TimeZone("+0530");
const tz = new Temporal.TimeZone("Asia/Kolkata");
assert.sameValue(otz1.equals(otz2), true);
assert.sameValue(otz2.equals(otz1), true);
assert.sameValue(otz1.equals("+05:30"), true);
assert.sameValue(otz1.equals(zdt.withTimeZone(otz2)), true);
assert.sameValue(otz1.equals(zdt.withTimeZone(otz2).toString()), true);
assert.sameValue(otz1.equals(tz), false);
assert.sameValue(otz1.equals("Asia/Kolkata"), false);
assert.sameValue(otz1.equals(zdt.withTimeZone(tz)), false);
assert.sameValue(otz1.equals(zdt.withTimeZone(tz).toString()), false);

View File

@ -2,11 +2,13 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
esid: sec-temporal.zoneddatetime.prototype.equals
description: Objects with IANA IDs are compared case-insensitively with their canonical IDs
features: [Temporal]
---*/
const instance = new Temporal.ZonedDateTime(0n, "UTC");
class CustomTimeZone extends Temporal.TimeZone {
constructor(id) {
super("UTC");
@ -35,10 +37,16 @@ const plainObjectsIANA = [
for (const object1 of classInstancesIANA) {
for (const object2 of classInstancesIANA) {
assert.sameValue(object1.equals(object2), true, `Receiver ${object1.id} should not equal argument ${object2.id}`);
assert(
instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
}
for (const object2 of plainObjectsIANA) {
assert.sameValue(object1.equals(object2), true, `Receiver ${object2.id} should not equal argument ${object1.id}`);
assert(
instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object2.id} should not equal argument ${object1.id}`
);
}
}
@ -51,14 +59,22 @@ const classInstancesIANADifferentCanonical = [
for (const object1 of classInstancesIANADifferentCanonical) {
for (const object2 of classInstancesIANA) {
assert.sameValue(object1.equals(object2), false, `Receiver ${object1.id} should not equal argument ${object2.id}`);
assert.sameValue(object2.equals(object1), false, `Receiver ${object2.id} should not equal argument ${object1.id}`);
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
assert(
!instance.withTimeZone(object2).equals(instance.withTimeZone(object1)),
`Receiver ${object2.id} should not equal argument ${object1.id}`
);
}
for (const object2 of plainObjectsIANA) {
assert.sameValue(object1.equals(object2), false, `Receiver ${object1.id} should not equal argument ${object2.id}`);
assert.sameValue(
object1.equals(object2.id),
false,
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2.id)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
}
@ -67,14 +83,22 @@ for (const object1 of classInstancesIANADifferentCanonical) {
const classInstancesCustomNotIANA = [new CustomTimeZone("Moon/Cheese")];
for (const object1 of classInstancesCustomNotIANA) {
for (const object2 of classInstancesIANA) {
assert.sameValue(object1.equals(object2), false, `Receiver ${object1.id} should not equal argument ${object2.id}`);
assert.sameValue(object2.equals(object1), false, `Receiver ${object2.id} should not equal argument ${object1.id}`);
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
assert(
!instance.withTimeZone(object2).equals(instance.withTimeZone(object1)),
`Receiver ${object2.id} should not equal argument ${object1.id}`
);
}
for (const object2 of plainObjectsIANA) {
assert.sameValue(object1.equals(object2), false, `Receiver ${object1.id} should not equal argument ${object2.id}`);
assert.sameValue(
object1.equals(object2.id),
false,
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
assert(
!instance.withTimeZone(object1).equals(instance.withTimeZone(object2.id)),
`Receiver ${object1.id} should not equal argument ${object2.id}`
);
}

View File

@ -2,11 +2,13 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
esid: sec-temporal.zoneddatetime.prototype.equals
description: Built-in time zones are parsed correctly out of valid strings
features: [Temporal]
---*/
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const valids = [
["Africa/CAIRO", "Africa/Cairo"],
["Asia/Ulan_Bator", "Asia/Ulaanbaatar"],
@ -19,8 +21,6 @@ const valids = [
];
for (const [valid, canonical = valid] of valids) {
const tzValid = Temporal.TimeZone.from(canonical);
const tzCanonical = Temporal.TimeZone.from(canonical);
assert.sameValue(tzValid.equals(tzCanonical), true);
assert.sameValue(tzCanonical.equals(tzValid), true);
assert(instance.withTimeZone(valid).equals(instance.withTimeZone(canonical)), `${valid} equals ${canonical}`);
assert(instance.withTimeZone(canonical).equals(instance.withTimeZone(valid)), `${canonical} equals ${valid}`);
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.equals
description: Canonicalizes to evaluate time zone equality
features: [Temporal]
---*/
const neverEqual = new Temporal.ZonedDateTime(0n, 'Asia/Tokyo');
const zdt = new Temporal.ZonedDateTime(0n, 'America/Los_Angeles');
const ids = [
['America/Atka', 'America/Adak'],
['America/Knox_IN', 'America/Indiana/Knox'],
['Asia/Ashkhabad', 'Asia/Ashgabat'],
['Asia/Dacca', 'Asia/Dhaka'],
['Asia/Istanbul', 'Europe/Istanbul'],
['Asia/Macao', 'Asia/Macau'],
['Asia/Thimbu', 'Asia/Thimphu'],
['Asia/Ujung_Pandang', 'Asia/Makassar'],
['Asia/Ulan_Bator', 'Asia/Ulaanbaatar']
];
for (const [identifier, primaryIdentifier] of ids) {
const z1 = zdt.withTimeZone(identifier);
const z2 = zdt.withTimeZone(primaryIdentifier);
// compare objects
assert(z1.equals(z2), `${identifier} equals ${primaryIdentifier} object`);
assert(z2.equals(z1), `${primaryIdentifier} equals ${identifier} object`);
assert(!z1.equals(neverEqual), "not equal to unrelated time zone object");
// compare IXDTF strings
assert(z1.equals(z2.toString()), `${identifier} equals ${primaryIdentifier} IXDTF string`);
assert(z2.equals(z1.toString()), `${primaryIdentifier} equals ${identifier} IXDTF string`);
assert(!z1.equals(neverEqual.toString()), "not equal to unrelated IXDTF string");
}

View File

@ -2,9 +2,9 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
esid: sec-temporal.zoneddatetime.prototype.equals
description: Canonical time zone identifiers are never equal to each other
features: [Temporal]
features: [Temporal, Intl-enumeration]
---*/
// supportedValuesOf only returns canonical IDs
@ -19,7 +19,7 @@ const forEachDistinctPair = (array, func) => {
};
forEachDistinctPair(ids, (id1, id2) => {
const tz = new Temporal.TimeZone(id1);
assert.sameValue(tz.equals(id2), false);
const instance = new Temporal.ZonedDateTime(0n, id1);
assert(!instance.equals(instance.withTimeZone(id2)), `${id1} does not equal ${id2}`);
})

View File

@ -0,0 +1,20 @@
// Copyright (C) 2023 Justin Grant. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.equals
description: Offset string time zones compare as expected
features: [Temporal]
---*/
const zdt = new Temporal.ZonedDateTime(0n, "America/Los_Angeles");
const otz1 = new Temporal.TimeZone("+05:30");
const otz2 = new Temporal.TimeZone("+0530");
const tz = new Temporal.TimeZone("Asia/Kolkata");
assert(zdt.withTimeZone(otz1).equals(zdt.withTimeZone(otz2)), "+05:30 = +0530");
assert(zdt.withTimeZone(otz2).equals(zdt.withTimeZone(otz1)), "+0530 = +05:30");
assert(zdt.withTimeZone(otz1).equals(zdt.withTimeZone("+05:30")), "+05:30 = +05:30 string ID");
assert(zdt.withTimeZone(otz1).equals(zdt.withTimeZone(otz2).toString()), "+05:30 = +0530 IXDTF string");
assert(!zdt.withTimeZone(otz1).equals(zdt.withTimeZone("Asia/Kolkata")), "+05:30 != Asia/Kolkata string ID");
assert(!zdt.withTimeZone(otz1).equals(zdt.withTimeZone(tz)), "+05:30 != Asia/Kolkata");
assert(!zdt.withTimeZone(otz1).equals(zdt.withTimeZone(tz).toString()), "+05:30 != Asia/Kolkata IXDTF string");

View File

@ -2,9 +2,9 @@
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone.from
esid: sec-temporal.zoneddatetime.prototype.equals
description: Time zone names are compared case-insensitively
features: [Temporal]
features: [Temporal, Intl-enumeration]
---*/
const timeZoneIdentifiers = [
@ -618,7 +618,7 @@ const ids = [...new Set([...timeZoneIdentifiers, ...Intl.supportedValuesOf('time
for (const id of ids) {
const lower = id.toLowerCase();
const upper = id.toUpperCase();
const tz = new Temporal.TimeZone(id);
assert.sameValue(tz.equals(upper), true, `Time zone "${id}" compared to string "${upper}"`);
assert.sameValue(tz.equals(lower), true, `Time zone "${id}" compared to string "${lower}"`);
const zdt = new Temporal.ZonedDateTime(0n, id);
assert(zdt.equals(zdt.withTimeZone(upper)), `Time zone "${id}" compared to string "${upper}"`);
assert(zdt.equals(zdt.withTimeZone(lower)), `Time zone "${id}" compared to string "${lower}"`);
}