Temporal: Limit duration years, months, and weeks to <2³² each

This commit is contained in:
Philip Chimento 2023-06-19 18:30:57 +02:00 committed by Philip Chimento
parent 01ec9938bb
commit 99d5bc8c1b
36 changed files with 662 additions and 94 deletions

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.Calendar("iso8601");
const maxCases = [
["P273790Y8M12DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M12DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W2DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000000DT23H59M59.999999999S", "string with max days"],
[{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000023H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M12DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W3DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -3, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000001DT23H59M59.999999999S", "string with min days"],
[{ days: -100000001, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000047H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.Calendar("iso8601");
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -4,7 +4,7 @@
/*---
esid: sec-temporal.calendar.prototype.dateadd
description: >
Call BalanceISOYearMonth with Number.MAX_VALUE and -Number.MAX_VALUE for years/months.
Call BalanceISOYearMonth with 2³² - 1 and -(2³² - 1) for years/months.
info: |
Temporal.Calendar.prototype.dateAdd ( date, duration [ , options ] )
@ -26,8 +26,10 @@ features: [Temporal]
var cal = new Temporal.Calendar("iso8601");
var date = new Temporal.PlainDate(1970, 1, 1);
var maxValue = new Temporal.Duration(Number.MAX_VALUE, Number.MAX_VALUE);
var minValue = new Temporal.Duration(-Number.MAX_VALUE, -Number.MAX_VALUE);
const max = 4294967295; // 2³² - 1
var maxValue = new Temporal.Duration(max, max);
var minValue = new Temporal.Duration(-max, -max);
assert.throws(RangeError, () => cal.dateAdd(date, maxValue), "years/months is +Number.MAX_VALUE");
assert.throws(RangeError, () => cal.dateAdd(date, minValue), "years/months is -Number.MAX_VALUE");

View File

@ -8,6 +8,20 @@ features: [Temporal]
---*/
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -8,6 +8,12 @@ features: [Temporal]
---*/
const maxCases = [
["P4294967295Y104249991374DT7H36M31.999999999S", "string with max years"],
[{ years: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max years"],
["P4294967295M104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ months: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max months"],
["P4294967295W104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ weeks: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max weeks"],
["P104249991374DT7H36M31.999999999S", "string with max days"],
[{ days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max days"],
["PT2501999792983H36M31.999999999S", "string with max hours"],
@ -20,10 +26,16 @@ const maxCases = [
for (const [arg, descr] of maxCases) {
const result = Temporal.Duration.from(arg);
assert.sameValue(result.total("seconds"), 9007199254740991.999999999, `operation succeeds with ${descr}`);
assert.sameValue(result.with({ years: 0, months: 0, weeks: 0 }).total("seconds"), 9007199254740991.999999999, `operation succeeds with ${descr}`);
}
const minCases = [
["-P4294967295Y104249991374DT7H36M31.999999999S", "string with min years"],
[{ years: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min years"],
["-P4294967295M104249991374DT7H36M31.999999999S", "string with min months"],
[{ months: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min months"],
["-P4294967295W104249991374DT7H36M31.999999999S", "string with min weeks"],
[{ weeks: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min weeks"],
["-P104249991374DT7H36M31.999999999S", "string with min days"],
[{ days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min days"],
["-PT2501999792983H36M31.999999999S", "string with min hours"],
@ -36,5 +48,5 @@ const minCases = [
for (const [arg, descr] of minCases) {
const result = Temporal.Duration.from(arg);
assert.sameValue(result.total("seconds"), -9007199254740991.999999999, `operation succeeds with ${descr}`);
assert.sameValue(result.with({ years: 0, months: 0, weeks: 0 }).total("seconds"), -9007199254740991.999999999, `operation succeeds with ${descr}`);
}

View File

@ -4,6 +4,7 @@
/*---
esid: sec-temporal.duration
description: Maximum values of arguments to the Duration constructor
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -21,3 +22,9 @@ const cases = [
for (const [d, descr, expected] of cases) {
assert.sameValue(d.total("seconds"), expected, descr);
}
// 2^32 - 1 = 4294967295
const max = new Temporal.Duration(4294967295, 4294967295, 4294967295, 104249991374, 7, 36, 31, 999, 999, 999);
TemporalHelpers.assertDuration(max, 4294967295, 4294967295, 4294967295, 104249991374, 7, 36, 31, 999, 999, 999);
const min = new Temporal.Duration(-4294967295, -4294967295, -4294967295, -104249991374, -7, -36, -31, -999, -999, -999);
TemporalHelpers.assertDuration(min, -4294967295, -4294967295, -4294967295, -104249991374, -7, -36, -31, -999, -999, -999);

View File

@ -7,6 +7,14 @@ description: Various arguments to the Duration constructor that are out of range
features: [Temporal]
---*/
// 2^32 = 4294967296
assert.throws(RangeError, () => new Temporal.Duration(4294967296), "years > max");
assert.throws(RangeError, () => new Temporal.Duration(-4294967296), "years < min");
assert.throws(RangeError, () => new Temporal.Duration(0, 4294967296), "months > max");
assert.throws(RangeError, () => new Temporal.Duration(0, -4294967296), "months < min");
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 4294967296), "days > max");
assert.throws(RangeError, () => new Temporal.Duration(0, 0, -4294967296), "days < min");
// ceil(max safe integer / 86400) = 104249991375
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 104249991375), "days > max");
assert.throws(RangeError, () => new Temporal.Duration(0, 0, 0, 104249991374, 24), "hours balance into days > max");

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.Duration();
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -22,7 +22,7 @@ const maxCases = [
for (const [arg, descr] of maxCases) {
const result = instance.subtract(arg);
assert.sameValue(result.total("seconds"), -9007199254740991.999999999, `operation succeeds with ${descr}`);
assert.sameValue(result.with({ years: 0, months: 0, weeks: 0 }).total("seconds"), -9007199254740991.999999999, `operation succeeds with ${descr}`);
}
const minCases = [
@ -38,5 +38,5 @@ const minCases = [
for (const [arg, descr] of minCases) {
const result = instance.subtract(arg);
assert.sameValue(result.total("seconds"), 9007199254740991.999999999, `operation succeeds with ${descr}`);
assert.sameValue(result.with({ years: 0, months: 0, weeks: 0 }).total("seconds"), 9007199254740991.999999999, `operation succeeds with ${descr}`);
}

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.Duration();
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -1,44 +0,0 @@
// 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 formatted as precise decimal numbers.
info: |
TemporalDurationToString ( years, months, weeks, days, hours, minutes, seconds, milliseconds,
microseconds, nanoseconds, precision )
...
9. If years is not 0, then
a. Set datePart to the string concatenation of abs(years) formatted as a decimal number and
the code unit 0x0059 (LATIN CAPITAL LETTER Y).
10. If months is not 0, then
a. Set datePart to the string concatenation of datePart, abs(months) formatted as a decimal
number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
If weeks is not 0, then
a. Set datePart to the string concatenation of datePart, abs(weeks) formatted as a decimal
number, and the code unit 0x0057 (LATIN CAPITAL LETTER W).
...
features: [Temporal]
---*/
{
let d = Temporal.Duration.from({weeks: 10000000000000004000});
// Number(10000000000000004000).toString() is "10000000000000004000".
assert.sameValue(d.toString(), "P10000000000000004096W");
}
{
let d = Temporal.Duration.from({months: 9e59});
// Number(9e+59).toString() is "9e+59".
assert.sameValue(d.toString(), "P899999999999999918767229449717619953810131273674690656206848M");
}
{
let d = Temporal.Duration.from({years: Number.MAX_VALUE});
// Number.MAX_VALUE.toString() is "1.7976931348623157e+308".
assert.sameValue(d.toString(), "P179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368Y");
}

View File

@ -0,0 +1,118 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
RoundDuration computes in such a way as to avoid precision loss when the
computed day, week, month, and year lengths are very large numbers.
info: |
RoundDuration:
...
7. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then
a. If _zonedRelativeTo_ is not *undefined*, then
...
iii. Let _fractionalDays_ be _days_ + _result_.[[Days]] + DivideNormalizedTimeDuration(_result_.[[Remainder]], _result_.[[DayLength]]).
...
10. If _unit_ is *"year"*, then
...
z. Let _fractionalYears_ be _years_ + _fractionalDays_ / abs(_oneYearDays_).
...
11. If _unit_ is *"month"*, then
...
z. Let _fractionalMonths_ be _months_ + _fractionalDays_ / abs(_oneMonthDays_).
...
12. If _unit_ is *"week"*, then
...
s. Let _fractionalWeeks_ be _weeks_ + _fractionalDays_ / abs(_oneWeekDays_).
includes: [compareArray.js]
features: [Temporal]
---*/
// Return the next Number value in direction to +Infinity.
function nextUp(num) {
if (!Number.isFinite(num)) {
return num;
}
if (num === 0) {
return Number.MIN_VALUE;
}
var f64 = new Float64Array([num]);
var u64 = new BigUint64Array(f64.buffer);
u64[0] += (num < 0 ? -1n : 1n);
return f64[0];
}
// Return the next Number value in direction to -Infinity.
function nextDown(num) {
if (!Number.isFinite(num)) {
return num;
}
if (num === 0) {
return -Number.MIN_VALUE;
}
var f64 = new Float64Array([num]);
var u64 = new BigUint64Array(f64.buffer);
u64[0] += (num < 0 ? 1n : -1n);
return f64[0];
}
// Return bit pattern representation of Number as a Uint8Array of bytes.
function f64Repr(f) {
const buf = new ArrayBuffer(8);
new DataView(buf).setFloat64(0, f);
return new Uint8Array(buf);
}
// ============
const tz = new (class extends Temporal.TimeZone {
getPossibleInstantsFor() {
// Called in NormalizedTimeDurationToDays 21.a from RoundDuration 7.b.
// Sets _result_.[[DayLength]] to 2⁵³ - 1 ns, its largest possible value
return [new Temporal.Instant(-86400_0000_0000_000_000_000n + 2n ** 53n - 1n)];
}
})("UTC");
const cal = new (class extends Temporal.Calendar {
dateAdd() {
// Called in MoveRelativeDate from RoundDuration 10.x, 11.x, or 12.q.
// Sets _oneYearDays_, _oneMonthDays_, or _oneWeekDays_ respectively to
// 200_000_000, its largest possible value.
return new Temporal.PlainDate(275760, 9, 13);
}
})("iso8601");
const relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, tz, cal);
const d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, /* nanoseconds = */ 1);
/*
* RoundDuration step 7:
* ii. result = { [[Days]] = 0, [[Remainder]] = normalized time duration of 1 ns,
* [[DayLength]] = Number.MAX_SAFE_INTEGER }
* iii. fractionalDays = 0 + 0 + 1 / Number.MAX_SAFE_INTEGER
* step 10:
* y. oneYearDays = 200_000_000
* z. fractionalYears = 0 + (1 / Number.MAX_SAFE_INTEGER) / 200_000_000
*/
// Calculated with Python's Decimal module to 50 decimal places
const expected = 5.55111512312578_3318415740544369642963189519987393e-25;
// Check that we are not accidentally losing precision in our expected value:
assert.sameValue(expected, 5.55111512312578_373662e-25, "the float representation of the result is 5.55111512312578373662e-25");
assert.compareArray(
f64Repr(expected),
[0x3a, 0xe5, 0x79, 0x8e, 0xe2, 0x30, 0x8c, 0x3b],
"the bit representation of the result is 0x3ae5798ee2308c3b"
);
// The next Number in direction -Infinity is less precise.
assert.sameValue(nextDown(expected), 5.55111512312578_281826e-25, "the next Number in direction -Infinity is less precise");
// The next Number in direction +Infinity is less precise.
assert.sameValue(nextUp(expected), 5.55111512312578_465497e-25, "the next Number in direction +Infinity is less precise");
assert.sameValue(d.total({ unit: "years", relativeTo }), expected, "Correct division by large number in years total");
assert.sameValue(d.total({ unit: "months", relativeTo }), expected, "Correct division by large number in months total");
assert.sameValue(d.total({ unit: "weeks", relativeTo }), expected, "Correct division by large number in weeks total");

View File

@ -0,0 +1,152 @@
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.duration.prototype.total
description: >
RoundDuration computes in such a way as to avoid precision loss when the
computed day, week, month, and year lengths are very large numbers.
info: |
RoundDuration:
...
7. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then
a. If _zonedRelativeTo_ is not *undefined*, then
...
iii. Let _fractionalDays_ be _days_ + _result_.[[Days]] + DivideNormalizedTimeDuration(_result_.[[Remainder]], _result_.[[DayLength]]).
...
10. If _unit_ is *"year"*, then
...
z. Let _fractionalYears_ be _years_ + _fractionalDays_ / abs(_oneYearDays_).
...
11. If _unit_ is *"month"*, then
...
z. Let _fractionalMonths_ be _months_ + _fractionalDays_ / abs(_oneMonthDays_).
...
12. If _unit_ is *"week"*, then
...
s. Let _fractionalWeeks_ be _weeks_ + _fractionalDays_ / abs(_oneWeekDays_).
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
// Return the next Number value in direction to +Infinity.
function nextUp(num) {
if (!Number.isFinite(num)) {
return num;
}
if (num === 0) {
return Number.MIN_VALUE;
}
var f64 = new Float64Array([num]);
var u64 = new BigUint64Array(f64.buffer);
u64[0] += (num < 0 ? -1n : 1n);
return f64[0];
}
// Return the next Number value in direction to -Infinity.
function nextDown(num) {
if (!Number.isFinite(num)) {
return num;
}
if (num === 0) {
return -Number.MIN_VALUE;
}
var f64 = new Float64Array([num]);
var u64 = new BigUint64Array(f64.buffer);
u64[0] += (num < 0 ? 1n : -1n);
return f64[0];
}
// Return bit pattern representation of Number as a Uint8Array of bytes.
function f64Repr(f) {
const buf = new ArrayBuffer(8);
new DataView(buf).setFloat64(0, f);
return new Uint8Array(buf);
}
// ============
// Set up contrived custom time zone and calendar to give dayLengthNs,
// oneYearDays, oneMonthDays, and oneWeekDays their largest possible values
function createTimeZone() {
const tz = new Temporal.TimeZone("UTC");
TemporalHelpers.substituteMethod(tz, "getPossibleInstantsFor", [
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.e.ii AddDaysToZonedDateTime
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.i.ii NormalizedTimeDurationToDays step 16
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.i.ii NormalizedTimeDurationToDays step 19
[new Temporal.Instant(-86400_0000_0000_000_000_000n)], // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime
[new Temporal.Instant(-86400_0000_0000_000_000_000n + 2n ** 53n - 1n)], // RoundDuration step 7.a.ii NormalizedTimeDurationToDays step 19
// sets dayLengthNs to Number.MAX_SAFE_INTEGER
]);
return tz;
}
function createCalendar() {
const cal = new Temporal.Calendar("iso8601");
TemporalHelpers.substituteMethod(cal, "dateAdd", [
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime
TemporalHelpers.SUBSTITUTE_SKIP, // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime
new Temporal.PlainDate(-271821, 4, 20), // RoundDuration step 10.d/11.d AddDate
new Temporal.PlainDate(-271821, 4, 20), // RoundDuration step 10.f/11.f AddDate
new Temporal.PlainDate(275760, 9, 13), // RoundDuration step 10.r/11.r MoveRelativeDate
// sets one{Year,Month,Week}Days to 200_000_000
]);
return cal;
}
// ============
// We will calculate the total years/months/weeks of durations with:
// 1 year/month/week, 1 day, 0.199000001 s
// RoundDuration step 7:
// ii. result = { [[Days]] = 1, [[Remainder]] = normalized time duration of 199_000_001 ns,
// [[DayLength]] = Number.MAX_SAFE_INTEGER }
// iii. fractionalDays = 1 + 0 + 199_000_001 / Number.MAX_SAFE_INTEGER
// step 10: (similar for steps 11 and 12 in the case of months/weeks)
// y. oneYearDays = 200_000_000
// z. fractionalYears = 1 + (1 + 199_000_001 / Number.MAX_SAFE_INTEGER) / 200_000_000
//
// Note: if calculated as 1 + 1/200_000_000 + 199_000_001 / Number.MAX_SAFE_INTEGER / 200_000_000
// this will lose precision and give the result 1.000000005.
// Calculated with Python's Decimal module to 50 decimal places
const expected = 1.000000005000000_1104671915053146003490515686745299;
// Check that we are not accidentally losing precision in our expected value:
assert.sameValue(expected, 1.000000005000000_2, "the float representation of the result is 1.0000000050000002");
assert.compareArray(
f64Repr(expected),
[0x3f, 0xf0, 0x00, 0x00, 0x01, 0x57, 0x98, 0xef],
"the bit representation of the result is 0x3ff00000015798ef"
);
// The next Number in direction -Infinity is less precise.
assert.sameValue(nextDown(expected), 1.000000004999999_96961, "the next Number in direction -Infinity is less precise");
// The next Number in direction +Infinity is less precise.
assert.sameValue(nextUp(expected), 1.000000005000000_4137, "the next Number in direction +Infinity is less precise");
// ============
let relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), createCalendar());
const dYears = new Temporal.Duration(/* years = */ 1, 0, 0, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1);
assert.sameValue(dYears.total({ unit: "years", relativeTo }), expected, "Correct division by large number in years total");
relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), createCalendar());
const dMonths = new Temporal.Duration(0, /* months = */ 1, 0, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1);
assert.sameValue(dMonths.total({ unit: "months", relativeTo }), expected, "Correct division by large number in months total");
// Weeks calculation doesn't have the AddDate calls to convert months/weeks to days
const weeksCal = new Temporal.Calendar("iso8601");
TemporalHelpers.substituteMethod(weeksCal, "dateAdd", [
TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime
TemporalHelpers.SUBSTITUTE_SKIP, // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime
new Temporal.PlainDate(275760, 9, 13), // RoundDuration step 12.q MoveRelativeDate
// sets one{Year,Month,Week}Days to 200_000_000
]);
relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), weeksCal);
const dWeeks = new Temporal.Duration(0, 0, /* weejs = */ 1, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1);
assert.sameValue(dWeeks.total({ unit: "weeks", relativeTo }), expected, "Correct division by large number in weeks total");

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.Instant(0n);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.Instant(0n);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainDate(1970, 1, 1);
const maxCases = [
["P273790Y8M12DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M12DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W2DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000000DT23H59M59.999999999S", "string with max days"],
[{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000023H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M12DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W3DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -3, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000001DT23H59M59.999999999S", "string with min days"],
[{ days: -100000001, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000047H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainDate(1970, 1, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainDate(1970, 1, 1);
const maxCases = [
["P273790Y8M12DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M12DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W3DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 3, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000001DT23H59M59.999999999S", "string with max days"],
[{ days: 100000001, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000047H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M12DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W2DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -2, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000000DT23H59M59.999999999S", "string with min days"],
[{ days: -100000000, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000023H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainDate(1970, 1, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainDateTime(1970, 1, 1);
const maxCases = [
["P273790Y8M12DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M12DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W2DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000000DT23H59M59.999999999S", "string with max days"],
[{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000023H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M11DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -11, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M11DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -11, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W2DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -2, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000000DT23H59M59.999999999S", "string with min days"],
[{ days: -100000000, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000023H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainDateTime(1970, 1, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainDateTime(1970, 1, 1);
const maxCases = [
["P273790Y8M11DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 11, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M11DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 11, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W2DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000000DT23H59M59.999999999S", "string with max days"],
[{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000023H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M12DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W2DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -2, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000000DT23H59M59.999999999S", "string with min days"],
[{ days: -100000000, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000023H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainDateTime(1970, 1, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainTime();
const maxCases = [
["P4294967295Y104249991374DT7H36M31.999999999S", "string with max years"],
[{ years: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max years"],
["P4294967295M104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ months: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max months"],
["P4294967295W104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ weeks: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max weeks"],
["P104249991374DT7H36M31.999999999S", "string with max days"],
[{ days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max days"],
["PT2501999792983H36M31.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P4294967295Y104249991374DT7H36M31.999999999S", "string with min years"],
[{ years: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min years"],
["-P4294967295M104249991374DT7H36M31.999999999S", "string with min months"],
[{ months: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min months"],
["-P4294967295W104249991374DT7H36M31.999999999S", "string with min weeks"],
[{ weeks: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min weeks"],
["-P104249991374DT7H36M31.999999999S", "string with min days"],
[{ days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min days"],
["-PT2501999792983H36M31.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainTime();
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainTime();
const maxCases = [
["P4294967295Y104249991374DT7H36M31.999999999S", "string with max years"],
[{ years: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max years"],
["P4294967295M104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ months: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max months"],
["P4294967295W104249991374DT7H36M31.999999999S", "string with max weeks"],
[{ weeks: 4294967295, days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max weeks"],
["P104249991374DT7H36M31.999999999S", "string with max days"],
[{ days: 104249991374, nanoseconds: 27391999999999 }, "property bag with max days"],
["PT2501999792983H36M31.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P4294967295Y104249991374DT7H36M31.999999999S", "string with min years"],
[{ years: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min years"],
["-P4294967295M104249991374DT7H36M31.999999999S", "string with min months"],
[{ months: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min months"],
["-P4294967295W104249991374DT7H36M31.999999999S", "string with min weeks"],
[{ weeks: -4294967295, days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min weeks"],
["-P104249991374DT7H36M31.999999999S", "string with min days"],
[{ days: -104249991374, nanoseconds: -27391999999999 }, "property bag with min days"],
["-PT2501999792983H36M31.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainTime();
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainYearMonth(1970, 1);
const maxCases = [
["P273790Y8M12DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 12, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M12DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 12, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285714W2DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285714, days: 2, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000000DT23H59M59.999999999S", "string with max days"],
[{ days: 100000000, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000023H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M42DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -42, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M42DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -42, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285718W5DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285718, days: -5, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000031DT23H59M59.999999999S", "string with min days"],
[{ days: -100000031, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000767H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainYearMonth(1970, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -11,6 +11,12 @@ features: [Temporal]
const instance = new Temporal.PlainYearMonth(1970, 1);
const maxCases = [
["P273790Y8M42DT23H59M59.999999999S", "string with max years"],
[{ years: 273790, months: 8, days: 42, nanoseconds: 86399999999999 }, "property bag with max years"],
["P3285488M42DT23H59M59.999999999S", "string with max months"],
[{ months: 3285488, days: 42, nanoseconds: 86399999999999 }, "property bag with max months"],
["P14285718W5DT23H59M59.999999999S", "string with max weeks"],
[{ weeks: 14285718, days: 5, nanoseconds: 86399999999999 }, "property bag with max weeks"],
["P100000031DT23H59M59.999999999S", "string with max days"],
[{ days: 100000031, nanoseconds: 86399999999999 }, "property bag with max days"],
["PT2400000767H59M59.999999999S", "string with max hours"],
@ -27,6 +33,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12DT23H59M59.999999999S", "string with min years"],
[{ years: -273790, months: -8, days: -12, nanoseconds: -86399999999999 }, "property bag with min years"],
["-P3285488M12DT23H59M59.999999999S", "string with min months"],
[{ months: -3285488, days: -12, nanoseconds: -86399999999999 }, "property bag with min months"],
["-P14285714W2DT23H59M59.999999999S", "string with min weeks"],
[{ weeks: -14285714, days: -2, nanoseconds: -86399999999999 }, "property bag with min weeks"],
["-P100000000DT23H59M59.999999999S", "string with min days"],
[{ days: -100000000, nanoseconds: -86399999999999 }, "property bag with min days"],
["-PT2400000023H59M59.999999999S", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.PlainYearMonth(1970, 1);
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -10,6 +10,12 @@ features: [Temporal]
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const maxCases = [
["P273790Y8M12D", "string with max years"],
[{ years: 273790, months: 8, days: 12 }, "property bag with max years"],
["P3285488M12D", "string with max months"],
[{ months: 3285488, days: 12 }, "property bag with max months"],
["P14285714W2D", "string with max weeks"],
[{ weeks: 14285714, days: 2 }, "property bag with max weeks"],
["P100000000D", "string with max days"],
[{ days: 100000000 }, "property bag with max days"],
["PT2400000000H", "string with max hours"],
@ -26,6 +32,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M11D", "string with min years"],
[{ years: -273790, months: -8, days: -11 }, "property bag with min years"],
["-P3285488M11D", "string with min months"],
[{ months: -3285488, days: -11 }, "property bag with min months"],
["-P14285714W2D", "string with min weeks"],
[{ weeks: -14285714, days: -2 }, "property bag with min weeks"],
["-P100000000D", "string with min days"],
[{ days: -100000000 }, "property bag with min days"],
["-PT2400000000H", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -10,6 +10,12 @@ features: [Temporal]
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const maxCases = [
["P273790Y8M11D", "string with max years"],
[{ years: 273790, months: 8, days: 11 }, "property bag with max years"],
["P3285488M11D", "string with max months"],
[{ months: 3285488, days: 11 }, "property bag with max months"],
["P14285714W2D", "string with max weeks"],
[{ weeks: 14285714, days: 2 }, "property bag with max weeks"],
["P100000000D", "string with max days"],
[{ days: 100000000 }, "property bag with max days"],
["PT2400000000H", "string with max hours"],
@ -26,6 +32,12 @@ for (const [arg, descr] of maxCases) {
}
const minCases = [
["-P273790Y8M12D", "string with min years"],
[{ years: -273790, months: -8, days: -12 }, "property bag with min years"],
["-P3285488M12D", "string with min months"],
[{ months: -3285488, days: -12 }, "property bag with min months"],
["-P14285714W2D", "string with min weeks"],
[{ weeks: -14285714, days: -2 }, "property bag with min weeks"],
["-P100000000D", "string with min days"],
[{ days: -100000000 }, "property bag with min days"],
["-PT2400000000H", "string with min hours"],

View File

@ -10,6 +10,20 @@ features: [Temporal]
const instance = new Temporal.ZonedDateTime(0n, "UTC");
const cases = [
// 2^32 = 4294967296
["P4294967296Y", "string with years > max"],
[{ years: 4294967296 }, "property bag with years > max"],
["-P4294967296Y", "string with years < min"],
[{ years: -4294967296 }, "property bag with years < min"],
["P4294967296M", "string with months > max"],
[{ months: 4294967296 }, "property bag with months > max"],
["-P4294967296M", "string with months < min"],
[{ months: -4294967296 }, "property bag with months < min"],
["P4294967296W", "string with weeks > max"],
[{ weeks: 4294967296 }, "property bag with weeks > max"],
["-P4294967296W", "string with weeks < min"],
[{ weeks: -4294967296 }, "property bag with weeks < min"],
// ceil(max safe integer / 86400) = 104249991375
["P104249991375D", "string with days > max"],
[{ days: 104249991375 }, "property bag with days > max"],

View File

@ -32,46 +32,3 @@ units.forEach(unit => assert.sameValue(`${ Temporal.Duration.from({ [unit]: 0 })
"PT0M",
"PT0S"
].forEach(str => assert.sameValue(`${ Temporal.Duration.from(str) }`, "PT0S"));
// unrepresentable number is not allowed
units.forEach((unit, ix) => {
assert.throws(RangeError, () => new Temporal.Duration(...Array(ix).fill(0), 1e+400));
assert.throws(RangeError, () => Temporal.Duration.from({ [unit]: 1e+400 }));
});
var manyNines = "9".repeat(309);
[
`P${ manyNines }Y`,
`P${ manyNines }M`,
`P${ manyNines }W`,
`P${ manyNines }D`,
`PT${ manyNines }H`,
`PT${ manyNines }M`,
`PT${ manyNines }S`
].forEach(str => assert.throws(RangeError, () => Temporal.Duration.from(str)));
// max safe integer is allowed in calendar units and as seconds
[
[0, "P9007199254740991Y"],
[1, "P9007199254740991M"],
[2, "P9007199254740991W"],
[6, "PT9007199254740991S"],
].forEach(([ix, str]) => {
assert.sameValue(`${ new Temporal.Duration(...Array(ix).fill(0), Number.MAX_SAFE_INTEGER) }`, str);
assert.sameValue(`${ Temporal.Duration.from(str) }`, str);
});
// larger integers are allowed in calendar units but may lose precision
function test(ix, suffix) {
function doAsserts(duration) {
var str = duration.toString();
assert.sameValue(str.slice(0, 11), "P1000000000");
assert.sameValue(str.slice(-1), suffix);
assert.sameValue(str.length, suffix.length + 28);
}
doAsserts(new Temporal.Duration(...Array(ix).fill(0), 1e+26, ...Array(9 - ix).fill(0)));
doAsserts(Temporal.Duration.from({ [units[ix]]: 1e+26 }));
doAsserts(Temporal.Duration.from(`P100000000000001000000000000${ suffix }`));
}
test(0, "Y");
test(1, "M");
test(2, "W");