Implement Temporal.PlainDateTime.{ since, until }

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2025-10-20 20:49:19 +09:00 committed by Patrick Kim
commit fa3432f1d6
8 changed files with 158 additions and 164 deletions

View file

@ -722,6 +722,18 @@ static Value builtinTemporalPlainDateTimeSubtract(ExecutionState& state, Value t
return plainDateTime->addDurationToDateTime(state, TemporalPlainDateTimeObject::AddDurationToDateTimeOperation::Subtract, argv[0], argc > 1 ? argv[1] : Value());
}
static Value builtinTemporalPlainDateTimeSince(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINDATETIME(plainDateTime, Since);
return new TemporalDurationObject(state, plainDateTime->differenceTemporalPlainDateTime(state, TemporalPlainDateTimeObject::DifferenceTemporalPlainDateTime::Since, argv[0], argc > 1 ? argv[1] : Value()));
}
static Value builtinTemporalPlainDateTimeUntil(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
RESOLVE_THIS_BINDING_TO_PLAINDATETIME(plainDateTime, Until);
return new TemporalDurationObject(state, plainDateTime->differenceTemporalPlainDateTime(state, TemporalPlainDateTimeObject::DifferenceTemporalPlainDateTime::Until, argv[0], argc > 1 ? argv[1] : Value()));
}
static Value builtinTemporalPlainYearMonthConstructor(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
{
// If NewTarget is undefined, throw a TypeError exception.
@ -1291,6 +1303,9 @@ void GlobalObject::installTemporal(ExecutionState& state)
m_temporalPlainDateTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyWithCalendar()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyWithCalendar(), builtinTemporalPlainDateTimeWithCalendar, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainDateTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->add), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->add, builtinTemporalPlainDateTimeAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainDateTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySubtract()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySubtract(), builtinTemporalPlainDateTimeSubtract, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainDateTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazyUntil()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazyUntil(), builtinTemporalPlainDateTimeUntil, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_temporalPlainDateTimePrototype->directDefineOwnProperty(state, ObjectPropertyName(strings->lazySince()), ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(strings->lazySince(), builtinTemporalPlainDateTimeSince, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
{
AtomicString name(state.context(), "get calendarId");

View file

@ -2455,10 +2455,6 @@ static NudgeResult nudgeToDayOrTime(ExecutionState& state, ISO8601::InternalDura
auto nudgedEpochNs = diffTime + destEpochNs;
auto days = 0;
auto remainder = roundedTime;
if (largestUnit <= TemporalUnit::Day) {
days = roundedWholeDays;
remainder = roundedTime + Temporal::timeDurationFromComponents(-roundedWholeDays * 24, 0, 0, 0, 0, 0);
}
auto dateDuration = adjustDateDurationRecord(state, duration.dateDuration(), days, NullOption, NullOption);
auto resultDuration = ISO8601::InternalDuration::combineDateAndTimeDuration(dateDuration, remainder);
return NudgeResult(resultDuration, nudgedEpochNs, didExpandDays);
@ -2788,6 +2784,77 @@ ISO8601::Duration Temporal::adjustDateDurationRecord(ExecutionState& state, ISO8
return ISO8601::Duration({ dateDuration.years(), months.value(), weeks.value(), days });
}
ISO8601::InternalDuration Temporal::differencePlainDateTimeWithRounding(ExecutionState& state, ISO8601::PlainDateTime isoDateTime1, ISO8601::PlainDateTime isoDateTime2, Calendar calendar,
ISO8601::DateTimeUnit largestUnit, unsigned roundingIncrement, ISO8601::DateTimeUnit smallestUnit, ISO8601::RoundingMode roundingMode)
{
// If CompareISODateTime(isoDateTime1, isoDateTime2) = 0, then
if (isoDateTime1 == isoDateTime2) {
// Return CombineDateAndTimeDuration(ZeroDateDuration(), 0).
return ISO8601::InternalDuration();
}
// If ISODateTimeWithinLimits(isoDateTime1) is false or ISODateTimeWithinLimits(isoDateTime2) is false, throw a RangeError exception.
if (!ISO8601::isoDateTimeWithinLimits(isoDateTime1) || !ISO8601::isoDateTimeWithinLimits(isoDateTime2)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "date-time is out of range");
}
// Let diff be DifferenceISODateTime(isoDateTime1, isoDateTime2, calendar, largestUnit).
auto diff = differenceISODateTime(state, isoDateTime1, isoDateTime2, calendar, largestUnit);
// If smallestUnit is nanosecond and roundingIncrement = 1, return diff.
if (smallestUnit == ISO8601::DateTimeUnit::Nanosecond && roundingIncrement == 1) {
return diff;
}
// Let originEpochNs be GetUTCEpochNanoseconds(isoDateTime1).
auto originEpochNs = ISO8601::ExactTime::fromISOPartsAndOffset(isoDateTime1.plainDate().year(), isoDateTime1.plainDate().month(), isoDateTime1.plainDate().day(),
isoDateTime1.plainTime().hour(), isoDateTime1.plainTime().minute(), isoDateTime1.plainTime().second(), isoDateTime1.plainTime().millisecond(), isoDateTime1.plainTime().microsecond(),
isoDateTime1.plainTime().nanosecond(), 0)
.epochNanoseconds();
// Let destEpochNs be GetUTCEpochNanoseconds(isoDateTime2).
auto destEpochNs = ISO8601::ExactTime::fromISOPartsAndOffset(isoDateTime2.plainDate().year(), isoDateTime2.plainDate().month(), isoDateTime2.plainDate().day(),
isoDateTime2.plainTime().hour(), isoDateTime2.plainTime().minute(), isoDateTime2.plainTime().second(), isoDateTime2.plainTime().millisecond(), isoDateTime2.plainTime().microsecond(),
isoDateTime2.plainTime().nanosecond(), 0)
.epochNanoseconds();
// Return ? RoundRelativeDuration(diff, originEpochNs, destEpochNs, isoDateTime1, unset, calendar, largestUnit, roundingIncrement, smallestUnit, roundingMode).
return roundRelativeDuration(state, diff, destEpochNs, isoDateTime1, NullOption, calendar, toTemporalUnit(largestUnit), roundingIncrement, toTemporalUnit(smallestUnit), roundingMode);
}
// https://tc39.es/proposal-temporal/#sec-temporal-differenceisodatetime
ISO8601::InternalDuration Temporal::differenceISODateTime(ExecutionState& state, ISO8601::PlainDateTime isoDateTime1, ISO8601::PlainDateTime isoDateTime2, Calendar calendar, ISO8601::DateTimeUnit largestUnit)
{
// Let timeDuration be DifferenceTime(isoDateTime1.[[Time]], isoDateTime2.[[Time]]).
auto timeDuration = differenceTime(isoDateTime1.plainTime(), isoDateTime2.plainTime());
// Let timeSign be TimeDurationSign(timeDuration).
int timeSign = 0;
if (timeDuration < 0) {
timeSign = -1;
} else if (timeDuration > 0) {
timeSign = 1;
}
// Let dateSign be CompareISODate(isoDateTime1.[[ISODate]], isoDateTime2.[[ISODate]]).
auto dateSign = isoDateTime1.plainDate().compare(isoDateTime2.plainDate());
// Let adjustedDate be isoDateTime2.[[ISODate]].
ISO8601::PlainDate adjustedDate = isoDateTime2.plainDate();
// If timeSign = dateSign, then
if (timeSign == dateSign) {
// Set adjustedDate to BalanceISODate(adjustedDate.[[Year]], adjustedDate.[[Month]], adjustedDate.[[Day]] + timeSign).
adjustedDate = balanceISODate(state, adjustedDate.year(), adjustedDate.month(), adjustedDate.day() + timeSign);
// Set timeDuration to ! Add24HourDaysToTimeDuration(timeDuration, -timeSign).
timeDuration = add24HourDaysToTimeDuration(state, timeDuration, -timeSign);
}
// Let dateLargestUnit be LargerOfTwoTemporalUnits(day, largestUnit).
auto dateLargestUnit = largerOfTwoTemporalUnits(ISO8601::DateTimeUnit::Day, largestUnit);
// Let dateDifference be CalendarDateUntil(calendar, isoDateTime1.[[ISODate]], adjustedDate, dateLargestUnit).
auto dateDifference = calendarDateUntil(calendar, isoDateTime1.plainDate(), adjustedDate, toTemporalUnit(dateLargestUnit));
// If largestUnit is not dateLargestUnit, then
if (largestUnit != dateLargestUnit) {
// Set timeDuration to ! Add24HourDaysToTimeDuration(timeDuration, dateDifference.[[Days]]).
timeDuration = add24HourDaysToTimeDuration(state, timeDuration, dateDifference.days());
// Set dateDifference.[[Days]] to 0.
dateDifference.setDays(0);
}
// Return CombineDateAndTimeDuration(dateDifference, timeDuration).
return ISO8601::InternalDuration(dateDifference, timeDuration);
}
} // namespace Escargot
#endif

View file

@ -400,6 +400,13 @@ public:
// https://tc39.es/proposal-temporal/#sec-temporal-adjustdatedurationrecord
static ISO8601::Duration adjustDateDurationRecord(ExecutionState& state, ISO8601::Duration dateDuration, double days, Optional<double> weeks, Optional<double> months);
// https://tc39.es/proposal-temporal/#sec-temporal-differenceplaindatetimewithrounding
static ISO8601::InternalDuration differencePlainDateTimeWithRounding(ExecutionState& state, ISO8601::PlainDateTime isoDateTime1, ISO8601::PlainDateTime isoDateTime2, Calendar calendar,
ISO8601::DateTimeUnit largestUnit, unsigned roundingIncrement, ISO8601::DateTimeUnit smallestUnit, ISO8601::RoundingMode roundingMode);
// https://tc39.es/proposal-temporal/#sec-temporal-differenceisodatetime
static ISO8601::InternalDuration differenceISODateTime(ExecutionState& state, ISO8601::PlainDateTime isoDateTime1, ISO8601::PlainDateTime isoDateTime2, Calendar calendar, ISO8601::DateTimeUnit largestUnit);
};
} // namespace Escargot

View file

@ -293,6 +293,40 @@ TemporalPlainDateTimeObject* TemporalPlainDateTimeObject::addDurationToDateTime(
return new TemporalPlainDateTimeObject(state, state.context()->globalObject()->temporalPlainDateTimePrototype(),
addedDate.second, ISO8601::PlainTime(timeResult.hours(), timeResult.minutes(), timeResult.seconds(), timeResult.milliseconds(), timeResult.microseconds(), timeResult.nanoseconds()), calendarID());
}
ISO8601::Duration TemporalPlainDateTimeObject::differenceTemporalPlainDateTime(ExecutionState& state, DifferenceTemporalPlainDateTime operation, Value otherInput, Value options)
{
// Set other to ? ToTemporalDateTime(other).
auto other = Temporal::toTemporalDateTime(state, otherInput, options);
// If CalendarEquals(dateTime.[[Calendar]], other.[[Calendar]]) is false, throw a RangeError exception.
if (other->calendarID() != calendarID()) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, "other calendar is not same");
}
// Let resolvedOptions be ? GetOptionsObject(options).
auto resolvedOptions = Intl::getOptionsObject(state, options);
// Let settings be ? GetDifferenceSettings(operation, resolvedOptions, datetime, « », nanosecond, day).
auto settings = Temporal::getDifferenceSettings(state, operation == DifferenceTemporalPlainDateTime::Since, resolvedOptions, ISO8601::DateTimeUnitCategory::DateTime, nullptr, 0, TemporalUnit::Nanosecond, TemporalUnit::Day);
// If CompareISODateTime(dateTime.[[ISODateTime]], other.[[ISODateTime]]) = 0, then
auto isoDateTime1 = computeISODate(state);
auto isoDateTime2 = other->computeISODate(state);
if (isoDateTime1 == isoDateTime2 && plainTime() == other->plainTime()) {
// Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
return {};
}
// Let internalDuration be ? DifferencePlainDateTimeWithRounding(dateTime.[[ISODateTime]], other.[[ISODateTime]], dateTime.[[Calendar]], settings.[[LargestUnit]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
auto internalDuration = Temporal::differencePlainDateTimeWithRounding(state, ISO8601::PlainDateTime(isoDateTime1, plainTime()), ISO8601::PlainDateTime(isoDateTime2, other->plainTime()),
calendarID(), settings.largestUnit, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode);
// Let result be ! TemporalDurationFromInternal(internalDuration, settings.[[LargestUnit]]).
auto result = TemporalDurationObject::temporalDurationFromInternal(state, internalDuration, settings.largestUnit);
// If operation is since, set result to CreateNegatedTemporalDuration(result).
if (operation == DifferenceTemporalPlainDateTime::Since) {
result = TemporalDurationObject::createNegatedTemporalDuration(result);
}
// Return result.
return result;
}
} // namespace Escargot
#endif

View file

@ -49,6 +49,11 @@ public:
return m_plainDateTime->plainTime();
}
ISO8601::PlainDateTime plainDateTime() const
{
return *m_plainDateTime;
}
Calendar calendarID() const
{
return m_calendarID;
@ -121,6 +126,17 @@ public:
};
TemporalPlainDateTimeObject* addDurationToDateTime(ExecutionState& state, AddDurationToDateTimeOperation operation, Value temporalDurationLike, Value options);
// https://tc39.es/proposal-temporal/#sec-temporal-differenceplaindatetimewithrounding
ISO8601::InternalDuration differencePlainDateTimeWithRounding(ExecutionState& state, ISO8601::PlainDateTime isoDateTime1, ISO8601::PlainDateTime isoDateTime2, Calendar calendar,
ISO8601::DateTimeUnit largestUnit, unsigned roundingIncrement, ISO8601::DateTimeUnit smallestUnit, ISO8601::RoundingMode roundingMode);
// https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalplaindatetime
enum class DifferenceTemporalPlainDateTime {
Until,
Since
};
ISO8601::Duration differenceTemporalPlainDateTime(ExecutionState& state, DifferenceTemporalPlainDateTime operation, Value other, Value options);
private:
ISO8601::PlainDateTime* m_plainDateTime;
Calendar m_calendarID;

View file

@ -128,6 +128,13 @@ bool isoDateTimeWithinLimits(Int128 nanoseconds)
return true;
}
bool isoDateTimeWithinLimits(PlainDateTime t)
{
return isoDateTimeWithinLimits(ExactTime::fromISOPartsAndOffset(t.plainDate().year(), t.plainDate().month(), t.plainDate().day(),
t.plainTime().hour(), t.plainTime().minute(), t.plainTime().second(), t.plainTime().millisecond(), t.plainTime().microsecond(), t.plainTime().nanosecond(), 0)
.epochNanoseconds());
}
bool isValidEpochNanoseconds(Int128 s)
{
// If (epochNanoseconds) < nsMinInstant or (epochNanoseconds) > nsMaxInstant, then

View file

@ -466,7 +466,7 @@ public:
}
// https://tc39.es/proposal-temporal/#sec-temporal-compareisodate
int compare(const PlainDate& other)
int compare(const PlainDate& other) const
{
if (year() > other.year())
return 1;
@ -528,6 +528,11 @@ public:
return m_plainTime;
}
bool operator==(const PlainDateTime& other) const
{
return m_plainDate == other.plainDate() && m_plainTime == other.plainTime();
}
private:
PlainDate m_plainDate;
PlainTime m_plainTime;
@ -604,6 +609,8 @@ bool isoDateTimeWithinLimits(int32_t year, uint8_t month, uint8_t day);
// https://tc39.es/proposal-temporal/#sec-temporal-isodatetimewithinlimits
bool isDateTimeWithinLimits(int32_t year, uint8_t month, uint8_t day, unsigned hour, unsigned minute, unsigned second, unsigned millisecond, unsigned microsecond, unsigned nanosecond);
bool isoDateTimeWithinLimits(Int128 t);
bool isoDateTimeWithinLimits(PlainDateTime t);
// https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds
bool isValidEpochNanoseconds(Int128 s);
Optional<ISO8601::PlainDate> toPlainDate(const ISO8601::Duration& duration);

View file

@ -654,86 +654,11 @@
<test id="built-ins/Temporal/PlainDateTime/prototype/round/subclassing-ignored"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/round/throws-argument-object-insufficient-data"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-plaindate"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-case-insensitive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-invalid-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-propertybag-calendar-year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-limits"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-duration"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/no-unnecessary-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/options-empty"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/returns-days"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/round-negative-duration"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/round-relative-to-receiver"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-cleanly-divides"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-does-not-divide"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-halfexpand-default-changes"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-trunc-is-default"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/subseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/weeks-months-mutually-exclusive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/wrapping-at-end-of-month"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/since/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/toPlainDate/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/toPlainDate/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/toPlainDate/length"><reason>TODO</reason></test>
@ -778,89 +703,11 @@
<test id="built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/two-digit-year"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/toZonedDateTime/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-plaindate"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-case-insensitive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-invalid-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-iso-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-propertybag-calendar-year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-calendar-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-calendar-annotation-invalid-key"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-critical-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-date-with-utc-offset"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-limits"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-minus-sign"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-multiple-calendar"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-multiple-time-zone"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-time-separators"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-time-zone-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-unknown-annotation"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-string-with-utc-designator"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/argument-zoneddatetime-negative-epochnanoseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/balance"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-duration"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/balance-negative-time-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/branding"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/builtin"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/casts-argument"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/inverse"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/largestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/largestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/largestunit-smallestunit-mismatch"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/largestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/largestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/leap-second"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/length"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/name"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/not-a-constructor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/options-empty"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/options-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/prop-desc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/returns-days"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/round-cross-unit-boundary"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/round-negative-duration"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/round-relative-to-receiver"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-basic"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-cleanly-divides"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-does-not-divide"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-nan"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-non-integer"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-out-of-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingincrement-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-ceil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-expand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-floor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfCeil"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfEven"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfExpand"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfFloor"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfTrunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-halfexpand-default-changes"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-trunc"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-trunc-is-default"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/roundingmode-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-invalid-string"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-plurals-accepted"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-undefined"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/smallestunit-wrong-type"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/subseconds"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/throws-if-rounded-date-outside-valid-iso-range"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/units-changed"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/weeks-months-mutually-exclusive"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/wrapping-at-end-of-month"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/until/year-zero"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/with/calendar-temporal-object-throws"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/withCalendar/calendar-temporal-object"><reason>TODO</reason></test>
<test id="built-ins/Temporal/PlainDateTime/prototype/withPlainTime/argument-zoneddatetime-balance-negative-time-units"><reason>TODO</reason></test>
@ -1810,9 +1657,6 @@
<test id="intl402/Temporal/PlainDateTime/prototype/equals/calendar-checked"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/equals/canonicalize-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/equals/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/since/canonicalize-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/since/different-calendars-throws"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/since/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/toLocaleString/calendar-mismatch"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/toLocaleString/dateStyle-timeStyle-undefined"><reason>TODO</reason></test>
@ -1834,9 +1678,6 @@
<test id="intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/options-undefined"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/order-of-operations"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/toZonedDateTime/timezone-string-datetime"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/until/canonicalize-calendar"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/until/different-calendars-throws"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/until/infinity-throws-rangeerror"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainDateTime/prototype/with/non-iso-calendar-fields"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainMonthDay/from/calendar-not-supporting-eras"><reason>TODO</reason></test>
<test id="intl402/Temporal/PlainMonthDay/from/canonicalize-calendar"><reason>TODO</reason></test>