mirror of https://github.com/tc39/test262.git
Temporal: Remove tests using relativeTo in Duration.p.add/subtract
See tc39/proposal-temporal#2825. This is a mass removal of tests that use this functionality, in a separate commit for ease of review. Further adjustments will be made in the following commit.
This commit is contained in:
parent
ba9c397923
commit
ea4945c66f
|
@ -10,20 +10,6 @@ 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"],
|
||||
|
|
|
@ -3,24 +3,7 @@
|
|||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays
|
||||
info: |
|
||||
sec-temporal-nanosecondstodays step 6:
|
||||
6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then
|
||||
a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }.
|
||||
sec-temporal-balanceduration step 4:
|
||||
4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then
|
||||
a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_).
|
||||
sec-temporal-addduration steps 5–6:
|
||||
5. If _relativeTo_ is *undefined*, then
|
||||
...
|
||||
b. Let _result_ be ! BalanceDuration(_d1_ + _d2_, _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_).
|
||||
...
|
||||
6. Else if _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then
|
||||
...
|
||||
n. Let _result_ be ! BalanceDuration(_dateDifference_.[[Days]], _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_).
|
||||
sec-temporal.duration.prototype.add step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_).
|
||||
description: A negative duration result is balanced only up to hours
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
@ -30,7 +13,3 @@ const duration2 = new Temporal.Duration(0, 0, 0, -1);
|
|||
|
||||
const resultNotRelative = duration1.add(duration2);
|
||||
TemporalHelpers.assertDuration(resultNotRelative, 0, 0, 0, -3, -12, 0, 0, 0, 0, 0);
|
||||
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
const resultRelative = duration1.add(duration2, { relativeTo });
|
||||
TemporalHelpers.assertDuration(resultRelative, 0, 0, 0, -3, -12, 0, 0, 0, 0, 0);
|
||||
|
|
|
@ -3,58 +3,27 @@
|
|||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Negative time fields in relativeTo are balanced upwards
|
||||
info: |
|
||||
sec-temporal-balancetime steps 3–14:
|
||||
3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000).
|
||||
4. Set _nanosecond_ to _nanosecond_ modulo 1000.
|
||||
5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000).
|
||||
6. Set _microsecond_ to _microsecond_ modulo 1000.
|
||||
7. Set _second_ to _second_ + floor(_millisecond_ / 1000).
|
||||
8. Set _millisecond_ to _millisecond_ modulo 1000.
|
||||
9. Set _minute_ to _minute_ + floor(_second_ / 60).
|
||||
10. Set _second_ to _second_ modulo 60.
|
||||
11. Set _hour_ to _hour_ + floor(_minute_ / 60).
|
||||
12. Set _minute_ to _minute_ modulo 60.
|
||||
13. Let _days_ be floor(_hour_ / 24).
|
||||
14. Set _hour_ to _hour_ modulo 24.
|
||||
sec-temporal-differencetime step 8:
|
||||
8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
|
||||
sec-temporal-differenceisodatetime step 2:
|
||||
2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_).
|
||||
sec-temporal-differencezoneddatetime step 7:
|
||||
7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_).
|
||||
sec-temporal-addduration step 7.g.i:
|
||||
i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_).
|
||||
sec-temporal.duration.prototype.add step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_).
|
||||
description: Negative time fields are balanced upwards
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const relativeTo = new Temporal.ZonedDateTime(830998861_000_000_000n, timeZone);
|
||||
// This code path is encountered if largestUnit is years, months, weeks, or days
|
||||
// and relativeTo is a ZonedDateTime
|
||||
const options = { largestUnit: "days", relativeTo };
|
||||
|
||||
const result1 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2), options);
|
||||
const result1 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance");
|
||||
|
||||
const result2 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2), options);
|
||||
const result2 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance");
|
||||
|
||||
const result3 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2), options);
|
||||
const result3 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance");
|
||||
|
||||
const result4 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2), options);
|
||||
const result4 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance");
|
||||
|
||||
const result5 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, -2), options);
|
||||
const result5 = duration.add(new Temporal.Duration(0, 0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance");
|
||||
|
||||
// This one is different because hours are later balanced again in BalanceDuration
|
||||
const result6 = duration.add(new Temporal.Duration(0, 0, 0, 0, -2), options);
|
||||
const result6 = duration.add(new Temporal.Duration(0, 0, 0, 0, -2));
|
||||
TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance");
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the
|
||||
options value
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarDateAddUndefinedOptions();
|
||||
const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9);
|
||||
const instance = new Temporal.Duration(1, 1, 1, 1);
|
||||
instance.add(instance, { relativeTo: new Temporal.ZonedDateTime(0n, timeZone, calendar) });
|
||||
assert.sameValue(calendar.dateAddCallCount, 2);
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
relativeTo parameters that are not ZonedDateTime or undefined, are always
|
||||
converted to PlainDate for observable calendar calls
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarDateAddPlainDateInstance();
|
||||
const instance = new Temporal.Duration(1, 1, 1, 1);
|
||||
const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar);
|
||||
calendar.specificPlainDate = relativeTo;
|
||||
instance.add(instance, { relativeTo });
|
||||
assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested");
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Duration.prototype.add should call dateAdd with the appropriate values.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
let calls = 0;
|
||||
const expected = [
|
||||
{
|
||||
plainDate: [1920, 5, "M05", 3],
|
||||
duration: [2, 0, 0, 4, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
{
|
||||
plainDate: [1922, 5, "M05", 7],
|
||||
duration: [0, 10, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
];
|
||||
class CustomCalendar extends Temporal.Calendar {
|
||||
constructor() {
|
||||
super("iso8601");
|
||||
}
|
||||
dateAdd(plainDate, duration, options) {
|
||||
TemporalHelpers.assertPlainDate(plainDate, ...expected[calls].plainDate,
|
||||
`plainDate argument ${calls}`);
|
||||
TemporalHelpers.assertDuration(duration, ...expected[calls].duration,
|
||||
`duration argument ${calls}`);
|
||||
assert.sameValue(options, undefined, "options argument");
|
||||
++calls;
|
||||
return super.dateAdd(plainDate, duration, options);
|
||||
}
|
||||
}
|
||||
const relativeTo = new Temporal.PlainDate(1920, 5, 3, new CustomCalendar());
|
||||
const duration = new Temporal.Duration(2, 0, 0, 4, 2);
|
||||
const result = duration.add({ months: 10, hours: 14 }, { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 2, 10, 0, 4, 16, 0, 0, 0, 0, 0, "result");
|
||||
assert.sameValue(calls, 2, "should have called dateAdd");
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form
|
||||
info: |
|
||||
sec-temporal.duration.prototype.add step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _other_.[[Years]], _other_.[[Months]], _other_.[[Weeks]], _other_.[[Days]], _other_.[[Hours]], _other_.[[Minutes]], _other_.[[Seconds]], _other_.[[Milliseconds]], _other_.[[Microseconds]], _other_.[[Nanoseconds]], _relativeTo_).
|
||||
sec-temporal-addduration steps 6-7:
|
||||
6. If _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then
|
||||
...
|
||||
j. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_).
|
||||
k. Let _differenceOptions_ be ! OrdinaryObjectCreate(*null*).
|
||||
l. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_).
|
||||
m. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _datePart_, _end_, _differenceOptions_).
|
||||
...
|
||||
7. Else,
|
||||
a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot.
|
||||
...
|
||||
f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then
|
||||
...
|
||||
g. Else,
|
||||
i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_).
|
||||
sec-temporal-differencezoneddatetime steps 7 and 11:
|
||||
7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_).
|
||||
11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_).
|
||||
sec-temporal-nanosecondstodays step 11:
|
||||
11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*).
|
||||
sec-temporal-differenceisodatetime steps 9–11:
|
||||
9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_).
|
||||
10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_).
|
||||
11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_).
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
|
||||
(calendar, largestUnit, index) => {
|
||||
const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]);
|
||||
const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
|
||||
one.add(two, { relativeTo, largestUnit });
|
||||
},
|
||||
{
|
||||
years: ["year"],
|
||||
months: ["month"],
|
||||
weeks: ["week"],
|
||||
days: [],
|
||||
hours: [],
|
||||
minutes: [],
|
||||
seconds: [],
|
||||
milliseconds: [],
|
||||
microseconds: [],
|
||||
nanoseconds: []
|
||||
}
|
||||
);
|
||||
|
||||
TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
|
||||
(calendar, largestUnit, index) => {
|
||||
const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]);
|
||||
const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar);
|
||||
one.add(two, { relativeTo, largestUnit });
|
||||
},
|
||||
{
|
||||
years: ["year"],
|
||||
months: ["month"],
|
||||
weeks: ["week"],
|
||||
days: [],
|
||||
hours: [],
|
||||
minutes: [],
|
||||
seconds: [],
|
||||
milliseconds: [],
|
||||
microseconds: [],
|
||||
nanoseconds: []
|
||||
}
|
||||
);
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Verify the result of calendar.fields() is treated correctly.
|
||||
info: |
|
||||
sec-temporal.duration.prototype.add step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.c:
|
||||
c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
|
||||
sec-temporal-calendarfields step 4:
|
||||
4. Let _result_ be ? IterableToList(_fieldsArray_).
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const expected = [
|
||||
"day",
|
||||
"month",
|
||||
"monthCode",
|
||||
"year",
|
||||
];
|
||||
|
||||
const calendar = TemporalHelpers.calendarFieldsIterable();
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } });
|
||||
|
||||
assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once");
|
||||
assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args");
|
||||
assert(calendar.iteratorExhausted[0], "iterated through the whole iterable");
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
|
||||
info: |
|
||||
sec-temporal.duration.prototype.add step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.b:
|
||||
b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
|
||||
sec-temporal-gettemporalcalendarwithisodefault step 2:
|
||||
2. Return ? ToTemporalCalendarWithISODefault(_calendar_).
|
||||
sec-temporal-totemporalcalendarwithisodefault step 2b
|
||||
3. Return ? ToTemporalCalendar(_temporalCalendarLike_).
|
||||
sec-temporal-totemporalcalendar step 1.a:
|
||||
a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
|
||||
i. Return _temporalCalendarLike_.[[Calendar]].
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => {
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } });
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
// 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.add
|
||||
description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }));
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright (C) 2024 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Throws a RangeError when custom calendar method returns inconsistent result
|
||||
info: |
|
||||
DifferenceZonedDateTime ( ... )
|
||||
8. Repeat 3 times:
|
||||
...
|
||||
g. If _sign_ = 0, or _timeSign_ = 0, or _sign_ = _timeSign_, then
|
||||
...
|
||||
viii. Return ? CreateNormalizedDurationRecord(_dateDifference_.[[Years]],
|
||||
_dateDifference_.[[Months]], _dateDifference_.[[Weeks]],
|
||||
_dateDifference_.[[Days]], _norm_).
|
||||
h. Set _dayCorrection_ to _dayCorrection_ + 1.
|
||||
9. NOTE: This step is only reached when custom calendar or time zone methods
|
||||
return inconsistent values.
|
||||
10. Throw a *RangeError* exception.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
// Based partly on a test case by André Bargull
|
||||
|
||||
const duration1 = new Temporal.Duration(0, 0, /* weeks = */ 7, 0, /* hours = */ 12);
|
||||
const duration2 = new Temporal.Duration(0, 0, 0, /* days = */ 1);
|
||||
|
||||
{
|
||||
const tz = new (class extends Temporal.TimeZone {
|
||||
getPossibleInstantsFor(dateTime) {
|
||||
return super.getPossibleInstantsFor(dateTime.add({ days: 3 }));
|
||||
}
|
||||
})("UTC");
|
||||
|
||||
const relativeTo = new Temporal.ZonedDateTime(0n, tz);
|
||||
|
||||
assert.throws(RangeError, () => duration1.add(duration2, { relativeTo }),
|
||||
"Calendar calculation where more than 2 days correction is needed should cause RangeError");
|
||||
}
|
||||
|
||||
{
|
||||
const cal = new (class extends Temporal.Calendar {
|
||||
dateUntil(one, two, options) {
|
||||
return super.dateUntil(one, two, options).negated();
|
||||
}
|
||||
})("iso8601");
|
||||
|
||||
const relativeTo = new Temporal.ZonedDateTime(0n, "UTC", cal);
|
||||
|
||||
assert.throws(RangeError, () => duration1.add(duration2, { relativeTo }),
|
||||
"Calendar calculation causing mixed-sign values should cause RangeError");
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// 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.add
|
||||
description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
for (const extra_fields of [['foo', 'foo'], ['day'], ['month'], ['monthCode'], ['year']]) {
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }));
|
||||
}
|
|
@ -10,10 +10,9 @@ features: [Temporal]
|
|||
const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds'];
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
|
||||
fields.forEach((field) => {
|
||||
assert.throws(RangeError, () => instance.add({ [field]: Infinity }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.add({ [field]: Infinity }));
|
||||
});
|
||||
|
||||
let calls = 0;
|
||||
|
@ -26,6 +25,6 @@ const obj = {
|
|||
|
||||
fields.forEach((field) => {
|
||||
calls = 0;
|
||||
assert.throws(RangeError, () => instance.add({ [field]: obj }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.add({ [field]: obj }));
|
||||
assert.sameValue(calls, 1, "it fails after fetching the primitive value");
|
||||
});
|
||||
|
|
|
@ -1,18 +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.duration.prototype.add
|
||||
description: >
|
||||
AddZonedDateTime throws a RangeError when the intermediate instant is too large.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
|
||||
|
||||
var duration = Temporal.Duration.from({days: 1, seconds: Number.MAX_SAFE_INTEGER - 86400});
|
||||
|
||||
var options = {relativeTo: zonedDateTime};
|
||||
|
||||
assert.throws(RangeError, () => duration.add(duration, options));
|
|
@ -9,9 +9,6 @@ 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});
|
||||
|
@ -29,29 +26,3 @@ TemporalHelpers.assertDuration(
|
|||
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})"
|
||||
);
|
||||
|
|
|
@ -10,10 +10,9 @@ features: [Temporal]
|
|||
const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds'];
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
|
||||
fields.forEach((field) => {
|
||||
assert.throws(RangeError, () => instance.add({ [field]: -Infinity }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.add({ [field]: -Infinity }));
|
||||
});
|
||||
|
||||
let calls = 0;
|
||||
|
@ -26,6 +25,6 @@ const obj = {
|
|||
|
||||
fields.forEach((field) => {
|
||||
calls = 0;
|
||||
assert.throws(RangeError, () => instance.add({ [field]: obj }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.add({ [field]: obj }));
|
||||
assert.sameValue(calls, 1, "it fails after fetching the primitive value");
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Empty or a function object may be used as options
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(0, 0, 0, 0, 1);
|
||||
|
||||
const result1 = instance.add({ hours: 1 }, {});
|
||||
TemporalHelpers.assertDuration(
|
||||
result1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
|
||||
"options may be an empty plain object"
|
||||
);
|
||||
|
||||
const result2 = instance.add({ hours: 1 }, () => {});
|
||||
TemporalHelpers.assertDuration(
|
||||
result2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
|
||||
"options may be a function object"
|
||||
);
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Verify that undefined options are handled correctly.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
const duration3 = new Temporal.Duration(0, 0, 0, 1);
|
||||
const duration4 = new Temporal.Duration(0, 0, 0, 0, 24);
|
||||
|
||||
assert.throws(RangeError, () => duration1.add(duration2), "no options with years");
|
||||
TemporalHelpers.assertDuration(duration3.add(duration4),
|
||||
0, 0, 0, /* days = */ 2, 0, 0, 0, 0, 0, 0,
|
||||
"no options with days");
|
||||
|
||||
const optionValues = [
|
||||
[undefined, "undefined"],
|
||||
[{}, "plain object"],
|
||||
[() => {}, "lambda"],
|
||||
];
|
||||
for (const [options, description] of optionValues) {
|
||||
assert.throws(RangeError, () => duration1.add(duration2, options),
|
||||
`options ${description} with years`);
|
||||
TemporalHelpers.assertDuration(duration3.add(duration4, options),
|
||||
0, 0, 0, /* days = */ 2, 0, 0, 0, 0, 0, 0,
|
||||
`options ${description} with days`);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: TypeError thrown when options argument is a primitive
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const badOptions = [
|
||||
null,
|
||||
true,
|
||||
"some string",
|
||||
Symbol(),
|
||||
1,
|
||||
2n,
|
||||
];
|
||||
|
||||
const instance = new Temporal.Duration(0, 0, 0, 0, 1);
|
||||
for (const value of badOptions) {
|
||||
assert.throws(TypeError, () => instance.add({ hours: 1 }, value),
|
||||
`TypeError on wrong options type ${typeof value}`);
|
||||
};
|
|
@ -40,8 +40,6 @@ const expected = [
|
|||
"get fields.years",
|
||||
"get fields.years.valueOf",
|
||||
"call fields.years.valueOf",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
];
|
||||
const actual = [];
|
||||
|
||||
|
@ -58,423 +56,8 @@ const simpleFields = TemporalHelpers.propertyBagObserver(actual, {
|
|||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
function createOptionsObserver(relativeTo = undefined) {
|
||||
return TemporalHelpers.propertyBagObserver(actual, { relativeTo }, "options");
|
||||
}
|
||||
|
||||
// basic order of observable operations, without any calendar units:
|
||||
const simpleInstance = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1);
|
||||
simpleInstance.add(simpleFields, createOptionsObserver());
|
||||
simpleInstance.add(simpleFields);
|
||||
assert.compareArray(actual, expected, "order of operations");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForPlainRelativeTo = expected.concat([
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
// AddDuration
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.calendar.dateUntil",
|
||||
]);
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 0, 4, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const fields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
years: 1,
|
||||
months: 1,
|
||||
weeks: 1,
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
const plainRelativeTo = TemporalHelpers.propertyBagObserver(actual, {
|
||||
year: 2000,
|
||||
month: 1,
|
||||
monthCode: "M01",
|
||||
day: 1,
|
||||
calendar: TemporalHelpers.calendarObserver(actual, "options.relativeTo.calendar"),
|
||||
}, "options.relativeTo");
|
||||
|
||||
instance.add(fields, createOptionsObserver(plainRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForPlainRelativeTo, "order of operations with PlainDate relativeTo");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForPlainRelativeToNoCalendarOperations = [
|
||||
// ToTemporalDurationRecord
|
||||
"get fields.days",
|
||||
"get fields.days.valueOf",
|
||||
"call fields.days.valueOf",
|
||||
"get fields.hours",
|
||||
"get fields.hours.valueOf",
|
||||
"call fields.hours.valueOf",
|
||||
"get fields.microseconds",
|
||||
"get fields.microseconds.valueOf",
|
||||
"call fields.microseconds.valueOf",
|
||||
"get fields.milliseconds",
|
||||
"get fields.milliseconds.valueOf",
|
||||
"call fields.milliseconds.valueOf",
|
||||
"get fields.minutes",
|
||||
"get fields.minutes.valueOf",
|
||||
"call fields.minutes.valueOf",
|
||||
"get fields.months",
|
||||
"get fields.nanoseconds",
|
||||
"get fields.nanoseconds.valueOf",
|
||||
"call fields.nanoseconds.valueOf",
|
||||
"get fields.seconds",
|
||||
"get fields.seconds.valueOf",
|
||||
"call fields.seconds.valueOf",
|
||||
"get fields.weeks",
|
||||
"get fields.years",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
];
|
||||
|
||||
const noCalendarInstance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const noCalendarFields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
noCalendarInstance.add(noCalendarFields, createOptionsObserver(plainRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForPlainRelativeToNoCalendarOperations, "order of operations with PlainDate relativeTo and no calendar units");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForZonedRelativeTo = expected.concat([
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.hour.valueOf",
|
||||
"call options.relativeTo.hour.valueOf",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.microsecond.valueOf",
|
||||
"call options.relativeTo.microsecond.valueOf",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.millisecond.valueOf",
|
||||
"call options.relativeTo.millisecond.valueOf",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.minute.valueOf",
|
||||
"call options.relativeTo.minute.valueOf",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.nanosecond.valueOf",
|
||||
"call options.relativeTo.nanosecond.valueOf",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.offset.toString",
|
||||
"call options.relativeTo.offset.toString",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.second.valueOf",
|
||||
"call options.relativeTo.second.valueOf",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// ToRelativeTemporalObject again
|
||||
"has options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"has options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"has options.relativeTo.timeZone.id",
|
||||
// InterpretISODateTimeOffset
|
||||
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"get options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
// AddDuration
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// AddDuration → AddZonedDateTime 1
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
// AddDuration → AddZonedDateTime 2
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
// AddDuration → DifferenceZonedDateTime
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.calendar.dateUntil",
|
||||
]);
|
||||
|
||||
const zonedRelativeTo = TemporalHelpers.propertyBagObserver(actual, {
|
||||
year: 2000,
|
||||
month: 1,
|
||||
monthCode: "M01",
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0,
|
||||
microsecond: 0,
|
||||
nanosecond: 0,
|
||||
offset: "+00:00",
|
||||
calendar: TemporalHelpers.calendarObserver(actual, "options.relativeTo.calendar"),
|
||||
timeZone: TemporalHelpers.timeZoneObserver(actual, "options.relativeTo.timeZone"),
|
||||
}, "options.relativeTo");
|
||||
|
||||
instance.add(fields, createOptionsObserver(zonedRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForZonedRelativeTo, "order of operations with ZonedDateTime relativeTo");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForZonedRelativeToNoDaysOperations = [
|
||||
// ToTemporalDurationRecord
|
||||
"get fields.days",
|
||||
"get fields.hours",
|
||||
"get fields.hours.valueOf",
|
||||
"call fields.hours.valueOf",
|
||||
"get fields.microseconds",
|
||||
"get fields.microseconds.valueOf",
|
||||
"call fields.microseconds.valueOf",
|
||||
"get fields.milliseconds",
|
||||
"get fields.milliseconds.valueOf",
|
||||
"call fields.milliseconds.valueOf",
|
||||
"get fields.minutes",
|
||||
"get fields.minutes.valueOf",
|
||||
"call fields.minutes.valueOf",
|
||||
"get fields.months",
|
||||
"get fields.nanoseconds",
|
||||
"get fields.nanoseconds.valueOf",
|
||||
"call fields.nanoseconds.valueOf",
|
||||
"get fields.seconds",
|
||||
"get fields.seconds.valueOf",
|
||||
"call fields.seconds.valueOf",
|
||||
"get fields.weeks",
|
||||
"get fields.years",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.hour.valueOf",
|
||||
"call options.relativeTo.hour.valueOf",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.microsecond.valueOf",
|
||||
"call options.relativeTo.microsecond.valueOf",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.millisecond.valueOf",
|
||||
"call options.relativeTo.millisecond.valueOf",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.minute.valueOf",
|
||||
"call options.relativeTo.minute.valueOf",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.nanosecond.valueOf",
|
||||
"call options.relativeTo.nanosecond.valueOf",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.offset.toString",
|
||||
"call options.relativeTo.offset.toString",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.second.valueOf",
|
||||
"call options.relativeTo.second.valueOf",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// ToRelativeTemporalObject again
|
||||
"has options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"has options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"has options.relativeTo.timeZone.id",
|
||||
// InterpretISODateTimeOffset
|
||||
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"get options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
];
|
||||
|
||||
const noDaysInstance = new Temporal.Duration(0, 0, 0, 0, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const noDaysFields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
noDaysInstance.add(noDaysFields, createOptionsObserver(zonedRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForZonedRelativeToNoDaysOperations, "order of operations with ZonedDateTime relativeTo and no units above days");
|
||||
actual.splice(0); // clear
|
||||
|
|
|
@ -9,9 +9,6 @@ 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({seconds: 4503599627370495, nanoseconds: 499_999_999});
|
||||
const duration2 = Temporal.Duration.from({seconds: 4503599627370495 - 86400, nanoseconds: 499_999_999, days: 1});
|
||||
|
@ -29,21 +26,3 @@ TemporalHelpers.assertDuration(
|
|||
Number(nanos % 1000n),
|
||||
"duration1.add(duration2)"
|
||||
);
|
||||
|
||||
TemporalHelpers.assertDuration(
|
||||
duration1.add(duration2, {relativeTo: plainDate}),
|
||||
0, 0, 0,
|
||||
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});
|
||||
});
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// 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.add
|
||||
description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }));
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: The time fields are read from the object before being passed to dateFromFields().
|
||||
info: |
|
||||
sec-temporal.duration.prototype.add step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.g:
|
||||
g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
|
||||
sec-temporal-interprettemporaldatetimefields steps 1–2:
|
||||
1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_).
|
||||
2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarMakeInvalidGettersTime();
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } });
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: Throws if any value in the property bag is Infinity or -Infinity
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 };
|
||||
|
||||
[Infinity, -Infinity].forEach((inf) => {
|
||||
["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => {
|
||||
assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`);
|
||||
|
||||
const calls = [];
|
||||
const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
|
||||
assert.throws(RangeError, () => instance.add(instance, { relativeTo: { ...base, [prop]: obj } }));
|
||||
assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value");
|
||||
});
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Leap second is constrained in both an ISO string and a property bag
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = "2016-12-31T23:59:60";
|
||||
const result1 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result1,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"leap second is a valid ISO string for PlainDate relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = "2016-12-31T23:59:60+00:00[UTC]";
|
||||
const result2 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result2,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"leap second is a valid ISO string for ZonedDateTime relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
|
||||
const result3 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result3,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"second: 60 is valid in a property bag for PlainDate relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60, timeZone: "UTC" };
|
||||
const result4 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result4,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"second: 60 is valid in a property bag for ZonedDateTime relativeTo"
|
||||
);
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo with months.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const oneMonth = new Temporal.Duration(0, 1);
|
||||
const days30 = new Temporal.Duration(0, 0, 0, 30);
|
||||
TemporalHelpers.assertDuration(oneMonth.add(days30, { relativeTo: Temporal.PlainDate.from('2018-01-01') }),
|
||||
0, 2, 0, 2, 0, 0, 0, 0, 0, 0, "January");
|
||||
TemporalHelpers.assertDuration(oneMonth.add(days30, { relativeTo: Temporal.PlainDate.from('2018-02-01') }),
|
||||
0, 1, 0, 30, 0, 0, 0, 0, 0, 0, "February");
|
||||
TemporalHelpers.assertDuration(oneMonth.add(days30, { relativeTo: Temporal.PlainDate.from('2018-03-01') }),
|
||||
0, 2, 0, 0, 0, 0, 0, 0, 0, 0, "March");
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: A number cannot be used in place of a relativeTo
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const numbers = [
|
||||
1,
|
||||
-20191101,
|
||||
20191101,
|
||||
1234567890,
|
||||
];
|
||||
|
||||
for (const relativeTo of numbers) {
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
`A number (${relativeTo}) is not a valid ISO string for relativeTo`
|
||||
);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo with years.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const d1 = new Temporal.Duration(0, 1, 0, 0);
|
||||
const d2 = new Temporal.Duration(0, 0, 0, 30);
|
||||
const relativeTo = new Temporal.PlainDate(2000, 1, 1);
|
||||
TemporalHelpers.assertDuration(d1.add(d2, { relativeTo }),
|
||||
0, 2, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
"first this is resolved against relativeTo, then the argument against relativeTo + this");
|
|
@ -1,89 +0,0 @@
|
|||
// 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.add
|
||||
description: >
|
||||
Correct time zone calls are made when converting a ZonedDateTime-like
|
||||
relativeTo property bag denoting an ambiguous wall-clock time
|
||||
includes: [temporalHelpers.js, compareArray.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const actual = [];
|
||||
|
||||
const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone();
|
||||
const dstTimeZoneObserver = TemporalHelpers.timeZoneObserver(actual, "timeZone", {
|
||||
getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor.bind(dstTimeZone),
|
||||
getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor.bind(dstTimeZone),
|
||||
});
|
||||
const calendar = TemporalHelpers.calendarObserver(actual, "calendar");
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = { year: 2000, month: 4, day: 2, hour: 2, minute: 30, timeZone: dstTimeZoneObserver, calendar };
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
const expected = [
|
||||
// GetTemporalCalendarSlotValueWithISODefault
|
||||
"has calendar.dateAdd",
|
||||
"has calendar.dateFromFields",
|
||||
"has calendar.dateUntil",
|
||||
"has calendar.day",
|
||||
"has calendar.dayOfWeek",
|
||||
"has calendar.dayOfYear",
|
||||
"has calendar.daysInMonth",
|
||||
"has calendar.daysInWeek",
|
||||
"has calendar.daysInYear",
|
||||
"has calendar.fields",
|
||||
"has calendar.id",
|
||||
"has calendar.inLeapYear",
|
||||
"has calendar.mergeFields",
|
||||
"has calendar.month",
|
||||
"has calendar.monthCode",
|
||||
"has calendar.monthDayFromFields",
|
||||
"has calendar.monthsInYear",
|
||||
"has calendar.weekOfYear",
|
||||
"has calendar.year",
|
||||
"has calendar.yearMonthFromFields",
|
||||
"has calendar.yearOfWeek",
|
||||
// lookup
|
||||
"get calendar.dateFromFields",
|
||||
"get calendar.fields",
|
||||
// CalendarFields
|
||||
"call calendar.fields",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call calendar.dateFromFields",
|
||||
// ToTemporalTimeZoneSlotValue
|
||||
"has timeZone.getOffsetNanosecondsFor",
|
||||
"has timeZone.getPossibleInstantsFor",
|
||||
"has timeZone.id",
|
||||
// lookup
|
||||
"get timeZone.getOffsetNanosecondsFor",
|
||||
"get timeZone.getPossibleInstantsFor",
|
||||
// InterpretISODateTimeOffset
|
||||
"call timeZone.getPossibleInstantsFor",
|
||||
];
|
||||
|
||||
const expectedSpringForward = expected.concat([
|
||||
// DisambiguatePossibleInstants
|
||||
"call timeZone.getOffsetNanosecondsFor",
|
||||
"call timeZone.getOffsetNanosecondsFor",
|
||||
"call timeZone.getPossibleInstantsFor",
|
||||
]);
|
||||
assert.compareArray(
|
||||
actual.slice(0, expectedSpringForward.length), // ignore operations after ToRelativeTemporalObject
|
||||
expectedSpringForward,
|
||||
"order of operations converting property bag at skipped wall-clock time"
|
||||
);
|
||||
actual.splice(0); // clear
|
||||
|
||||
relativeTo = { year: 2000, month: 10, day: 29, hour: 1, minute: 30, timeZone: dstTimeZoneObserver, calendar };
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
assert.compareArray(
|
||||
actual.slice(0, expected.length), // ignore operations after ToRelativeTemporalObject
|
||||
expected,
|
||||
"order of operations converting property bag at repeated wall-clock time"
|
||||
);
|
||||
actual.splice(0); // clear
|
|
@ -1,22 +0,0 @@
|
|||
// 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.add
|
||||
description: >
|
||||
Calling the method with a relativeTo property bag with a builtin calendar
|
||||
causes no observable array iteration when getting the calendar fields.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator];
|
||||
Array.prototype[Symbol.iterator] = function arrayIterator() {
|
||||
throw new Test262Error("Array should not be iterated");
|
||||
}
|
||||
|
||||
const timeZone = "UTC";
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, hour: 21, minute: 43, second: 5, timeZone, calendar: "iso8601" };
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Calendar.dateFromFields method is called with a null-prototype fields object
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, calendar };
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar");
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: A number as calendar in relativeTo property bag is invalid
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const numbers = [
|
||||
1,
|
||||
19970327,
|
||||
-19970327,
|
||||
1234567890,
|
||||
];
|
||||
|
||||
for (const calendar of numbers) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
`A number (${calendar}) is not a valid ISO string for relativeTo.calendar`
|
||||
);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// 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.add
|
||||
description: >
|
||||
Builtin dateFromFields method is not observably called when the property bag
|
||||
has a string-valued calendar property
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const dateFromFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "dateFromFields");
|
||||
Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
get() {
|
||||
TemporalHelpers.assertUnreachable("dateFromFields should not be looked up");
|
||||
},
|
||||
});
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, calendar: "iso8601" };
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", dateFromFieldsOriginal);
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Appropriate error thrown when relativeTo.calendar cannot be converted to a
|
||||
calendar object or string
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const primitiveTests = [
|
||||
[null, "null"],
|
||||
[true, "boolean"],
|
||||
["", "empty string"],
|
||||
[1, "number that doesn't convert to a valid ISO string"],
|
||||
[1n, "bigint"],
|
||||
];
|
||||
|
||||
for (const [calendar, description] of primitiveTests) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(
|
||||
typeof calendar === 'string' ? RangeError : TypeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
`${description} does not convert to a valid ISO string`
|
||||
);
|
||||
}
|
||||
|
||||
const typeErrorTests = [
|
||||
[Symbol(), "symbol"],
|
||||
[{}, "plain object that doesn't implement the protocol"],
|
||||
[new Temporal.TimeZone("UTC"), "time zone instance"],
|
||||
[Temporal.PlainDate, "Temporal.PlainDate, object"],
|
||||
[Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"],
|
||||
[Temporal.ZonedDateTime, "Temporal.ZonedDateTime, object"],
|
||||
[Temporal.ZonedDateTime.prototype, "Temporal.ZonedDateTime.prototype, object"],
|
||||
];
|
||||
|
||||
for (const [calendar, description] of typeErrorTests) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(TypeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), `${description} is not a valid property bag and does not convert to a string`);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
// 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.add
|
||||
description: >
|
||||
Time zone's getPossibleInstantsFor is called with a PlainDateTime with the
|
||||
built-in ISO 8601 calendar
|
||||
features: [Temporal]
|
||||
info: |
|
||||
DisambiguatePossibleInstants:
|
||||
2. Let _n_ be _possibleInstants_'s length.
|
||||
...
|
||||
5. Assert: _n_ = 0.
|
||||
...
|
||||
19. If _disambiguation_ is *"earlier"*, then
|
||||
...
|
||||
c. Let _earlierDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
|
||||
d. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _earlierDateTime_).
|
||||
...
|
||||
20. Assert: _disambiguation_ is *"compatible"* or *"later"*.
|
||||
...
|
||||
23. Let _laterDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
|
||||
24. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _laterDateTime_).
|
||||
---*/
|
||||
|
||||
class SkippedDateTime extends Temporal.TimeZone {
|
||||
constructor() {
|
||||
super("UTC");
|
||||
this.calls = 0;
|
||||
}
|
||||
|
||||
getPossibleInstantsFor(dateTime) {
|
||||
// Calls occur in pairs. For the first one return no possible instants so
|
||||
// that DisambiguatePossibleInstants will call it again
|
||||
if (this.calls++ % 2 == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
assert.sameValue(
|
||||
dateTime.getISOFields().calendar,
|
||||
"iso8601",
|
||||
"getPossibleInstantsFor called with dateTime with built-in ISO 8601 calendar"
|
||||
);
|
||||
return super.getPossibleInstantsFor(dateTime);
|
||||
}
|
||||
}
|
||||
|
||||
const nonBuiltinISOCalendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = new SkippedDateTime();
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, timeZone, calendar: nonBuiltinISOCalendar };
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
assert.sameValue(timeZone.calls, 6, "getPossibleInstantsFor should have been called 6 times");
|
|
@ -1,29 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo property bag with offset property is rejected if offset is in the wrong format
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const badOffsets = [
|
||||
"00:00", // missing sign
|
||||
"+0", // too short
|
||||
"-000:00", // too long
|
||||
0, // must be a string
|
||||
null, // must be a string
|
||||
true, // must be a string
|
||||
1000n, // must be a string
|
||||
];
|
||||
badOffsets.forEach((offset) => {
|
||||
const relativeTo = { year: 2021, month: 10, day: 28, offset, timeZone };
|
||||
assert.throws(
|
||||
typeof(offset) === 'string' ? RangeError : TypeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
`"${offset} is not a valid offset string`
|
||||
);
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Missing time units in relativeTo property bag default to 0
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = { year: 2000, month: 1, day: 1 };
|
||||
const result = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "missing time units default to 0");
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (C) 2024 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
UTC offset shift returned by getPossibleInstantsFor can be at most 24 hours.
|
||||
features: [Temporal]
|
||||
info: |
|
||||
GetPossibleInstantsFor:
|
||||
5.b.i. Let _numResults_ be _list_'s length.
|
||||
ii. If _numResults_ > 1, then
|
||||
1. Let _epochNs_ be a new empty List.
|
||||
2. For each value _instant_ in list, do
|
||||
a. Append _instant_.[[EpochNanoseconds]] to the end of the List _epochNs_.
|
||||
3. Let _min_ be the least element of the List _epochNs_.
|
||||
4. Let _max_ be the greatest element of the List _epochNs_.
|
||||
5. If abs(ℝ(_max_ - _min_)) > nsPerDay, throw a *RangeError* exception.
|
||||
---*/
|
||||
|
||||
class ShiftLonger24Hour extends Temporal.TimeZone {
|
||||
id = 'TestTimeZone';
|
||||
|
||||
constructor() {
|
||||
super('UTC');
|
||||
}
|
||||
|
||||
getOffsetNanosecondsFor(instant) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
getPossibleInstantsFor(plainDateTime) {
|
||||
const utc = new Temporal.TimeZone("UTC");
|
||||
const [utcInstant] = utc.getPossibleInstantsFor(plainDateTime);
|
||||
return [
|
||||
utcInstant.subtract({ hours: 12, nanoseconds: 1 }),
|
||||
utcInstant.add({ hours: 12 }),
|
||||
utcInstant, // add a third value in case the implementation doesn't sort
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const timeZone = new ShiftLonger24Hour();
|
||||
const relativeTo = { year: 1970, month: 1, day: 1, hour: 12, timeZone };
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "RangeError should be thrown");
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright (C) 2024 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
UTC offset shift returned by adjacent invocations of getOffsetNanosecondsFor
|
||||
in DisambiguatePossibleInstants cannot be greater than 24 hours.
|
||||
features: [Temporal]
|
||||
info: |
|
||||
DisambiguatePossibleInstants:
|
||||
18. If abs(_nanoseconds_) > nsPerDay, throw a *RangeError* exception.
|
||||
---*/
|
||||
|
||||
class ShiftLonger24Hour extends Temporal.TimeZone {
|
||||
id = 'TestTimeZone';
|
||||
_shiftEpochNs = 12n * 3600n * 1_000_000_000n; // 1970-01-01T12:00Z
|
||||
|
||||
constructor() {
|
||||
super('UTC');
|
||||
}
|
||||
|
||||
getOffsetNanosecondsFor(instant) {
|
||||
if (instant.epochNanoseconds < this._shiftEpochNs) return -12 * 3600e9;
|
||||
return 12 * 3600e9 + 1;
|
||||
}
|
||||
|
||||
getPossibleInstantsFor(plainDateTime) {
|
||||
const [utcInstant] = super.getPossibleInstantsFor(plainDateTime);
|
||||
const { year, month, day } = plainDateTime;
|
||||
|
||||
if (year < 1970) return [utcInstant.subtract({ hours: 12 })];
|
||||
if (year === 1970 && month === 1 && day === 1) return [];
|
||||
return [utcInstant.add({ hours: 12, nanoseconds: 1 })];
|
||||
}
|
||||
}
|
||||
|
||||
const timeZone = new ShiftLonger24Hour();
|
||||
const relativeTo = { year: 1970, month: 1, day: 1, hour: 12, timeZone };
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "RangeError should be thrown");
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
assert.throws(RangeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }));
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable
|
||||
features: [BigInt, Symbol, Temporal, arrow-function]
|
||||
---*/
|
||||
|
||||
[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
timeZone.getOffsetNanosecondsFor = notCallable;
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }),
|
||||
`Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
|
||||
);
|
||||
});
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: RangeError thrown if time zone reports an offset that is out of range
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
assert.throws(RangeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }));
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: TypeError thrown if time zone reports an offset that is not a Number
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"+01:00",
|
||||
Symbol(),
|
||||
3600_000_000_000n,
|
||||
{},
|
||||
{ valueOf() { return 3600_000_000_000; } },
|
||||
].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
assert.throws(TypeError, () => duration.add(other, { relativeTo: { year: 2000, month: 5, day: 2, hour: 12, timeZone } }));
|
||||
});
|
|
@ -1,63 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Conversion of ISO date-time strings to Temporal.TimeZone instances
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1);
|
||||
|
||||
let timeZone = "2021-08-19T17:30";
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "bare date-time string is not a time zone");
|
||||
|
||||
[
|
||||
"2021-08-19T17:30-07:00:01",
|
||||
"2021-08-19T17:30-07:00:00",
|
||||
"2021-08-19T17:30-07:00:00.1",
|
||||
"2021-08-19T17:30-07:00:00.0",
|
||||
"2021-08-19T17:30-07:00:00.01",
|
||||
"2021-08-19T17:30-07:00:00.00",
|
||||
"2021-08-19T17:30-07:00:00.001",
|
||||
"2021-08-19T17:30-07:00:00.000",
|
||||
"2021-08-19T17:30-07:00:00.0001",
|
||||
"2021-08-19T17:30-07:00:00.0000",
|
||||
"2021-08-19T17:30-07:00:00.00001",
|
||||
"2021-08-19T17:30-07:00:00.00000",
|
||||
"2021-08-19T17:30-07:00:00.000001",
|
||||
"2021-08-19T17:30-07:00:00.000000",
|
||||
"2021-08-19T17:30-07:00:00.0000001",
|
||||
"2021-08-19T17:30-07:00:00.0000000",
|
||||
"2021-08-19T17:30-07:00:00.00000001",
|
||||
"2021-08-19T17:30-07:00:00.00000000",
|
||||
"2021-08-19T17:30-07:00:00.000000001",
|
||||
"2021-08-19T17:30-07:00:00.000000000",
|
||||
].forEach((timeZone) => {
|
||||
assert.throws(
|
||||
RangeError,
|
||||
() => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }),
|
||||
`ISO string ${timeZone} with a sub-minute offset is not a valid time zone`
|
||||
);
|
||||
});
|
||||
|
||||
// The following are all valid strings so should not throw:
|
||||
|
||||
[
|
||||
"2021-08-19T17:30Z",
|
||||
"2021-08-19T1730Z",
|
||||
"2021-08-19T17:30-07:00",
|
||||
"2021-08-19T1730-07:00",
|
||||
"2021-08-19T17:30-0700",
|
||||
"2021-08-19T1730-0700",
|
||||
"2021-08-19T17:30[UTC]",
|
||||
"2021-08-19T1730[UTC]",
|
||||
"2021-08-19T17:30Z[UTC]",
|
||||
"2021-08-19T1730Z[UTC]",
|
||||
"2021-08-19T17:30-07:00[UTC]",
|
||||
"2021-08-19T1730-07:00[UTC]",
|
||||
"2021-08-19T17:30-0700[UTC]",
|
||||
"2021-08-19T1730-0700[UTC]",
|
||||
].forEach((timeZone) => {
|
||||
instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } });
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Leap second is a valid ISO string for TimeZone
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1);
|
||||
let timeZone = "2016-12-31T23:59:60+00:00[UTC]";
|
||||
|
||||
// A string with a leap second is a valid ISO string, so the following
|
||||
// operation should not throw
|
||||
|
||||
instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } });
|
||||
|
||||
timeZone = "2021-08-19T17:30:45.123456789+23:59[+23:59:60]";
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), "leap second in time zone name not valid");
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Negative zero, as an extended year, is rejected
|
||||
features: [Temporal, arrow-function]
|
||||
---*/
|
||||
|
||||
const invalidStrings = [
|
||||
"-000000-10-31T17:45Z",
|
||||
"-000000-10-31T17:45+00:00[UTC]",
|
||||
];
|
||||
const instance = new Temporal.Duration(1);
|
||||
invalidStrings.forEach((timeZone) => {
|
||||
assert.throws(
|
||||
RangeError,
|
||||
() => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }),
|
||||
"reject minus zero as extended year"
|
||||
);
|
||||
});
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Time zone IDs are valid input for a time zone
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const getPossibleInstantsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getPossibleInstantsFor");
|
||||
Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
get() {
|
||||
TemporalHelpers.assertUnreachable("getPossibleInstantsFor should not be looked up");
|
||||
},
|
||||
});
|
||||
const getOffsetNanosecondsForOriginal = Object.getOwnPropertyDescriptor(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor");
|
||||
Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
get() {
|
||||
TemporalHelpers.assertUnreachable("getOffsetNanosecondsFor should not be looked up");
|
||||
},
|
||||
});
|
||||
|
||||
const instance = new Temporal.Duration(1);
|
||||
|
||||
// The following are all valid strings so should not throw:
|
||||
|
||||
["UTC", "+01:00"].forEach((timeZone) => {
|
||||
instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } });
|
||||
});
|
||||
|
||||
Object.defineProperty(Temporal.TimeZone.prototype, "getPossibleInstantsFor", getPossibleInstantsForOriginal);
|
||||
Object.defineProperty(Temporal.TimeZone.prototype, "getOffsetNanosecondsFor", getOffsetNanosecondsForOriginal);
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Appropriate error thrown when argument cannot be converted to a valid string
|
||||
or object for TimeZone
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1);
|
||||
|
||||
const primitiveTests = [
|
||||
[null, "null"],
|
||||
[true, "boolean"],
|
||||
["", "empty string"],
|
||||
[1, "number that doesn't convert to a valid ISO string"],
|
||||
[19761118, "number that would convert to a valid ISO string in other contexts"],
|
||||
[1n, "bigint"],
|
||||
];
|
||||
|
||||
for (const [timeZone, description] of primitiveTests) {
|
||||
assert.throws(
|
||||
typeof timeZone === 'string' ? RangeError : TypeError,
|
||||
() => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }),
|
||||
`${description} does not convert to a valid ISO string`
|
||||
);
|
||||
}
|
||||
|
||||
const typeErrorTests = [
|
||||
[Symbol(), "symbol"],
|
||||
[{}, "object not implementing time zone protocol"],
|
||||
[new Temporal.Calendar("iso8601"), "calendar instance"],
|
||||
];
|
||||
|
||||
for (const [timeZone, description] of typeErrorTests) {
|
||||
assert.throws(TypeError, () => instance.add(new Temporal.Duration(1), { relativeTo: { year: 2000, month: 5, day: 2, timeZone } }), `${description} is not a valid object and does not convert to a string`);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo is required if the largest unit is at least weeks.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const d = Temporal.Duration.from({ hours: 1 });
|
||||
const dy = Temporal.Duration.from({ years: 1 });
|
||||
const dm = Temporal.Duration.from({ months: 1 });
|
||||
const dw = Temporal.Duration.from({ weeks: 1 });
|
||||
assert.throws(RangeError, () => d.add(dy));
|
||||
assert.throws(RangeError, () => d.add(dm));
|
||||
assert.throws(RangeError, () => d.add(dw));
|
||||
assert.throws(RangeError, () => dy.add(d));
|
||||
assert.throws(RangeError, () => dm.add(d));
|
||||
assert.throws(RangeError, () => dw.add(d));
|
||||
const relativeTo = Temporal.PlainDate.from("2000-01-01");
|
||||
TemporalHelpers.assertDuration(d.add(dy, { relativeTo }),
|
||||
1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
|
||||
TemporalHelpers.assertDuration(d.add(dm, { relativeTo }),
|
||||
0, 1, 0, 0, 1, 0, 0, 0, 0, 0);
|
||||
TemporalHelpers.assertDuration(d.add(dw, { relativeTo }),
|
||||
0, 0, 1, 0, 1, 0, 0, 0, 0, 0);
|
||||
TemporalHelpers.assertDuration(dy.add(d, { relativeTo }),
|
||||
1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
|
||||
TemporalHelpers.assertDuration(dm.add(d, { relativeTo }),
|
||||
0, 1, 0, 0, 1, 0, 0, 0, 0, 0);
|
||||
TemporalHelpers.assertDuration(dw.add(d, { relativeTo }),
|
||||
0, 0, 1, 0, 1, 0, 0, 0, 0, 0);
|
|
@ -1,38 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Conversion of ISO date-time strings as relativeTo option to
|
||||
Temporal.ZonedDateTime or Temporal.PlainDateTime instances
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = "2019-11-01T00:00";
|
||||
const result1 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "bare date-time string is a plain relativeTo");
|
||||
|
||||
relativeTo = "2019-11-01T00:00-07:00";
|
||||
const result2 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset is a plain relativeTo");
|
||||
|
||||
relativeTo = "2019-11-01T00:00[-07:00]";
|
||||
const result3 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo");
|
||||
|
||||
relativeTo = "2019-11-01T00:00Z[-07:00]";
|
||||
const result4 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo");
|
||||
|
||||
relativeTo = "2019-11-01T00:00+00:00[UTC]";
|
||||
const result5 = instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo");
|
||||
|
||||
relativeTo = "2019-11-01T00:00Z";
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "date-time + Z throws without an IANA annotation");
|
||||
relativeTo = "2019-11-01T00:00+04:15[UTC]";
|
||||
assert.throws(RangeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch");
|
|
@ -1,13 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: RangeError thrown if relativeTo is a string with the wrong format
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
['bad string', '15:30:45.123456', 'iso8601', 'UTC', 'P1YT1H'].forEach((relativeTo) => {
|
||||
const duration = new Temporal.Duration(1, 0, 0, 15);
|
||||
assert.throws(RangeError, () => duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo }));
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: The relativeTo option accepts a PlainDateTime-like ISO 8601 string
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
['2000-01-01', '2000-01-01T00:00', '2000-01-01T00:00[u-ca=iso8601]'].forEach((relativeTo) => {
|
||||
const duration = new Temporal.Duration(1, 0, 0, 15);
|
||||
const result = duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
});
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Throws if a ZonedDateTime-like relativeTo string has the wrong UTC offset
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = "2000-01-01T00:00+05:30[UTC]";
|
||||
assert.throws(
|
||||
RangeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
"add should throw RangeError on a string with UTC offset mismatch"
|
||||
);
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: The relativeTo option accepts a ZonedDateTime-like ISO 8601 string
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[
|
||||
'2000-01-01[UTC]',
|
||||
'2000-01-01T00:00[UTC]',
|
||||
'2000-01-01T00:00+00:00[UTC]',
|
||||
'2000-01-01T00:00+00:00[UTC][u-ca=iso8601]',
|
||||
].forEach((relativeTo) => {
|
||||
const duration = new Temporal.Duration(1, 0, 0, 15);
|
||||
const result = duration.add(new Temporal.Duration(0, 0, 0, 16), { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
});
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo string accepts trailing zeroes in sub-minute UTC offset
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
let result;
|
||||
let relativeTo;
|
||||
const action = (relativeTo) => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo });
|
||||
|
||||
relativeTo = "1970-01-01T00:00-00:45:00[-00:45]";
|
||||
result = action(relativeTo);
|
||||
TemporalHelpers.assertDateDuration(result, 1, 0, 0, 0, "ISO string offset accepted with zero seconds (string)");
|
||||
|
||||
relativeTo = { year: 1970, month: 1, day: 1, offset: "+00:45:00.000000000", timeZone: "+00:45" };
|
||||
result = action(relativeTo);
|
||||
TemporalHelpers.assertDateDuration(result, 1, 0, 0, 0, "ISO string offset accepted with zero seconds (property bag)");
|
||||
|
||||
relativeTo = "1970-01-01T00:00+00:44:30.123456789[+00:45]";
|
||||
assert.throws(RangeError, () => action(relativeTo), "rounding is not accepted between ISO offset and time zone");
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: >
|
||||
Appropriate error thrown when relativeTo cannot be converted to a valid
|
||||
relativeTo string or property bag
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const primitiveTests = [
|
||||
[undefined, "undefined"],
|
||||
[null, "null"],
|
||||
[true, "boolean"],
|
||||
["", "empty string"],
|
||||
[1, "number that doesn't convert to a valid ISO string"],
|
||||
[1n, "bigint"],
|
||||
];
|
||||
|
||||
for (const [relativeTo, description] of primitiveTests) {
|
||||
assert.throws(
|
||||
typeof relativeTo === 'string' || typeof relativeTo === 'undefined' ? RangeError : TypeError,
|
||||
() => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }),
|
||||
`${description} does not convert to a valid ISO string (first argument)`
|
||||
);
|
||||
}
|
||||
|
||||
const typeErrorTests = [
|
||||
[Symbol(), "symbol"],
|
||||
[{}, "plain object"],
|
||||
[Temporal.PlainDate, "Temporal.PlainDate, object"],
|
||||
[Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"],
|
||||
[Temporal.ZonedDateTime, "Temporal.ZonedDateTime, object"],
|
||||
[Temporal.ZonedDateTime.prototype, "Temporal.ZonedDateTime.prototype, object"],
|
||||
];
|
||||
|
||||
for (const [relativeTo, description] of typeErrorTests) {
|
||||
assert.throws(TypeError, () => instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }), `${description} is not a valid property bag and does not convert to a string`);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: relativeTo with years.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const oneYear = new Temporal.Duration(1);
|
||||
const days365 = new Temporal.Duration(0, 0, 0, 365);
|
||||
TemporalHelpers.assertDuration(oneYear.add(days365, { relativeTo: Temporal.PlainDate.from("2016-01-01") }),
|
||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, "non-leap year");
|
||||
TemporalHelpers.assertDuration(oneYear.add(days365, { relativeTo: Temporal.PlainDate.from("2015-01-01") }),
|
||||
1, 11, 0, 30, 0, 0, 0, 0, 0, 0, "leap year");
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: A pre-epoch value is handled correctly by the modulo operation in GetISOPartsFromEpoch
|
||||
info: |
|
||||
sec-temporal-getisopartsfromepoch step 1:
|
||||
1. Let _remainderNs_ be the mathematical value whose sign is the sign of _epochNanoseconds_ and whose magnitude is abs(_epochNanoseconds_) modulo 10<sup>6</sup>.
|
||||
sec-temporal-builtintimezonegetplaindatetimefor step 2:
|
||||
2. Let _result_ be ! GetISOPartsFromEpoch(_instant_.[[Nanoseconds]]).
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
const relativeTo = new Temporal.ZonedDateTime(-13849764_999_999_999n, "UTC");
|
||||
const duration = new Temporal.Duration(0, 0, 0, 1);
|
||||
|
||||
// This code path shows up anywhere we convert an exact time, before the Unix
|
||||
// epoch, with nonzero microseconds or nanoseconds, into a wall time; in this
|
||||
// case via relativeTo.
|
||||
|
||||
const result = duration.add(duration, { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0);
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: RangeError thrown if time zone reports an offset that is not an integer number of nanoseconds
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[3600_000_000_000.5, NaN, -Infinity, Infinity].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
|
||||
assert.throws(RangeError, () => duration.add(other, { relativeTo }));
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: TypeError thrown if timeZone.getOffsetNanosecondsFor is not callable
|
||||
features: [BigInt, Symbol, Temporal, arrow-function]
|
||||
---*/
|
||||
|
||||
[undefined, null, true, Math.PI, 'string', Symbol('sym'), 42n, {}].forEach((notCallable) => {
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
|
||||
timeZone.getOffsetNanosecondsFor = notCallable;
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => duration.add(other, { relativeTo }),
|
||||
`Uncallable ${notCallable === null ? 'null' : typeof notCallable} getOffsetNanosecondsFor should throw TypeError`
|
||||
);
|
||||
});
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: RangeError thrown if time zone reports an offset that is out of range
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[-86400_000_000_000, 86400_000_000_000].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
|
||||
assert.throws(RangeError, () => duration.add(other, { relativeTo }));
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: TypeError thrown if time zone reports an offset that is not a Number
|
||||
features: [Temporal]
|
||||
includes: [temporalHelpers.js]
|
||||
---*/
|
||||
|
||||
[
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"+01:00",
|
||||
Symbol(),
|
||||
3600_000_000_000n,
|
||||
{},
|
||||
{ valueOf() { return 3600_000_000_000; } },
|
||||
].forEach((wrongOffset) => {
|
||||
const timeZone = TemporalHelpers.specificOffsetTimeZone(wrongOffset);
|
||||
const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const other = new Temporal.Duration(2);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, timeZone);
|
||||
assert.throws(TypeError, () => duration.add(other, { relativeTo }));
|
||||
});
|
|
@ -8,20 +8,9 @@ description: >
|
|||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
|
||||
|
||||
// Largest temporal unit is "second".
|
||||
const duration = Temporal.Duration.from({seconds: Number.MAX_SAFE_INTEGER});
|
||||
|
||||
assert.throws(RangeError, () => {
|
||||
duration.add(duration);
|
||||
});
|
||||
|
||||
assert.throws(RangeError, () => {
|
||||
duration.add(duration, {relativeTo: plainDate});
|
||||
});
|
||||
|
||||
assert.throws(RangeError, () => {
|
||||
duration.add(duration, {relativeTo: zonedDateTime});
|
||||
});
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: An iterable returned from timeZone.getPossibleInstantsFor is consumed after each call
|
||||
info: |
|
||||
sec-temporal.duration.prototype.add steps 5–6:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], [...], _duration_.[[Nanoseconds]], _other_.[[Years]], [...], _other_.[[Nanoseconds]], _relativeTo_).
|
||||
sec-temporal-torelativetemporalobject step 6.d:
|
||||
d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*).
|
||||
sec-temporal-interpretisodatetimeoffset step 7:
|
||||
7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_).
|
||||
sec-temporal-addduration steps 7.d–e and 7.g.i:
|
||||
d. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, [...], _ns1_).
|
||||
e. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, [...], _ns2_).
|
||||
[...]
|
||||
i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_).
|
||||
sec-temporal-differencezoneddatetime step 8:
|
||||
8. Let _intermediateNs_ be ? AddZonedDateTime(_ns1_, _timeZone_, _calendar_, _dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], 0, 0, 0, 0, 0, 0, 0).
|
||||
sec-temporal-addzoneddatetime step 8:
|
||||
8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*).
|
||||
sec-temporal-builtintimezonegetinstantfor step 1:
|
||||
1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_).
|
||||
sec-temporal-getpossibleinstantsfor step 2:
|
||||
2. Let _list_ be ? IterableToList(_possibleInstants_).
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const expected = [
|
||||
"2000-01-01T09:00:00", // called once on the input relativeTo object
|
||||
"2001-01-01T09:00:00", // called once on relativeTo plus the receiver
|
||||
"2002-01-01T09:00:00", // called once on relativeTo plus the receiver plus the argument
|
||||
"2002-01-01T09:00:00", // called once on relativeTo plus the years, months, and weeks from the difference of relativeTo minus endNs
|
||||
];
|
||||
|
||||
TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => {
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, hour: 9, timeZone } });
|
||||
}, expected);
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.add
|
||||
description: Negative zero, as an extended year, is rejected
|
||||
features: [Temporal, arrow-function]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = "-000000-11-04T00:00";
|
||||
assert.throws(
|
||||
RangeError,
|
||||
() => { instance.add(new Temporal.Duration(0, 0, 0, 0, -24), { relativeTo }); },
|
||||
"reject minus zero as extended year"
|
||||
);
|
|
@ -10,20 +10,6 @@ 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"],
|
||||
|
|
|
@ -4,23 +4,6 @@
|
|||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: A negative duration result is balanced correctly by the modulo operation in NanosecondsToDays
|
||||
info: |
|
||||
sec-temporal-nanosecondstodays step 6:
|
||||
6. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then
|
||||
a. Return the new Record { ..., [[Nanoseconds]]: abs(_nanoseconds_) modulo _dayLengthNs_ × _sign_, ... }.
|
||||
sec-temporal-balanceduration step 4:
|
||||
4. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then
|
||||
a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_).
|
||||
sec-temporal-addduration steps 5–6:
|
||||
5. If _relativeTo_ is *undefined*, then
|
||||
...
|
||||
b. Let _result_ be ! BalanceDuration(_d1_ + _d2_, _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_).
|
||||
...
|
||||
6. Else if _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then
|
||||
...
|
||||
n. Let _result_ be ! BalanceDuration(_dateDifference_.[[Days]], _h1_ + _h2_, _min1_ + _min2_, _s1_ + _s2_, _ms1_ + _ms2_, _mus1_ + _mus2_, _ns1_ + _ns2_, _largestUnit_).
|
||||
sec-temporal.duration.prototype.subtract step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_).
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
@ -30,7 +13,3 @@ const duration2 = new Temporal.Duration(0, 0, 0, -1);
|
|||
|
||||
const resultNotRelative = duration1.subtract(duration2);
|
||||
TemporalHelpers.assertDuration(resultNotRelative, 0, 0, 0, -1, -12, 0, 0, 0, 0, 0);
|
||||
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
const resultRelative = duration1.subtract(duration2, { relativeTo });
|
||||
TemporalHelpers.assertDuration(resultRelative, 0, 0, 0, -1, -12, 0, 0, 0, 0, 0);
|
||||
|
|
|
@ -3,58 +3,29 @@
|
|||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Negative time fields in relativeTo are balanced upwards
|
||||
description: Negative time fields are balanced upwards
|
||||
info: |
|
||||
sec-temporal-balancetime steps 3–14:
|
||||
3. Set _microsecond_ to _microsecond_ + floor(_nanosecond_ / 1000).
|
||||
4. Set _nanosecond_ to _nanosecond_ modulo 1000.
|
||||
5. Set _millisecond_ to _millisecond_ + floor(_microsecond_ / 1000).
|
||||
6. Set _microsecond_ to _microsecond_ modulo 1000.
|
||||
7. Set _second_ to _second_ + floor(_millisecond_ / 1000).
|
||||
8. Set _millisecond_ to _millisecond_ modulo 1000.
|
||||
9. Set _minute_ to _minute_ + floor(_second_ / 60).
|
||||
10. Set _second_ to _second_ modulo 60.
|
||||
11. Set _hour_ to _hour_ + floor(_minute_ / 60).
|
||||
12. Set _minute_ to _minute_ modulo 60.
|
||||
13. Let _days_ be floor(_hour_ / 24).
|
||||
14. Set _hour_ to _hour_ modulo 24.
|
||||
sec-temporal-differencetime step 8:
|
||||
8. Let _bt_ be ? BalanceTime(_hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_).
|
||||
sec-temporal-differenceisodatetime step 2:
|
||||
2. Let _timeDifference_ be ? DifferenceTime(_h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_).
|
||||
sec-temporal-differencezoneddatetime step 7:
|
||||
7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_).
|
||||
sec-temporal-addduration step 7.g.i:
|
||||
i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_).
|
||||
sec-temporal.duration.prototype.subtract step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_).
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const duration = new Temporal.Duration(0, 0, 0, 0, 1, 1, 1, 1, 1, 1);
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const relativeTo = new Temporal.ZonedDateTime(830998861_000_000_000n, timeZone);
|
||||
// This code path is encountered if largestUnit is years, months, weeks, or days
|
||||
// and relativeTo is a ZonedDateTime
|
||||
const options = { largestUnit: "days", relativeTo };
|
||||
|
||||
const result1 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2), options);
|
||||
const result1 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 999, "nanoseconds balance");
|
||||
|
||||
const result2 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2), options);
|
||||
const result2 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result2, 0, 0, 0, 0, 1, 1, 1, 0, 999, 1, "microseconds balance");
|
||||
|
||||
const result3 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2), options);
|
||||
const result3 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result3, 0, 0, 0, 0, 1, 1, 0, 999, 1, 1, "milliseconds balance");
|
||||
|
||||
const result4 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2), options);
|
||||
const result4 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result4, 0, 0, 0, 0, 1, 0, 59, 1, 1, 1, "seconds balance");
|
||||
|
||||
const result5 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2), options);
|
||||
const result5 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result5, 0, 0, 0, 0, 0, 59, 1, 1, 1, 1, "minutes balance");
|
||||
|
||||
// This one is different because hours are later balanced again in BalanceDuration
|
||||
const result6 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 2), options);
|
||||
const result6 = duration.subtract(new Temporal.Duration(0, 0, 0, 0, 2));
|
||||
TemporalHelpers.assertDuration(result6, 0, 0, 0, 0, 0, -58, -58, -998, -998, -999, "hours balance");
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: >
|
||||
BuiltinTimeZoneGetInstantFor calls Calendar.dateAdd with undefined as the
|
||||
options value
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarDateAddUndefinedOptions();
|
||||
const timeZone = TemporalHelpers.oneShiftTimeZone(new Temporal.Instant(0n), 3600e9);
|
||||
const instance = new Temporal.Duration(1, 1, 1, 1);
|
||||
instance.subtract(new Temporal.Duration(-1, -1, -1, -1), { relativeTo: new Temporal.ZonedDateTime(0n, timeZone, calendar) });
|
||||
assert.sameValue(calendar.dateAddCallCount, 2);
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: >
|
||||
relativeTo parameters that are not ZonedDateTime or undefined, are always
|
||||
converted to PlainDate for observable calendar calls
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarDateAddPlainDateInstance();
|
||||
const instance = new Temporal.Duration(1, 1, 1, 1);
|
||||
const relativeTo = new Temporal.PlainDate(2000, 1, 1, calendar);
|
||||
calendar.specificPlainDate = relativeTo;
|
||||
instance.subtract(new Temporal.Duration(-1, -1, -1, -1), { relativeTo });
|
||||
assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested");
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Duration.prototype.subtract should call dateAdd with the appropriate values.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
let calls = 0;
|
||||
const expected = [
|
||||
{
|
||||
plainDate: [1920, 5, "M05", 3],
|
||||
duration: [2, 0, 0, 4, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
{
|
||||
plainDate: [1922, 5, "M05", 7],
|
||||
duration: [0, -10, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
},
|
||||
];
|
||||
class CustomCalendar extends Temporal.Calendar {
|
||||
constructor() {
|
||||
super("iso8601");
|
||||
}
|
||||
dateAdd(plainDate, duration, options) {
|
||||
TemporalHelpers.assertPlainDate(plainDate, ...expected[calls].plainDate,
|
||||
`plainDate argument ${calls}`);
|
||||
TemporalHelpers.assertDuration(duration, ...expected[calls].duration,
|
||||
`duration argument ${calls}`);
|
||||
assert.sameValue(options, undefined, "options argument");
|
||||
++calls;
|
||||
return super.dateAdd(plainDate, duration, options);
|
||||
}
|
||||
}
|
||||
const relativeTo = new Temporal.PlainDate(1920, 5, 3, new CustomCalendar());
|
||||
const duration = new Temporal.Duration(2, 0, 0, 4, 2);
|
||||
const result = duration.subtract({ months: 10, hours: 14 }, { relativeTo });
|
||||
TemporalHelpers.assertDuration(result, 1, 2, 0, 3, 12, 0, 0, 0, 0, 0, "result");
|
||||
assert.sameValue(calls, 2, "should have called dateAdd");
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form
|
||||
info: |
|
||||
sec-temporal.duration.prototype.subtract step 6:
|
||||
6. Let _result_ be ? AddDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], −_other_.[[Years]], −_other_.[[Months]], −_other_.[[Weeks]], −_other_.[[Days]], −_other_.[[Hours]], −_other_.[[Minutes]], −_other_.[[Seconds]], −_other_.[[Milliseconds]], −_other_.[[Microseconds]], −_other_.[[Nanoseconds]], _relativeTo_).
|
||||
sec-temporal-addduration steps 6-7:
|
||||
6. If _relativeTo_ has an [[InitializedTemporalPlainDateTime]] internal slot, then
|
||||
...
|
||||
j. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_).
|
||||
k. Let _differenceOptions_ be ! OrdinaryObjectCreate(*null*).
|
||||
l. Perform ! CreateDataPropertyOrThrow(_differenceOptions_, *"largestUnit"*, _dateLargestUnit_).
|
||||
m. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _datePart_, _end_, _differenceOptions_).
|
||||
...
|
||||
7. Else,
|
||||
a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot.
|
||||
...
|
||||
f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then
|
||||
...
|
||||
g. Else,
|
||||
i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_).
|
||||
sec-temporal-differencezoneddatetime steps 7 and 11:
|
||||
7. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _calendar_, _largestUnit_, _options_).
|
||||
11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_).
|
||||
sec-temporal-nanosecondstodays step 11:
|
||||
11. 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*).
|
||||
sec-temporal-differenceisodatetime steps 9–11:
|
||||
9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_).
|
||||
10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_).
|
||||
11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_).
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
|
||||
(calendar, largestUnit, index) => {
|
||||
const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]);
|
||||
const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321, calendar);
|
||||
two.subtract(one, { relativeTo });
|
||||
},
|
||||
{
|
||||
years: ["year"],
|
||||
months: ["month"],
|
||||
weeks: ["week"],
|
||||
days: [],
|
||||
hours: [],
|
||||
minutes: [],
|
||||
seconds: [],
|
||||
milliseconds: [],
|
||||
microseconds: [],
|
||||
nanoseconds: []
|
||||
}
|
||||
);
|
||||
|
||||
TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
|
||||
(calendar, largestUnit, index) => {
|
||||
const one = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(1)]);
|
||||
const two = new Temporal.Duration(...[...Array(index).fill(0), ...Array(10 - index).fill(2)]);
|
||||
const relativeTo = new Temporal.ZonedDateTime(1_000_000_000_987_654_321n, "UTC", calendar);
|
||||
two.subtract(one, { relativeTo });
|
||||
},
|
||||
{
|
||||
years: ["year"],
|
||||
months: ["month"],
|
||||
weeks: ["week"],
|
||||
days: [],
|
||||
hours: [],
|
||||
minutes: [],
|
||||
seconds: [],
|
||||
milliseconds: [],
|
||||
microseconds: [],
|
||||
nanoseconds: []
|
||||
}
|
||||
);
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Verify the result of calendar.fields() is treated correctly.
|
||||
info: |
|
||||
sec-temporal.duration.prototype.subtract step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.c:
|
||||
c. Let _fieldNames_ be ? CalendarFields(_calendar_, « *"day"*, *"month"*, *"monthCode"*, *"year"* »).
|
||||
sec-temporal-calendarfields step 4:
|
||||
4. Let _result_ be ? IterableToList(_fieldsArray_).
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const expected = [
|
||||
"day",
|
||||
"month",
|
||||
"monthCode",
|
||||
"year",
|
||||
];
|
||||
|
||||
const calendar = TemporalHelpers.calendarFieldsIterable();
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } });
|
||||
|
||||
assert.sameValue(calendar.fieldsCallCount, 1, "fields() method called once");
|
||||
assert.compareArray(calendar.fieldsCalledWith[0], expected, "fields() method called with correct args");
|
||||
assert(calendar.iteratorExhausted[0], "iterated through the whole iterable");
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Fast path for converting other Temporal objects to Temporal.Calendar by reading internal slots
|
||||
info: |
|
||||
sec-temporal.duration.prototype.subtract step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.b:
|
||||
b. Let _calendar_ be ? GetTemporalCalendarWithISODefault(_item_).
|
||||
sec-temporal-gettemporalcalendarwithisodefault step 2:
|
||||
2. Return ? ToTemporalCalendarWithISODefault(_calendar_).
|
||||
sec-temporal-totemporalcalendarwithisodefault step 2:
|
||||
3. Return ? ToTemporalCalendar(_temporalCalendarLike_).
|
||||
sec-temporal-totemporalcalendar step 1.a:
|
||||
a. If _temporalCalendarLike_ has an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], [[InitializedTemporalMonthDay]], [[InitializedTemporalYearMonth]], or [[InitializedTemporalZonedDateTime]] internal slot, then
|
||||
i. Return _temporalCalendarLike_.[[Calendar]].
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
TemporalHelpers.checkToTemporalCalendarFastPath((temporalObject) => {
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar: temporalObject } });
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
// 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.subtract
|
||||
description: If a calendar's fields() method returns a field named 'constructor', PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(['constructor']);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }));
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright (C) 2024 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: >
|
||||
Throws a RangeError when custom calendar method returns inconsistent result
|
||||
info: |
|
||||
DifferenceZonedDateTime ( ... )
|
||||
8. Repeat 3 times:
|
||||
...
|
||||
g. If _sign_ = 0, or _timeSign_ = 0, or _sign_ = _timeSign_, then
|
||||
...
|
||||
viii. Return ? CreateNormalizedDurationRecord(_dateDifference_.[[Years]],
|
||||
_dateDifference_.[[Months]], _dateDifference_.[[Weeks]],
|
||||
_dateDifference_.[[Days]], _norm_).
|
||||
h. Set _dayCorrection_ to _dayCorrection_ + 1.
|
||||
9. NOTE: This step is only reached when custom calendar or time zone methods
|
||||
return inconsistent values.
|
||||
10. Throw a *RangeError* exception.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
// Based partly on a test case by André Bargull
|
||||
|
||||
const duration1 = new Temporal.Duration(0, 0, /* weeks = */ 7, 0, /* hours = */ 12);
|
||||
const duration2 = new Temporal.Duration(0, 0, 0, /* days = */ -1);
|
||||
|
||||
{
|
||||
const tz = new (class extends Temporal.TimeZone {
|
||||
getPossibleInstantsFor(dateTime) {
|
||||
return super.getPossibleInstantsFor(dateTime.add({ days: 3 }));
|
||||
}
|
||||
})("UTC");
|
||||
|
||||
const relativeTo = new Temporal.ZonedDateTime(0n, tz);
|
||||
|
||||
assert.throws(RangeError, () => duration1.subtract(duration2, { relativeTo }),
|
||||
"Calendar calculation where more than 2 days correction is needed should cause RangeError");
|
||||
}
|
||||
|
||||
{
|
||||
const cal = new (class extends Temporal.Calendar {
|
||||
dateUntil(one, two, options) {
|
||||
return super.dateUntil(one, two, options).negated();
|
||||
}
|
||||
})("iso8601");
|
||||
|
||||
const relativeTo = new Temporal.ZonedDateTime(0n, "UTC", cal);
|
||||
|
||||
assert.throws(RangeError, () => duration1.subtract(duration2, { relativeTo }),
|
||||
"Calendar calculation causing mixed-sign values should cause RangeError");
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// 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.subtract
|
||||
description: If a calendar's fields() method returns duplicate field names, PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
for (const extra_fields of [['foo', 'foo'], ['day'], ['month'], ['monthCode'], ['year']]) {
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(extra_fields);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }));
|
||||
}
|
|
@ -10,10 +10,9 @@ features: [Temporal]
|
|||
const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds'];
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
|
||||
fields.forEach((field) => {
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: Infinity }));
|
||||
});
|
||||
|
||||
let calls = 0;
|
||||
|
@ -26,6 +25,6 @@ const obj = {
|
|||
|
||||
fields.forEach((field) => {
|
||||
calls = 0;
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: obj }));
|
||||
assert.sameValue(calls, 1, "it fails after fetching the primitive value");
|
||||
});
|
||||
|
|
|
@ -1,19 +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.duration.prototype.subtract
|
||||
description: >
|
||||
AddZonedDateTime throws a RangeError when the intermediate instant is too large.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(0n, "UTC", "iso8601");
|
||||
|
||||
var duration1 = Temporal.Duration.from({days: 1, seconds: Number.MAX_SAFE_INTEGER - 86400});
|
||||
var duration2 = Temporal.Duration.from({days: -1, seconds: -Number.MAX_SAFE_INTEGER + 86400});
|
||||
|
||||
var options = {relativeTo: zonedDateTime};
|
||||
|
||||
assert.throws(RangeError, () => duration1.subtract(duration2, options));
|
|
@ -9,9 +9,6 @@ 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});
|
||||
|
@ -29,29 +26,3 @@ TemporalHelpers.assertDuration(
|
|||
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})"
|
||||
);
|
||||
|
|
|
@ -10,10 +10,9 @@ features: [Temporal]
|
|||
const fields = ['years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds', 'nanoseconds'];
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const relativeTo = new Temporal.PlainDateTime(2000, 1, 1);
|
||||
|
||||
fields.forEach((field) => {
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: -Infinity }));
|
||||
});
|
||||
|
||||
let calls = 0;
|
||||
|
@ -26,6 +25,6 @@ const obj = {
|
|||
|
||||
fields.forEach((field) => {
|
||||
calls = 0;
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: obj }, { relativeTo }));
|
||||
assert.throws(RangeError, () => instance.subtract({ [field]: obj }));
|
||||
assert.sameValue(calls, 1, "it fails after fetching the primitive value");
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Empty or a function object may be used as options
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(0, 0, 0, 0, 1);
|
||||
|
||||
const result1 = instance.subtract({ hours: 1 }, {});
|
||||
TemporalHelpers.assertDuration(
|
||||
result1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"options may be an empty plain object"
|
||||
);
|
||||
|
||||
const result2 = instance.subtract({ hours: 1 }, () => {});
|
||||
TemporalHelpers.assertDuration(
|
||||
result2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"options may be a function object"
|
||||
);
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Verify that undefined options are handled correctly.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 24);
|
||||
const duration3 = new Temporal.Duration(0, 0, 0, 1);
|
||||
const duration4 = new Temporal.Duration(0, 0, 0, 0, 48);
|
||||
|
||||
assert.throws(RangeError, () => duration1.subtract(duration2), "no options with years");
|
||||
TemporalHelpers.assertDuration(duration3.subtract(duration4),
|
||||
0, 0, 0, /* days = */ -1, 0, 0, 0, 0, 0, 0,
|
||||
"no options with days");
|
||||
|
||||
const optionValues = [
|
||||
[undefined, "undefined"],
|
||||
[{}, "plain object"],
|
||||
[() => {}, "lambda"],
|
||||
];
|
||||
for (const [options, description] of optionValues) {
|
||||
assert.throws(RangeError, () => duration1.subtract(duration2, options),
|
||||
`options ${description} with years`);
|
||||
TemporalHelpers.assertDuration(duration3.subtract(duration4, options),
|
||||
0, 0, 0, /* days = */ -1, 0, 0, 0, 0, 0, 0,
|
||||
`options ${description} with days`);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: TypeError thrown when options argument is a primitive
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const badOptions = [
|
||||
null,
|
||||
true,
|
||||
"some string",
|
||||
Symbol(),
|
||||
1,
|
||||
2n,
|
||||
];
|
||||
|
||||
const instance = new Temporal.Duration(0, 0, 0, 0, 1);
|
||||
for (const value of badOptions) {
|
||||
assert.throws(TypeError, () => instance.subtract({ hours: 1 }, value),
|
||||
`TypeError on wrong options type ${typeof value}`);
|
||||
};
|
|
@ -40,8 +40,6 @@ const expected = [
|
|||
"get fields.years",
|
||||
"get fields.years.valueOf",
|
||||
"call fields.years.valueOf",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
];
|
||||
const actual = [];
|
||||
|
||||
|
@ -58,423 +56,8 @@ const simpleFields = TemporalHelpers.propertyBagObserver(actual, {
|
|||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
function createOptionsObserver(relativeTo = undefined) {
|
||||
return TemporalHelpers.propertyBagObserver(actual, { relativeTo }, "options");
|
||||
}
|
||||
|
||||
// basic order of observable operations, without any calendar units:
|
||||
const simpleInstance = new Temporal.Duration(0, 0, 0, 1, 1, 1, 1, 1, 1, 1);
|
||||
simpleInstance.subtract(simpleFields, createOptionsObserver());
|
||||
simpleInstance.subtract(simpleFields);
|
||||
assert.compareArray(actual, expected, "order of operations");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForPlainRelativeTo = expected.concat([
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
// AddDuration
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.calendar.dateUntil",
|
||||
]);
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 1, 4, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const fields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
years: 1,
|
||||
months: 1,
|
||||
weeks: 1,
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
const plainRelativeTo = TemporalHelpers.propertyBagObserver(actual, {
|
||||
year: 2000,
|
||||
month: 1,
|
||||
monthCode: "M01",
|
||||
day: 1,
|
||||
calendar: TemporalHelpers.calendarObserver(actual, "options.relativeTo.calendar"),
|
||||
}, "options.relativeTo");
|
||||
|
||||
instance.subtract(fields, createOptionsObserver(plainRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForPlainRelativeTo, "order of operations with PlainDate relativeTo");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForPlainRelativeToNoCalendarOperations = [
|
||||
// ToTemporalDurationRecord
|
||||
"get fields.days",
|
||||
"get fields.days.valueOf",
|
||||
"call fields.days.valueOf",
|
||||
"get fields.hours",
|
||||
"get fields.hours.valueOf",
|
||||
"call fields.hours.valueOf",
|
||||
"get fields.microseconds",
|
||||
"get fields.microseconds.valueOf",
|
||||
"call fields.microseconds.valueOf",
|
||||
"get fields.milliseconds",
|
||||
"get fields.milliseconds.valueOf",
|
||||
"call fields.milliseconds.valueOf",
|
||||
"get fields.minutes",
|
||||
"get fields.minutes.valueOf",
|
||||
"call fields.minutes.valueOf",
|
||||
"get fields.months",
|
||||
"get fields.nanoseconds",
|
||||
"get fields.nanoseconds.valueOf",
|
||||
"call fields.nanoseconds.valueOf",
|
||||
"get fields.seconds",
|
||||
"get fields.seconds.valueOf",
|
||||
"call fields.seconds.valueOf",
|
||||
"get fields.weeks",
|
||||
"get fields.years",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
];
|
||||
|
||||
const noCalendarInstance = new Temporal.Duration(0, 0, 0, 4, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const noCalendarFields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
days: 1,
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
noCalendarInstance.subtract(noCalendarFields, createOptionsObserver(plainRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForPlainRelativeToNoCalendarOperations, "order of operations with PlainDate relativeTo and no calendar units");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForZonedRelativeTo = expected.concat([
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.hour.valueOf",
|
||||
"call options.relativeTo.hour.valueOf",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.microsecond.valueOf",
|
||||
"call options.relativeTo.microsecond.valueOf",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.millisecond.valueOf",
|
||||
"call options.relativeTo.millisecond.valueOf",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.minute.valueOf",
|
||||
"call options.relativeTo.minute.valueOf",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.nanosecond.valueOf",
|
||||
"call options.relativeTo.nanosecond.valueOf",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.offset.toString",
|
||||
"call options.relativeTo.offset.toString",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.second.valueOf",
|
||||
"call options.relativeTo.second.valueOf",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// ToRelativeTemporalObject again
|
||||
"has options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"has options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"has options.relativeTo.timeZone.id",
|
||||
// InterpretISODateTimeOffset
|
||||
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"get options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
// AddDuration
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// AddDuration → AddZonedDateTime 1
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
// AddDuration → AddZonedDateTime 2
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"call options.relativeTo.calendar.dateAdd",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
// AddDuration → DifferenceZonedDateTime
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.calendar.dateUntil",
|
||||
]);
|
||||
|
||||
const zonedRelativeTo = TemporalHelpers.propertyBagObserver(actual, {
|
||||
year: 2000,
|
||||
month: 1,
|
||||
monthCode: "M01",
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0,
|
||||
microsecond: 0,
|
||||
nanosecond: 0,
|
||||
offset: "+00:00",
|
||||
calendar: TemporalHelpers.calendarObserver(actual, "options.relativeTo.calendar"),
|
||||
timeZone: TemporalHelpers.timeZoneObserver(actual, "options.relativeTo.timeZone"),
|
||||
}, "options.relativeTo");
|
||||
|
||||
instance.subtract(fields, createOptionsObserver(zonedRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForZonedRelativeTo, "order of operations with ZonedDateTime relativeTo");
|
||||
actual.splice(0); // clear
|
||||
|
||||
const expectedOpsForZonedRelativeToNoDaysOperations = [
|
||||
// ToTemporalDurationRecord
|
||||
"get fields.days",
|
||||
"get fields.hours",
|
||||
"get fields.hours.valueOf",
|
||||
"call fields.hours.valueOf",
|
||||
"get fields.microseconds",
|
||||
"get fields.microseconds.valueOf",
|
||||
"call fields.microseconds.valueOf",
|
||||
"get fields.milliseconds",
|
||||
"get fields.milliseconds.valueOf",
|
||||
"call fields.milliseconds.valueOf",
|
||||
"get fields.minutes",
|
||||
"get fields.minutes.valueOf",
|
||||
"call fields.minutes.valueOf",
|
||||
"get fields.months",
|
||||
"get fields.nanoseconds",
|
||||
"get fields.nanoseconds.valueOf",
|
||||
"call fields.nanoseconds.valueOf",
|
||||
"get fields.seconds",
|
||||
"get fields.seconds.valueOf",
|
||||
"call fields.seconds.valueOf",
|
||||
"get fields.weeks",
|
||||
"get fields.years",
|
||||
// ToRelativeTemporalObject
|
||||
"get options.relativeTo",
|
||||
"get options.relativeTo.calendar",
|
||||
"has options.relativeTo.calendar.dateAdd",
|
||||
"has options.relativeTo.calendar.dateFromFields",
|
||||
"has options.relativeTo.calendar.dateUntil",
|
||||
"has options.relativeTo.calendar.day",
|
||||
"has options.relativeTo.calendar.dayOfWeek",
|
||||
"has options.relativeTo.calendar.dayOfYear",
|
||||
"has options.relativeTo.calendar.daysInMonth",
|
||||
"has options.relativeTo.calendar.daysInWeek",
|
||||
"has options.relativeTo.calendar.daysInYear",
|
||||
"has options.relativeTo.calendar.fields",
|
||||
"has options.relativeTo.calendar.id",
|
||||
"has options.relativeTo.calendar.inLeapYear",
|
||||
"has options.relativeTo.calendar.mergeFields",
|
||||
"has options.relativeTo.calendar.month",
|
||||
"has options.relativeTo.calendar.monthCode",
|
||||
"has options.relativeTo.calendar.monthDayFromFields",
|
||||
"has options.relativeTo.calendar.monthsInYear",
|
||||
"has options.relativeTo.calendar.weekOfYear",
|
||||
"has options.relativeTo.calendar.year",
|
||||
"has options.relativeTo.calendar.yearMonthFromFields",
|
||||
"has options.relativeTo.calendar.yearOfWeek",
|
||||
"get options.relativeTo.calendar.dateFromFields",
|
||||
"get options.relativeTo.calendar.fields",
|
||||
"call options.relativeTo.calendar.fields",
|
||||
// PrepareTemporalFields
|
||||
"get options.relativeTo.day",
|
||||
"get options.relativeTo.day.valueOf",
|
||||
"call options.relativeTo.day.valueOf",
|
||||
"get options.relativeTo.hour",
|
||||
"get options.relativeTo.hour.valueOf",
|
||||
"call options.relativeTo.hour.valueOf",
|
||||
"get options.relativeTo.microsecond",
|
||||
"get options.relativeTo.microsecond.valueOf",
|
||||
"call options.relativeTo.microsecond.valueOf",
|
||||
"get options.relativeTo.millisecond",
|
||||
"get options.relativeTo.millisecond.valueOf",
|
||||
"call options.relativeTo.millisecond.valueOf",
|
||||
"get options.relativeTo.minute",
|
||||
"get options.relativeTo.minute.valueOf",
|
||||
"call options.relativeTo.minute.valueOf",
|
||||
"get options.relativeTo.month",
|
||||
"get options.relativeTo.month.valueOf",
|
||||
"call options.relativeTo.month.valueOf",
|
||||
"get options.relativeTo.monthCode",
|
||||
"get options.relativeTo.monthCode.toString",
|
||||
"call options.relativeTo.monthCode.toString",
|
||||
"get options.relativeTo.nanosecond",
|
||||
"get options.relativeTo.nanosecond.valueOf",
|
||||
"call options.relativeTo.nanosecond.valueOf",
|
||||
"get options.relativeTo.offset",
|
||||
"get options.relativeTo.offset.toString",
|
||||
"call options.relativeTo.offset.toString",
|
||||
"get options.relativeTo.second",
|
||||
"get options.relativeTo.second.valueOf",
|
||||
"call options.relativeTo.second.valueOf",
|
||||
"get options.relativeTo.timeZone",
|
||||
"get options.relativeTo.year",
|
||||
"get options.relativeTo.year.valueOf",
|
||||
"call options.relativeTo.year.valueOf",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call options.relativeTo.calendar.dateFromFields",
|
||||
// ToRelativeTemporalObject again
|
||||
"has options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"has options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"has options.relativeTo.timeZone.id",
|
||||
// InterpretISODateTimeOffset
|
||||
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
"get options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getPossibleInstantsFor",
|
||||
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
|
||||
// lookup in AddDurationToOrSubtractDurationFromDuration
|
||||
"get options.relativeTo.calendar.dateAdd",
|
||||
"get options.relativeTo.calendar.dateUntil",
|
||||
];
|
||||
|
||||
const noDaysInstance = new Temporal.Duration(0, 0, 0, 0, 5, 6, 7, 987, 654, 321);
|
||||
|
||||
const noDaysFields = TemporalHelpers.propertyBagObserver(actual, {
|
||||
hours: 1,
|
||||
minutes: 1,
|
||||
seconds: 1,
|
||||
milliseconds: 1,
|
||||
microseconds: 1,
|
||||
nanoseconds: 1,
|
||||
}, "fields");
|
||||
|
||||
noDaysInstance.subtract(noDaysFields, createOptionsObserver(zonedRelativeTo));
|
||||
assert.compareArray(actual, expectedOpsForZonedRelativeToNoDaysOperations, "order of operations with ZonedDateTime relativeTo and no units above days");
|
||||
actual.splice(0); // clear
|
||||
|
|
|
@ -9,9 +9,6 @@ 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({seconds: 4503599627370495, nanoseconds: 499_999_999});
|
||||
const duration2 = Temporal.Duration.from({seconds: -4503599627370495 + 86400, nanoseconds: -499_999_999, days: -1});
|
||||
|
@ -29,21 +26,3 @@ TemporalHelpers.assertDuration(
|
|||
Number(nanos % 1000n),
|
||||
"duration1.subtract(duration2)"
|
||||
);
|
||||
|
||||
TemporalHelpers.assertDuration(
|
||||
duration1.subtract(duration2, {relativeTo: plainDate}),
|
||||
0, 0, 0,
|
||||
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});
|
||||
});
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
// 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.subtract
|
||||
description: If a calendar's fields() method returns a field named '__proto__', PrepareTemporalFields should throw a RangeError.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarWithExtraFields(['__proto__']);
|
||||
const relativeTo = { year: 2023, month: 5, monthCode: 'M05', day: 1, calendar: calendar, timeZone: 'Europe/Paris' };
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
assert.throws(RangeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }));
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: The time fields are read from the object before being passed to dateFromFields().
|
||||
info: |
|
||||
sec-temporal.duration.prototype.subtract step 5:
|
||||
5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_).
|
||||
sec-temporal-torelativetemporalobject step 4.g:
|
||||
g. Let _result_ be ? InterpretTemporalDateTimeFields(_calendar_, _fields_, _options_).
|
||||
sec-temporal-interprettemporaldatetimefields steps 1–2:
|
||||
1. Let _timeResult_ be ? ToTemporalTimeRecord(_fields_).
|
||||
2. Let _temporalDate_ be ? DateFromFields(_calendar_, _fields_, _options_).
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarMakeInvalidGettersTime();
|
||||
const duration1 = new Temporal.Duration(1);
|
||||
const duration2 = new Temporal.Duration(0, 12);
|
||||
duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, calendar } });
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2021 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
description: Throws if any value in the property bag is Infinity or -Infinity
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
includes: [compareArray.js, temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
|
||||
const base = { year: 2000, month: 5, day: 2, hour: 15, minute: 30, second: 45, millisecond: 987, microsecond: 654, nanosecond: 321 };
|
||||
|
||||
[Infinity, -Infinity].forEach((inf) => {
|
||||
["year", "month", "day", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond"].forEach((prop) => {
|
||||
assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, [prop]: inf } }), `${prop} property cannot be ${inf} in relativeTo`);
|
||||
|
||||
const calls = [];
|
||||
const obj = TemporalHelpers.toPrimitiveObserver(calls, inf, prop);
|
||||
assert.throws(RangeError, () => instance.subtract(instance, { relativeTo: { ...base, [prop]: obj } }));
|
||||
assert.compareArray(calls, [`get ${prop}.valueOf`, `call ${prop}.valueOf`], "it fails after fetching the primitive value");
|
||||
});
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: Leap second is constrained in both an ISO string and a property bag
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = "2016-12-31T23:59:60";
|
||||
const result1 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result1,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"leap second is a valid ISO string for PlainDate relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = "2016-12-31T23:59:60+00:00[UTC]";
|
||||
const result2 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result2,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"leap second is a valid ISO string for ZonedDateTime relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60 };
|
||||
const result3 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result3,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"second: 60 is valid in a property bag for PlainDate relativeTo"
|
||||
);
|
||||
|
||||
relativeTo = { year: 2016, month: 12, day: 31, hour: 23, minute: 59, second: 60, timeZone: "UTC" };
|
||||
const result4 = instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
TemporalHelpers.assertDuration(
|
||||
result4,
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
"second: 60 is valid in a property bag for ZonedDateTime relativeTo"
|
||||
);
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: relativeTo with months.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const oneMonth = new Temporal.Duration(0, 1);
|
||||
const days30 = new Temporal.Duration(0, 0, 0, 30);
|
||||
TemporalHelpers.assertDuration(oneMonth.subtract(days30, { relativeTo: Temporal.PlainDate.from('2018-02-01') }),
|
||||
0, 0, 0, -2, 0, 0, 0, 0, 0, 0, "February");
|
||||
TemporalHelpers.assertDuration(oneMonth.subtract(days30, { relativeTo: Temporal.PlainDate.from('2018-03-01') }),
|
||||
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "March");
|
||||
TemporalHelpers.assertDuration(oneMonth.subtract(days30, { relativeTo: Temporal.PlainDate.from('2018-04-01') }),
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "April");
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: A number cannot be used in place of a relativeTo
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const numbers = [
|
||||
1,
|
||||
20191101,
|
||||
-20191101,
|
||||
1234567890,
|
||||
];
|
||||
|
||||
for (const relativeTo of numbers) {
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }),
|
||||
`A number (${relativeTo}) is not a valid ISO string for relativeTo`
|
||||
);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: relativeTo with years.
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const d1 = new Temporal.Duration(0, 2, 1, 4);
|
||||
const d2 = new Temporal.Duration(0, 1, 1, 1);
|
||||
const relativeTo = new Temporal.PlainDate(2000, 1, 1);
|
||||
TemporalHelpers.assertDuration(d1.subtract(d2, { relativeTo }),
|
||||
0, 1, 0, 3, 0, 0, 0, 0, 0, 0,
|
||||
"first this is resolved against relativeTo, then the argument against relativeTo + this");
|
|
@ -1,89 +0,0 @@
|
|||
// 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.subtract
|
||||
description: >
|
||||
Correct time zone calls are made when converting a ZonedDateTime-like
|
||||
relativeTo property bag denoting an ambiguous wall-clock time
|
||||
includes: [temporalHelpers.js, compareArray.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const actual = [];
|
||||
|
||||
const dstTimeZone = TemporalHelpers.springForwardFallBackTimeZone();
|
||||
const dstTimeZoneObserver = TemporalHelpers.timeZoneObserver(actual, "timeZone", {
|
||||
getOffsetNanosecondsFor: dstTimeZone.getOffsetNanosecondsFor.bind(dstTimeZone),
|
||||
getPossibleInstantsFor: dstTimeZone.getPossibleInstantsFor.bind(dstTimeZone),
|
||||
});
|
||||
const calendar = TemporalHelpers.calendarObserver(actual, "calendar");
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
let relativeTo = { year: 2000, month: 4, day: 2, hour: 2, minute: 30, timeZone: dstTimeZoneObserver, calendar };
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
|
||||
const expected = [
|
||||
// GetTemporalCalendarSlotValueWithISODefault
|
||||
"has calendar.dateAdd",
|
||||
"has calendar.dateFromFields",
|
||||
"has calendar.dateUntil",
|
||||
"has calendar.day",
|
||||
"has calendar.dayOfWeek",
|
||||
"has calendar.dayOfYear",
|
||||
"has calendar.daysInMonth",
|
||||
"has calendar.daysInWeek",
|
||||
"has calendar.daysInYear",
|
||||
"has calendar.fields",
|
||||
"has calendar.id",
|
||||
"has calendar.inLeapYear",
|
||||
"has calendar.mergeFields",
|
||||
"has calendar.month",
|
||||
"has calendar.monthCode",
|
||||
"has calendar.monthDayFromFields",
|
||||
"has calendar.monthsInYear",
|
||||
"has calendar.weekOfYear",
|
||||
"has calendar.year",
|
||||
"has calendar.yearMonthFromFields",
|
||||
"has calendar.yearOfWeek",
|
||||
// lookup
|
||||
"get calendar.dateFromFields",
|
||||
"get calendar.fields",
|
||||
// CalendarFields
|
||||
"call calendar.fields",
|
||||
// InterpretTemporalDateTimeFields
|
||||
"call calendar.dateFromFields",
|
||||
// ToTemporalTimeZoneSlotValue
|
||||
"has timeZone.getOffsetNanosecondsFor",
|
||||
"has timeZone.getPossibleInstantsFor",
|
||||
"has timeZone.id",
|
||||
// lookup
|
||||
"get timeZone.getOffsetNanosecondsFor",
|
||||
"get timeZone.getPossibleInstantsFor",
|
||||
// InterpretISODateTimeOffset
|
||||
"call timeZone.getPossibleInstantsFor",
|
||||
];
|
||||
|
||||
const expectedSpringForward = expected.concat([
|
||||
// DisambiguatePossibleInstants
|
||||
"call timeZone.getOffsetNanosecondsFor",
|
||||
"call timeZone.getOffsetNanosecondsFor",
|
||||
"call timeZone.getPossibleInstantsFor",
|
||||
]);
|
||||
assert.compareArray(
|
||||
actual.slice(0, expectedSpringForward.length), // ignore operations after ToRelativeTemporalObject
|
||||
expectedSpringForward,
|
||||
"order of operations converting property bag at skipped wall-clock time"
|
||||
);
|
||||
actual.splice(0); // clear
|
||||
|
||||
relativeTo = { year: 2000, month: 10, day: 29, hour: 1, minute: 30, timeZone: dstTimeZoneObserver, calendar };
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
|
||||
assert.compareArray(
|
||||
actual.slice(0, expected.length), // ignore operations after ToRelativeTemporalObject
|
||||
expected,
|
||||
"order of operations converting property bag at repeated wall-clock time"
|
||||
);
|
||||
actual.splice(0); // clear
|
|
@ -1,22 +0,0 @@
|
|||
// 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.subtract
|
||||
description: >
|
||||
Calling the method with a relativeTo property bag with a builtin calendar
|
||||
causes no observable array iteration when getting the calendar fields.
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const arrayPrototypeSymbolIteratorOriginal = Array.prototype[Symbol.iterator];
|
||||
Array.prototype[Symbol.iterator] = function arrayIterator() {
|
||||
throw new Test262Error("Array should not be iterated");
|
||||
}
|
||||
|
||||
const timeZone = "UTC";
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, hour: 21, minute: 43, second: 5, timeZone, calendar: "iso8601" };
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
|
||||
Array.prototype[Symbol.iterator] = arrayPrototypeSymbolIteratorOriginal;
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: >
|
||||
Calendar.dateFromFields method is called with a null-prototype fields object
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const calendar = TemporalHelpers.calendarCheckFieldsPrototypePollution();
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, calendar };
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
assert.sameValue(calendar.dateFromFieldsCallCount, 1, "dateFromFields should be called on the property bag's calendar");
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: A number as calendar in relativeTo property bag is invalid
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const numbers = [
|
||||
1,
|
||||
19970327,
|
||||
-19970327,
|
||||
1234567890,
|
||||
];
|
||||
|
||||
for (const calendar of numbers) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(
|
||||
TypeError,
|
||||
() => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }),
|
||||
`A number (${calendar}) is not a valid ISO string for relativeTo.calendar`
|
||||
);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// 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.subtract
|
||||
description: >
|
||||
Builtin dateFromFields method is not observably called when the property bag
|
||||
has a string-valued calendar property
|
||||
includes: [temporalHelpers.js]
|
||||
features: [Temporal]
|
||||
---*/
|
||||
|
||||
const dateFromFieldsOriginal = Object.getOwnPropertyDescriptor(Temporal.Calendar.prototype, "dateFromFields");
|
||||
Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
get() {
|
||||
TemporalHelpers.assertUnreachable("dateFromFields should not be looked up");
|
||||
},
|
||||
});
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, calendar: "iso8601" };
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
|
||||
Object.defineProperty(Temporal.Calendar.prototype, "dateFromFields", dateFromFieldsOriginal);
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
|
||||
/*---
|
||||
esid: sec-temporal.duration.prototype.subtract
|
||||
description: >
|
||||
Appropriate error thrown when relativeTo.calendar cannot be converted to a
|
||||
calendar object or string
|
||||
features: [BigInt, Symbol, Temporal]
|
||||
---*/
|
||||
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
|
||||
const primitiveTests = [
|
||||
[null, "null"],
|
||||
[true, "boolean"],
|
||||
["", "empty string"],
|
||||
[1, "number that doesn't convert to a valid ISO string"],
|
||||
[1n, "bigint"],
|
||||
];
|
||||
|
||||
for (const [calendar, description] of primitiveTests) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(
|
||||
typeof calendar === 'string' ? RangeError : TypeError,
|
||||
() => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }),
|
||||
`${description} does not convert to a valid ISO string`
|
||||
);
|
||||
}
|
||||
|
||||
const typeErrorTests = [
|
||||
[Symbol(), "symbol"],
|
||||
[{}, "plain object that doesn't implement the protocol"],
|
||||
[new Temporal.TimeZone("UTC"), "time zone instance"],
|
||||
[Temporal.PlainDate, "Temporal.PlainDate, object"],
|
||||
[Temporal.PlainDate.prototype, "Temporal.PlainDate.prototype, object"],
|
||||
[Temporal.ZonedDateTime, "Temporal.ZonedDateTime, object"],
|
||||
[Temporal.ZonedDateTime.prototype, "Temporal.ZonedDateTime.prototype, object"],
|
||||
];
|
||||
|
||||
for (const [calendar, description] of typeErrorTests) {
|
||||
const relativeTo = { year: 2019, monthCode: "M11", day: 1, calendar };
|
||||
assert.throws(TypeError, () => instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo }), `${description} is not a valid property bag and does not convert to a string`);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
// 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.subtract
|
||||
description: >
|
||||
Time zone's getPossibleInstantsFor is called with a PlainDateTime with the
|
||||
built-in ISO 8601 calendar
|
||||
features: [Temporal]
|
||||
info: |
|
||||
DisambiguatePossibleInstants:
|
||||
2. Let _n_ be _possibleInstants_'s length.
|
||||
...
|
||||
5. Assert: _n_ = 0.
|
||||
...
|
||||
19. If _disambiguation_ is *"earlier"*, then
|
||||
...
|
||||
c. Let _earlierDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
|
||||
d. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _earlierDateTime_).
|
||||
...
|
||||
20. Assert: _disambiguation_ is *"compatible"* or *"later"*.
|
||||
...
|
||||
23. Let _laterDateTime_ be ! CreateTemporalDateTime(..., *"iso8601"*).
|
||||
24. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _laterDateTime_).
|
||||
---*/
|
||||
|
||||
class SkippedDateTime extends Temporal.TimeZone {
|
||||
constructor() {
|
||||
super("UTC");
|
||||
this.calls = 0;
|
||||
}
|
||||
|
||||
getPossibleInstantsFor(dateTime) {
|
||||
// Calls occur in pairs. For the first one return no possible instants so
|
||||
// that DisambiguatePossibleInstants will call it again
|
||||
if (this.calls++ % 2 == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
assert.sameValue(
|
||||
dateTime.getISOFields().calendar,
|
||||
"iso8601",
|
||||
"getPossibleInstantsFor called with dateTime with built-in ISO 8601 calendar"
|
||||
);
|
||||
return super.getPossibleInstantsFor(dateTime);
|
||||
}
|
||||
}
|
||||
|
||||
const nonBuiltinISOCalendar = new Temporal.Calendar("iso8601");
|
||||
const timeZone = new SkippedDateTime();
|
||||
const relativeTo = { year: 2000, month: 5, day: 2, timeZone, calendar: nonBuiltinISOCalendar };
|
||||
|
||||
const instance = new Temporal.Duration(1, 0, 0, 1);
|
||||
instance.subtract(new Temporal.Duration(0, 0, 0, 0, 24), { relativeTo });
|
||||
|
||||
assert.sameValue(timeZone.calls, 6, "getPossibleInstantsFor should have been called 6 times");
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue