Import SpiderMonkey Temporal tests

Temporal tests written for the SpiderMonkey implementation. Mostly
covers edge cases around mathematical operations and regression tests
for reported spec bugs.
This commit is contained in:
André Bargull 2022-07-05 12:48:26 +02:00 committed by Ms2ger
parent e849d40605
commit eaf85892fb
24 changed files with 995 additions and 0 deletions

View File

@ -0,0 +1,68 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.compare
description: >
Duration components are precise mathematical integers.
info: |
Temporal.Duration.compare ( one, two [ , options ] )
...
7. If any of one.[[Years]], two.[[Years]], one.[[Months]], two.[[Months]], one.[[Weeks]], or
two.[[Weeks]] are not 0, then
a. Let unbalanceResult1 be ? UnbalanceDurationRelative(one.[[Years]], one.[[Months]],
one.[[Weeks]], one.[[Days]], "day", relativeTo).
...
9. Let ns1 be ! TotalDurationNanoseconds(days1, one.[[Hours]], one.[[Minutes]], one.[[Seconds]],
one.[[Milliseconds]], one.[[Microseconds]], one.[[Nanoseconds]], shift1).
10. Let ns2 be ! TotalDurationNanoseconds(days2, two.[[Hours]], two.[[Minutes]], two.[[Seconds]],
two.[[Milliseconds]], two.[[Microseconds]], two.[[Nanoseconds]], shift2).
11. If ns1 > ns2, return 1𝔽.
12. If ns1 < ns2, return -1𝔽.
13. Return +0𝔽.
UnbalanceDurationRelative ( years, months, weeks, days, largestUnit, relativeTo )
...
11. Else,
a. If any of years, months, and weeks are not zero, then
...
iv. Repeat, while weeks 0,
1. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneWeek).
2. Set relativeTo to moveResult.[[RelativeTo]].
3. Set days to days + moveResult.[[Days]].
4. Set weeks to weeks - sign.
12. Return ? CreateDateDurationRecord(years, months, weeks, days).
features: [Temporal]
---*/
var one = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER,
weeks: 3,
});
var two = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER + 3,
weeks: 0,
});
var cal = new class extends Temporal.Calendar {
dateAdd(date, duration, options) {
// Add one day when one week was requested.
if (duration.toString() === "P1W") {
return super.dateAdd(date, "P1D", options);
}
// Only expect to add one week.
throw new Test262Error("dateAdd called with unexpected value");
}
}("iso8601");
var pd = new Temporal.PlainDate(1970, 1, 1, cal);
// |Number.MAX_SAFE_INTEGER + 1 + 1 + 1| is unequal to |Number.MAX_SAFE_INTEGER + 3|
// when the addition is performed using IEEE-754 semantics. But for compare we have
// to ensure exact mathematical computations are performed.
assert.sameValue(Temporal.Duration.compare(one, two, {relativeTo: pd}), 0);

View File

@ -0,0 +1,68 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.compare
description: >
Duration components are precise mathematical integers.
info: |
Temporal.Duration.compare ( one, two [ , options ] )
...
7. If any of one.[[Years]], two.[[Years]], one.[[Months]], two.[[Months]], one.[[Weeks]], or
two.[[Weeks]] are not 0, then
a. Let unbalanceResult1 be ? UnbalanceDurationRelative(one.[[Years]], one.[[Months]],
one.[[Weeks]], one.[[Days]], "day", relativeTo).
...
9. Let ns1 be ! TotalDurationNanoseconds(days1, one.[[Hours]], one.[[Minutes]], one.[[Seconds]],
one.[[Milliseconds]], one.[[Microseconds]], one.[[Nanoseconds]], shift1).
10. Let ns2 be ! TotalDurationNanoseconds(days2, two.[[Hours]], two.[[Minutes]], two.[[Seconds]],
two.[[Milliseconds]], two.[[Microseconds]], two.[[Nanoseconds]], shift2).
11. If ns1 > ns2, return 1𝔽.
12. If ns1 < ns2, return -1𝔽.
13. Return +0𝔽.
UnbalanceDurationRelative ( years, months, weeks, days, largestUnit, relativeTo )
...
11. Else,
a. If any of years, months, and weeks are not zero, then
...
iv. Repeat, while weeks 0,
1. Let moveResult be ? MoveRelativeDate(calendar, relativeTo, oneWeek).
2. Set relativeTo to moveResult.[[RelativeTo]].
3. Set days to days + moveResult.[[Days]].
4. Set weeks to weeks - sign.
12. Return ? CreateDateDurationRecord(years, months, weeks, days).
features: [Temporal]
---*/
var one = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER,
weeks: 3,
});
var two = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER + 3,
weeks: 0,
});
var cal = new class extends Temporal.Calendar {
dateAdd(date, duration, options) {
// Add one day when one week was requested.
if (duration.toString() === "P1W") {
return super.dateAdd(date, "P1D", options);
}
// Use zero duration to avoid a RangeError during CalculateOffsetShift.
return super.dateAdd(date, "PT0S", options);
}
}("iso8601");
var zdt = new Temporal.ZonedDateTime(0n, "UTC", cal);
// |Number.MAX_SAFE_INTEGER + 1 + 1 + 1| is unequal to |Number.MAX_SAFE_INTEGER + 3|
// when the addition is performed using IEEE-754 semantics. But for compare we have
// to ensure exact mathematical computations are performed.
assert.sameValue(Temporal.Duration.compare(one, two, {relativeTo: zdt}), 0);

View File

@ -0,0 +1,56 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.from
description: >
Fractional parts are computed using exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const tests = {
"PT0.999999999H": Temporal.Duration.from({
minutes: 59,
seconds: 59,
milliseconds: 999,
microseconds: 996,
nanoseconds: 400,
}),
"PT0.000000011H": Temporal.Duration.from({
minutes: 0,
seconds: 0,
milliseconds: 0,
microseconds: 39,
nanoseconds: 600,
}),
"PT0.999999999M": Temporal.Duration.from({
seconds: 59,
milliseconds: 999,
microseconds: 999,
nanoseconds: 940,
}),
"PT0.000000011M": Temporal.Duration.from({
seconds: 0,
milliseconds: 0,
microseconds: 0,
nanoseconds: 660,
}),
"PT0.999999999S": Temporal.Duration.from({
milliseconds: 999,
microseconds: 999,
nanoseconds: 999,
}),
"PT0.000000011S": Temporal.Duration.from({
milliseconds: 0,
microseconds: 0,
nanoseconds: 11,
}),
};
for (let [str, expected] of Object.entries(tests)) {
let actual = Temporal.Duration.from(str);
TemporalHelpers.assertDurationsEqual(actual, expected, str);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.from
description: >
Throws when a fractional unit is present and a sub-part is zero.
features: [Temporal]
---*/
const invalid = [
// Hours fraction with whole minutes.
"PT0.1H0M",
// Hours fraction with fractional minutes.
"PT0.1H0.0M",
// Hours fraction with whole seconds.
"PT0.1H0S",
// Hours fraction with fractional seconds.
"PT0.1H0.0S",
// Minutes fraction with whole seconds.
"PT0.1M0S",
// Minutes fraction with fractional seconds.
"PT0.1M0.0S",
];
for (let string of invalid) {
assert.throws(RangeError, () => Temporal.Duration.from(string));
}

View File

@ -0,0 +1,57 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.add
description: >
AddDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const plainDate = new Temporal.PlainDate(1970, 1, 1);
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
// Largest temporal unit is "day".
const duration1 = Temporal.Duration.from({nanoseconds: Number.MAX_SAFE_INTEGER});
const duration2 = Temporal.Duration.from({nanoseconds: 2, days: 1});
const nanos = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
TemporalHelpers.assertDuration(
duration1.add(duration2),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.add(duration2)"
);
TemporalHelpers.assertDuration(
duration1.add(duration2, {relativeTo: plainDate}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.add(duration2, {relativeTo: plainDate})"
);
TemporalHelpers.assertDuration(
duration1.add(duration2, {relativeTo: zonedDateTime}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.add(duration2, {relativeTo: zonedDateTime})"
);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.add
description: >
BalanceDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const plainDate = new Temporal.PlainDate(1970, 1, 1);
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
// Largest temporal unit is "day".
const duration1 = Temporal.Duration.from({nanoseconds: Number.MAX_VALUE});
const duration2 = Temporal.Duration.from({nanoseconds: Number.MAX_VALUE, days: 1});
const nanos = BigInt(Number.MAX_VALUE) * 2n;
TemporalHelpers.assertDuration(
duration1.add(duration2),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.add(duration2)"
);
TemporalHelpers.assertDuration(
duration1.add(duration2, {relativeTo: plainDate}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.add(duration2, {relativeTo: plainDate})"
);
// Throws a RangeError because the intermediate instant is too large.
assert.throws(RangeError, () => {
duration1.add(duration2, {relativeTo: zonedDateTime});
});

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.add
description: >
AddDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
// Largest temporal unit is "microsecond".
let duration1 = Temporal.Duration.from({microseconds: Number.MAX_SAFE_INTEGER + 1, nanoseconds: 0});
let duration2 = Temporal.Duration.from({microseconds: 1, nanoseconds: 1000});
TemporalHelpers.assertDuration(
duration1.add(duration2),
0, 0, 0, 0,
0, 0, 0, 0,
9007199254740994,
0,
"duration1.add(duration2)"
);

View File

@ -0,0 +1,52 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
BalanceDurationRelative computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
months: Number.MAX_SAFE_INTEGER,
days: 31 + 28 + 31,
});
let result = duration.round({
largestUnit: "months",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
0, 9007199254740994, 0, 0,
0, 0, 0,
0, 0, 0,
);
}
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
months: Number.MAX_SAFE_INTEGER,
days: 31 + 28 + 31 + 1,
});
let result = duration.round({
largestUnit: "months",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
0, 9007199254740994, 0, 1,
0, 0, 0,
0, 0, 0,
);
}

View File

@ -0,0 +1,52 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
BalanceDurationRelative computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
weeks: Number.MAX_SAFE_INTEGER,
days: 7 * 3,
});
let result = duration.round({
largestUnit: "weeks",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
0, 0, 9007199254740994, 0,
0, 0, 0,
0, 0, 0,
);
}
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
weeks: Number.MAX_SAFE_INTEGER,
days: 7 * 3 + 1,
});
let result = duration.round({
largestUnit: "weeks",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
0, 0, 9007199254740994, 1,
0, 0, 0,
0, 0, 0,
);
}

View File

@ -0,0 +1,52 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
BalanceDurationRelative computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
years: Number.MAX_SAFE_INTEGER,
days: 366 + 365 + 365,
});
let result = duration.round({
largestUnit: "years",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
9007199254740994, 0, 0, 0,
0, 0, 0,
0, 0, 0,
);
}
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
years: Number.MAX_SAFE_INTEGER,
days: 366 + 365 + 365 + 1,
});
let result = duration.round({
largestUnit: "years",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
9007199254740994, 0, 0, 1,
0, 0, 0,
0, 0, 0,
);
}

View File

@ -0,0 +1,52 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
BalanceDurationRelative computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
years: Number.MAX_SAFE_INTEGER,
months: 12 * 3,
});
let result = duration.round({
largestUnit: "years",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
9007199254740994, 0, 0, 0,
0, 0, 0,
0, 0, 0,
);
}
{
let date = new Temporal.PlainDate(1970, 1, 1);
let duration = Temporal.Duration.from({
years: Number.MAX_SAFE_INTEGER,
months: 12 * 3 + 1,
});
let result = duration.round({
largestUnit: "years",
relativeTo: date,
});
TemporalHelpers.assertDuration(
result,
9007199254740994, 1, 0, 0,
0, 0, 0,
0, 0, 0,
);
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
BalanceDurationRelative computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let calendar = new class extends Temporal.Calendar {
#dateUntil = 0;
dateUntil(one, two, options) {
this.#dateUntil++;
// Subtract one six times from 9007199254740996.
if (this.#dateUntil <= 6) {
return Temporal.Duration.from({months: 1});
}
// After subtracting six in total, months is 9007199254740996 - 6 = 9007199254740990.
// |MAX_SAFE_INTEGER| = 9007199254740991 is larger than 9007199254740990, so we exit
// from the loop.
if (this.#dateUntil === 7) {
return Temporal.Duration.from({months: Number.MAX_SAFE_INTEGER});
}
// Any additional calls to dateUntil are incorrect.
throw new Test262Error("dateUntil called more times than expected");
}
}("iso8601");
let date = new Temporal.PlainDate(1970, 1, 1, calendar);
let duration = Temporal.Duration.from({
years: 0,
months: Number.MAX_SAFE_INTEGER + 4, // 9007199254740996
});
let result = duration.round({
largestUnit: "years",
relativeTo: date,
});
// Years is equal to the number of times we returned one month from dateUntil.
// Months is equal to 9007199254740996 - 6.
TemporalHelpers.assertDuration(
result,
6, 9007199254740990, 0, 0,
0, 0, 0,
0, 0, 0,
);

View File

@ -0,0 +1,50 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.round
description: >
RoundDuration computes on exact mathematical values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
{
let duration = Temporal.Duration.from({
hours: 100_000,
nanoseconds: 5,
});
let rounded = duration.round({smallestUnit: "hours", roundingMode: "ceil"});
// If RoundDuration() was implemented with float64, precision loss would lead
// to computing an incorrect result.
//
// "PT100000H" with float64, but "PT100001H" with exact mathematical values.
TemporalHelpers.assertDuration(
rounded,
0, 0, 0, 0,
100001, 0, 0,
0, 0, 0,
);
}
{
let duration = Temporal.Duration.from({
days: 1000,
nanoseconds: 5,
});
let rounded = duration.round({smallestUnit: "days", roundingMode: "ceil"});
// If RoundDuration() was implemented with float64, precision loss would lead
// to computing an incorrect result.
//
// "P1000D" with float64, but "P1001D" with exact mathematical values.
TemporalHelpers.assertDuration(
rounded,
0, 0, 0, 1001,
0, 0, 0,
0, 0, 0,
);
}

View File

@ -0,0 +1,57 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.subtract
description: >
AddDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const plainDate = new Temporal.PlainDate(1970, 1, 1);
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
// Largest temporal unit is "day".
const duration1 = Temporal.Duration.from({nanoseconds: Number.MAX_SAFE_INTEGER});
const duration2 = Temporal.Duration.from({nanoseconds: -2, days: -1});
const nanos = BigInt(Number.MAX_SAFE_INTEGER) + 2n;
TemporalHelpers.assertDuration(
duration1.subtract(duration2),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.subtract(duration2)"
);
TemporalHelpers.assertDuration(
duration1.subtract(duration2, {relativeTo: plainDate}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.subtract(duration2, {relativeTo: plainDate})"
);
TemporalHelpers.assertDuration(
duration1.subtract(duration2, {relativeTo: zonedDateTime}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.subtract(duration2, {relativeTo: zonedDateTime})"
);

View File

@ -0,0 +1,49 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.subtract
description: >
BalanceDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
const plainDate = new Temporal.PlainDate(1970, 1, 1);
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
// Largest temporal unit is "day".
const duration1 = Temporal.Duration.from({nanoseconds: Number.MAX_VALUE});
const duration2 = Temporal.Duration.from({nanoseconds: -Number.MAX_VALUE, days: -1});
const nanos = BigInt(Number.MAX_VALUE) * 2n;
TemporalHelpers.assertDuration(
duration1.subtract(duration2),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.subtract(duration2)"
);
TemporalHelpers.assertDuration(
duration1.subtract(duration2, {relativeTo: plainDate}),
0, 0, 0,
1 + Number((nanos / (24n * 60n * 60n * 1_000_000_000n))),
Number((nanos / (60n * 60n * 1_000_000_000n)) % 24n),
Number((nanos / (60n * 1_000_000_000n)) % 60n),
Number((nanos / 1_000_000_000n) % 60n),
Number((nanos / 1_000_000n) % 1000n),
Number((nanos / 1000n) % 1000n),
Number(nanos % 1000n),
"duration1.subtract(duration2, {relativeTo: plainDate})"
);
// Throws a RangeError because the intermediate instant is too large.
assert.throws(RangeError, () => {
duration1.subtract(duration2, {relativeTo: zonedDateTime});
});

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.subtract
description: >
AddDuration computes on exact mathematical number values.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
// Largest temporal unit is "microsecond".
let duration1 = Temporal.Duration.from({microseconds: Number.MAX_SAFE_INTEGER + 1, nanoseconds: 0});
let duration2 = Temporal.Duration.from({microseconds: -1, nanoseconds: -1000});
TemporalHelpers.assertDuration(
duration1.subtract(duration2),
0, 0, 0, 0,
0, 0, 0, 0,
9007199254740994,
0,
"duration1.subtract(duration2)"
);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal-temporaldurationtostring
description: >
Duration components are precise mathematical integers.
info: |
TemporalDurationToString ( years, months, weeks, days, hours, minutes, seconds, milliseconds,
microseconds, nanoseconds, precision )
...
2. Set microseconds to microseconds + RoundTowardsZero(nanoseconds / 1000).
3. Set nanoseconds to remainder(nanoseconds, 1000).
4. Set milliseconds to milliseconds + RoundTowardsZero(microseconds / 1000).
5. Set microseconds to remainder(microseconds, 1000).
6. Set seconds to seconds + RoundTowardsZero(milliseconds / 1000).
7. Set milliseconds to remainder(milliseconds, 1000).
...
features: [Temporal]
---*/
{
let d = Temporal.Duration.from({microseconds: 10000000000000004000, nanoseconds: 1000});
// "PT10000000000000.004096S" with float64.
// "PT10000000000000.004097S" with exact precision.
assert.sameValue(d.toString(), "PT10000000000000.004097S");
}
{
let d = Temporal.Duration.from({seconds: 10000000000000004000, microseconds: 1000});
// "PT10000000000000004000.001S" with float64.
// "PT10000000000000004096.001S" with exact precision.
assert.sameValue(d.toString(), "PT10000000000000004096.001S");
}

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.add
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
microseconds: Number.MAX_SAFE_INTEGER,
nanoseconds: 1000,
});
let time = Temporal.PlainTime.from({
microsecond: 1,
});
let result = time.add(duration);
TemporalHelpers.assertPlainTime(result, 23, 47, 34, 740, 993, 0);

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.add
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
hours: Number.MAX_VALUE,
minutes: Number.MAX_VALUE,
});
let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0);
let result = time.add(duration);
TemporalHelpers.assertPlainTime(result, 10, 8, 0, 0, 0, 0);

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.add
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
hours: Number.MAX_VALUE,
minutes: Number.MAX_VALUE,
seconds: Number.MAX_VALUE,
milliseconds: Number.MAX_VALUE,
microseconds: Number.MAX_VALUE,
nanoseconds: Number.MAX_VALUE,
});
let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0);
let result = time.add(duration);
TemporalHelpers.assertPlainTime(result, 3, 53, 35, 351, 226, 368);

View File

@ -0,0 +1,23 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.subtract
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
microseconds: Number.MIN_SAFE_INTEGER,
nanoseconds: -1000,
});
let time = Temporal.PlainTime.from({
microsecond: 1,
});
let result = time.subtract(duration);
TemporalHelpers.assertPlainTime(result, 23, 47, 34, 740, 993, 0);

View File

@ -0,0 +1,21 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.subtract
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
hours: -Number.MAX_VALUE,
minutes: -Number.MAX_VALUE,
});
let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0);
let result = time.subtract(duration);
TemporalHelpers.assertPlainTime(result, 10, 8, 0, 0, 0, 0);

View File

@ -0,0 +1,25 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaintime.prototype.subtract
description: >
Duration components are precise mathematical integers.
includes: [temporalHelpers.js]
features: [Temporal]
---*/
let duration = Temporal.Duration.from({
hours: -Number.MAX_VALUE,
minutes: -Number.MAX_VALUE,
seconds: -Number.MAX_VALUE,
milliseconds: -Number.MAX_VALUE,
microseconds: -Number.MAX_VALUE,
nanoseconds: -Number.MAX_VALUE,
});
let time = new Temporal.PlainTime(0, 0, 0, 0, 0, 0);
let result = time.subtract(duration);
TemporalHelpers.assertPlainTime(result, 3, 53, 35, 351, 226, 368);

View File

@ -0,0 +1,27 @@
// Copyright (C) 2022 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.timezone
description: >
TimeZone constructor canonicalises its input.
features: [Temporal]
---*/
const testCases = {
"Etc/GMT": "UTC",
"Etc/GMT+0": "UTC",
"Etc/GMT-0": "UTC",
"Etc/GMT0": "UTC",
"Etc/Greenwich": "UTC",
"Etc/UCT": "UTC",
"Etc/UTC": "UTC",
"Etc/Universal": "UTC",
"Etc/Zulu": "UTC",
};
for (let [id, canonical] of Object.entries(testCases)) {
let tz = new Temporal.TimeZone(id);
assert.sameValue(tz.id, canonical);
}