mirror of https://github.com/tc39/test262.git
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:
parent
e849d40605
commit
eaf85892fb
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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));
|
||||
}
|
57
test/built-ins/Temporal/Duration/prototype/add/nanoseconds-is-number-max-safe-integer.js
vendored
Normal file
57
test/built-ins/Temporal/Duration/prototype/add/nanoseconds-is-number-max-safe-integer.js
vendored
Normal 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})"
|
||||
);
|
49
test/built-ins/Temporal/Duration/prototype/add/nanoseconds-is-number-max-value-2.js
vendored
Normal file
49
test/built-ins/Temporal/Duration/prototype/add/nanoseconds-is-number-max-value-2.js
vendored
Normal 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});
|
||||
});
|
23
test/built-ins/Temporal/Duration/prototype/add/precision-exact-mathematical-values.js
vendored
Normal file
23
test/built-ins/Temporal/Duration/prototype/add/precision-exact-mathematical-values.js
vendored
Normal 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)"
|
||||
);
|
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
);
|
||||
}
|
|
@ -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,
|
||||
);
|
50
test/built-ins/Temporal/Duration/prototype/round/precision-exact-in-round-duration.js
vendored
Normal file
50
test/built-ins/Temporal/Duration/prototype/round/precision-exact-in-round-duration.js
vendored
Normal 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,
|
||||
);
|
||||
}
|
57
test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-is-number-max-safe-integer.js
vendored
Normal file
57
test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-is-number-max-safe-integer.js
vendored
Normal 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})"
|
||||
);
|
49
test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-is-number-max-value-2.js
vendored
Normal file
49
test/built-ins/Temporal/Duration/prototype/subtract/nanoseconds-is-number-max-value-2.js
vendored
Normal 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});
|
||||
});
|
23
test/built-ins/Temporal/Duration/prototype/subtract/precision-exact-mathematical-values.js
vendored
Normal file
23
test/built-ins/Temporal/Duration/prototype/subtract/precision-exact-mathematical-values.js
vendored
Normal 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)"
|
||||
);
|
36
test/built-ins/Temporal/Duration/prototype/toString/precision-exact-mathematical-values.js
vendored
Normal file
36
test/built-ins/Temporal/Duration/prototype/toString/precision-exact-mathematical-values.js
vendored
Normal 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");
|
||||
}
|
23
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-1.js
vendored
Normal file
23
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-1.js
vendored
Normal 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);
|
21
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-2.js
vendored
Normal file
21
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-2.js
vendored
Normal 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);
|
25
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-3.js
vendored
Normal file
25
test/built-ins/Temporal/PlainTime/prototype/add/precision-exact-mathematical-values-3.js
vendored
Normal 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);
|
23
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-1.js
vendored
Normal file
23
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-1.js
vendored
Normal 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);
|
21
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-2.js
vendored
Normal file
21
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-2.js
vendored
Normal 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);
|
25
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-3.js
vendored
Normal file
25
test/built-ins/Temporal/PlainTime/prototype/subtract/precision-exact-mathematical-values-3.js
vendored
Normal 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);
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue