mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:58:11 +00:00
LibJS: Change internal slots of Duration to store mathematical values
This is a normative change in the Temporal spec.
See: 1f3fba8
This commit is contained in:
parent
cc8f5151d7
commit
b751f80166
4 changed files with 128 additions and 110 deletions
|
@ -174,9 +174,9 @@ JS_DEFINE_NATIVE_FUNCTION(CalendarPrototype::date_add)
|
|||
// 7. Let overflow be ? ToTemporalOverflow(options).
|
||||
auto overflow = TRY(to_temporal_overflow(global_object, options));
|
||||
|
||||
// 8. Let balanceResult be ! BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
|
||||
// 8. Let balanceResult be ? BalanceDuration(duration.[[Days]], duration.[[Hours]], duration.[[Minutes]], duration.[[Seconds]], duration.[[Milliseconds]], duration.[[Microseconds]], duration.[[Nanoseconds]], "day").
|
||||
// FIXME: Narrowing conversion from 'double' to 'i64'
|
||||
auto balance_result = MUST(balance_duration(global_object, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger::create_from(duration->nanoseconds()), "day"sv));
|
||||
auto balance_result = TRY(balance_duration(global_object, duration->days(), duration->hours(), duration->minutes(), duration->seconds(), duration->milliseconds(), duration->microseconds(), Crypto::SignedBigInteger::create_from(duration->nanoseconds()), "day"sv));
|
||||
|
||||
// 9. Let result be ? AddISODate(date.[[ISOYear]], date.[[ISOMonth]], date.[[ISODay]], duration.[[Years]], duration.[[Months]], duration.[[Weeks]], balanceResult.[[Days]], overflow).
|
||||
auto result = TRY(add_iso_date(global_object, date->iso_year(), date->iso_month(), date->iso_day(), duration->years(), duration->months(), duration->weeks(), balance_result.days, overflow));
|
||||
|
|
|
@ -35,6 +35,32 @@ Duration::Duration(double years, double months, double weeks, double days, doubl
|
|||
, m_microseconds(microseconds)
|
||||
, m_nanoseconds(nanoseconds)
|
||||
{
|
||||
auto fields = AK::Array {
|
||||
&Duration::m_years,
|
||||
&Duration::m_months,
|
||||
&Duration::m_weeks,
|
||||
&Duration::m_days,
|
||||
&Duration::m_hours,
|
||||
&Duration::m_minutes,
|
||||
&Duration::m_seconds,
|
||||
&Duration::m_milliseconds,
|
||||
&Duration::m_microseconds,
|
||||
&Duration::m_nanoseconds,
|
||||
};
|
||||
|
||||
// NOTE: The spec stores these fields as mathematical values. VERIFY() that we have finite,
|
||||
// integral values in them, and normalize any negative zeros caused by floating point math.
|
||||
// This is usually done using ℝ(𝔽(value)) at the call site.
|
||||
for (auto const& field : fields) {
|
||||
auto& value = this->*field;
|
||||
VERIFY(isfinite(value));
|
||||
// FIXME: test-js contains a small number of cases where a Temporal.Duration is constructed
|
||||
// with a non-integral double. Eliminate these and VERIFY(trunc(value) == value) instead.
|
||||
if (trunc(value) != value)
|
||||
value = trunc(value);
|
||||
else if (bit_cast<u64>(value) == NEGATIVE_ZERO_BITS)
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: All of these have two overloads: one that can throw, and one that can't.
|
||||
|
@ -47,7 +73,7 @@ DurationRecord create_duration_record(double years, double months, double weeks,
|
|||
// 1. If ! IsValidDuration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
|
||||
VERIFY(is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds));
|
||||
|
||||
// 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
|
||||
// 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
|
||||
return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds };
|
||||
}
|
||||
|
||||
|
@ -60,7 +86,7 @@ ThrowCompletionOr<DurationRecord> create_duration_record(GlobalObject& global_ob
|
|||
if (!is_valid_duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration);
|
||||
|
||||
// 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
|
||||
// 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
|
||||
return DurationRecord { .years = years, .months = months, .weeks = weeks, .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds };
|
||||
}
|
||||
|
||||
|
@ -70,7 +96,7 @@ DateDurationRecord create_date_duration_record(double years, double months, doub
|
|||
// 1. If ! IsValidDuration(years, months, weeks, days, 0, 0, 0, 0, 0, 0) is false, throw a RangeError exception.
|
||||
VERIFY(is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0));
|
||||
|
||||
// 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, }.
|
||||
// 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }.
|
||||
return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days };
|
||||
}
|
||||
|
||||
|
@ -83,7 +109,7 @@ ThrowCompletionOr<DateDurationRecord> create_date_duration_record(GlobalObject&
|
|||
if (!is_valid_duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration);
|
||||
|
||||
// 2. Return the Record { [[Years]]: years, [[Months]]: months, [[Weeks]]: weeks, [[Days]]: days, }.
|
||||
// 2. Return the Record { [[Years]]: ℝ(𝔽(years)), [[Months]]: ℝ(𝔽(months)), [[Weeks]]: ℝ(𝔽(weeks)), [[Days]]: ℝ(𝔽(days)) }.
|
||||
return DateDurationRecord { .years = years, .months = months, .weeks = weeks, .days = days };
|
||||
}
|
||||
|
||||
|
@ -93,7 +119,7 @@ TimeDurationRecord create_time_duration_record(double days, double hours, double
|
|||
// 1. If ! IsValidDuration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds) is false, throw a RangeError exception.
|
||||
VERIFY(is_valid_duration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds));
|
||||
|
||||
// 2. Return the Record { [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
|
||||
// 2. Return the Record { [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
|
||||
return TimeDurationRecord { .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds };
|
||||
}
|
||||
|
||||
|
@ -106,7 +132,7 @@ ThrowCompletionOr<TimeDurationRecord> create_time_duration_record(GlobalObject&
|
|||
if (!is_valid_duration(0, 0, 0, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds))
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDuration);
|
||||
|
||||
// 2. Return the Record { [[Days]]: days, [[Hours]]: hours, [[Minutes]]: minutes, [[Seconds]]: seconds, [[Milliseconds]]: milliseconds, [[Microseconds]]: microseconds, [[Nanoseconds]]: nanoseconds }.
|
||||
// 2. Return the Record { [[Days]]: ℝ(𝔽(days)), [[Hours]]: ℝ(𝔽(hours)), [[Minutes]]: ℝ(𝔽(minutes)), [[Seconds]]: ℝ(𝔽(seconds)), [[Milliseconds]]: ℝ(𝔽(milliseconds)), [[Microseconds]]: ℝ(𝔽(microseconds)), [[Nanoseconds]]: ℝ(𝔽(nanoseconds)) }.
|
||||
return TimeDurationRecord { .days = days, .hours = hours, .minutes = minutes, .seconds = seconds, .milliseconds = milliseconds, .microseconds = microseconds, .nanoseconds = nanoseconds };
|
||||
}
|
||||
|
||||
|
@ -171,11 +197,11 @@ ThrowCompletionOr<DurationRecord> to_temporal_duration_record(GlobalObject& glob
|
|||
// i. Set any to true.
|
||||
any = true;
|
||||
|
||||
// ii. Let val be 𝔽(? ToIntegerWithoutRounding(val)).
|
||||
value = Value(TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects())));
|
||||
// ii. Let val be ? ToIntegerWithoutRounding(val).
|
||||
auto value_integer = TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects()));
|
||||
|
||||
// iii. Set result's field whose name is the Field Name value of the current row to val.
|
||||
result.*field = value.as_double();
|
||||
result.*field = value_integer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,7 +247,7 @@ bool is_valid_duration(double years, double months, double weeks, double days, d
|
|||
|
||||
// 2. For each value v of « years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds », do
|
||||
for (auto& v : { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }) {
|
||||
// a. If v is not finite, return false.
|
||||
// a. If 𝔽(v) is not finite, return false.
|
||||
if (!isfinite(v))
|
||||
return false;
|
||||
|
||||
|
@ -310,11 +336,11 @@ ThrowCompletionOr<PartialDurationRecord> to_partial_duration(GlobalObject& globa
|
|||
// i. Set any to true.
|
||||
any = true;
|
||||
|
||||
// ii. Set value to 𝔽(? ToIntegerWithoutRounding(value)).
|
||||
value = Value(TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects())));
|
||||
// ii. Set value to ? ToIntegerWithoutRounding(value).
|
||||
auto value_integer = TRY(to_integer_without_rounding(global_object, value, ErrorType::TemporalInvalidDurationPropertyValueNonIntegral, property.as_string(), value.to_string_without_side_effects()));
|
||||
|
||||
// iii. Set result's field whose name is the Field Name value of the current row to value.
|
||||
result.*field = value.as_double();
|
||||
result.*field = value_integer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -342,16 +368,16 @@ ThrowCompletionOr<Duration*> create_temporal_duration(GlobalObject& global_objec
|
|||
new_target = global_object.temporal_duration_constructor();
|
||||
|
||||
// 3. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Duration.prototype%", « [[InitializedTemporalDuration]], [[Years]], [[Months]], [[Weeks]], [[Days]], [[Hours]], [[Minutes]], [[Seconds]], [[Milliseconds]], [[Microseconds]], [[Nanoseconds]] »).
|
||||
// 4. Set object.[[Years]] to years.
|
||||
// 5. Set object.[[Months]] to months.
|
||||
// 6. Set object.[[Weeks]] to weeks.
|
||||
// 7. Set object.[[Days]] to days.
|
||||
// 8. Set object.[[Hours]] to hours.
|
||||
// 9. Set object.[[Minutes]] to minutes.
|
||||
// 10. Set object.[[Seconds]] to seconds.
|
||||
// 11. Set object.[[Milliseconds]] to milliseconds.
|
||||
// 12. Set object.[[Microseconds]] to microseconds.
|
||||
// 13. Set object.[[Nanoseconds]] to nanoseconds.
|
||||
// 4. Set object.[[Years]] to ℝ(𝔽(years)).
|
||||
// 5. Set object.[[Months]] to ℝ(𝔽(months)).
|
||||
// 6. Set object.[[Weeks]] to ℝ(𝔽(weeks)).
|
||||
// 7. Set object.[[Days]] to ℝ(𝔽(days)).
|
||||
// 8. Set object.[[Hours]] to ℝ(𝔽(hours)).
|
||||
// 9. Set object.[[Minutes]] to ℝ(𝔽(minutes)).
|
||||
// 10. Set object.[[Seconds]] to ℝ(𝔽(seconds)).
|
||||
// 11. Set object.[[Milliseconds]] to ℝ(𝔽(milliseconds)).
|
||||
// 12. Set object.[[Microseconds]] to ℝ(𝔽(microseconds)).
|
||||
// 13. Set object.[[Nanoseconds]] to ℝ(𝔽(nanoseconds)).
|
||||
auto* object = TRY(ordinary_create_from_constructor<Duration>(global_object, *new_target, &GlobalObject::temporal_duration_prototype, years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds));
|
||||
|
||||
// 14. Return object.
|
||||
|
@ -398,28 +424,27 @@ Crypto::SignedBigInteger total_duration_nanoseconds(double days, double hours, d
|
|||
{
|
||||
VERIFY(offset_shift == trunc(offset_shift));
|
||||
|
||||
// 1. Set nanoseconds to ℝ(nanoseconds).
|
||||
auto result_nanoseconds = nanoseconds;
|
||||
|
||||
// TODO: Add a way to create SignedBigIntegers from doubles with full precision and remove this restriction
|
||||
VERIFY(AK::is_within_range<i64>(days) && AK::is_within_range<i64>(hours) && AK::is_within_range<i64>(minutes) && AK::is_within_range<i64>(seconds) && AK::is_within_range<i64>(milliseconds) && AK::is_within_range<i64>(microseconds));
|
||||
|
||||
// 2. If days ≠ 0, then
|
||||
// 1. If days ≠ 0, then
|
||||
if (days != 0) {
|
||||
// a. Set nanoseconds to nanoseconds - offsetShift.
|
||||
result_nanoseconds = result_nanoseconds.minus(Crypto::SignedBigInteger::create_from(offset_shift));
|
||||
}
|
||||
// 3. Set hours to ℝ(hours) + ℝ(days) × 24.
|
||||
// 2. Set hours to hours + days × 24.
|
||||
auto total_hours = Crypto::SignedBigInteger::create_from(hours).plus(Crypto::SignedBigInteger::create_from(days).multiplied_by(Crypto::UnsignedBigInteger(24)));
|
||||
// 4. Set minutes to ℝ(minutes) + hours × 60.
|
||||
// 3. Set minutes to minutes + hours × 60.
|
||||
auto total_minutes = Crypto::SignedBigInteger::create_from(minutes).plus(total_hours.multiplied_by(Crypto::UnsignedBigInteger(60)));
|
||||
// 5. Set seconds to ℝ(seconds) + minutes × 60.
|
||||
// 4. Set seconds to seconds + minutes × 60.
|
||||
auto total_seconds = Crypto::SignedBigInteger::create_from(seconds).plus(total_minutes.multiplied_by(Crypto::UnsignedBigInteger(60)));
|
||||
// 6. Set milliseconds to ℝ(milliseconds) + seconds × 1000.
|
||||
// 5. Set milliseconds to milliseconds + seconds × 1000.
|
||||
auto total_milliseconds = Crypto::SignedBigInteger::create_from(milliseconds).plus(total_seconds.multiplied_by(Crypto::UnsignedBigInteger(1000)));
|
||||
// 7. Set microseconds to ℝ(microseconds) + milliseconds × 1000.
|
||||
// 6. Set microseconds to microseconds + milliseconds × 1000.
|
||||
auto total_microseconds = Crypto::SignedBigInteger::create_from(microseconds).plus(total_milliseconds.multiplied_by(Crypto::UnsignedBigInteger(1000)));
|
||||
// 8. Return nanoseconds + microseconds × 1000.
|
||||
// 7. Return nanoseconds + microseconds × 1000.
|
||||
return result_nanoseconds.plus(total_microseconds.multiplied_by(Crypto::UnsignedBigInteger(1000)));
|
||||
}
|
||||
|
||||
|
@ -560,7 +585,7 @@ ThrowCompletionOr<TimeDurationRecord> balance_duration(GlobalObject& global_obje
|
|||
// a. Assert: largestUnit is "nanosecond".
|
||||
VERIFY(largest_unit == "nanosecond"sv);
|
||||
}
|
||||
// 15. Return ! CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
|
||||
// 15. Return ? CreateTimeDurationRecord(days, hours × sign, minutes × sign, seconds × sign, milliseconds × sign, microseconds × sign, nanoseconds × sign).
|
||||
return create_time_duration_record(days, hours * sign, minutes * sign, seconds * sign, milliseconds * sign, microseconds * sign, result_nanoseconds * sign);
|
||||
}
|
||||
|
||||
|
@ -976,12 +1001,12 @@ ThrowCompletionOr<DurationRecord> add_duration(GlobalObject& global_object, doub
|
|||
return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalMissingStartingPoint, "year, month or week");
|
||||
}
|
||||
|
||||
// b. Let result be ! BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
// b. Let result be ? BalanceDuration(d1 + d2, h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
// FIXME: Narrowing conversion from 'double' to 'i64'
|
||||
auto result = MUST(balance_duration(global_object, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit));
|
||||
auto result = TRY(balance_duration(global_object, days1 + days2, hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit));
|
||||
|
||||
// c. Return ? CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return create_duration_record(global_object, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds);
|
||||
// c. Return ! CreateDurationRecord(0, 0, 0, result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return MUST(create_duration_record(global_object, 0, 0, 0, result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
}
|
||||
|
||||
// 5. If relativeTo has an [[InitializedTemporalDate]] internal slot, then
|
||||
|
@ -1018,12 +1043,12 @@ ThrowCompletionOr<DurationRecord> add_duration(GlobalObject& global_object, doub
|
|||
// j. Let dateDifference be ? CalendarDateUntil(calendar, relativeTo, end, differenceOptions).
|
||||
auto* date_difference = TRY(calendar_date_until(global_object, calendar, &relative_to, end, *difference_options));
|
||||
|
||||
// k. Let result be ! BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
// k. Let result be ? BalanceDuration(dateDifference.[[Days]], h1 + h2, min1 + min2, s1 + s2, ms1 + ms2, mus1 + mus2, ns1 + ns2, largestUnit).
|
||||
// FIXME: Narrowing conversion from 'double' to 'i64'
|
||||
auto result = MUST(balance_duration(global_object, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit));
|
||||
auto result = TRY(balance_duration(global_object, date_difference->days(), hours1 + hours2, minutes1 + minutes2, seconds1 + seconds2, milliseconds1 + milliseconds2, microseconds1 + microseconds2, Crypto::SignedBigInteger::create_from(nanoseconds1 + nanoseconds2), largest_unit));
|
||||
|
||||
// l. Return ? CreateDurationRecord(dateDifference.[[Years]], dateDifference.[[Months]], dateDifference.[[Weeks]], result.[[Days]], result.[[Hours]], result.[[Minutes]], result.[[Seconds]], result.[[Milliseconds]], result.[[Microseconds]], result.[[Nanoseconds]]).
|
||||
return create_duration_record(global_object, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds);
|
||||
return MUST(create_duration_record(global_object, date_difference->years(), date_difference->months(), date_difference->weeks(), result.days, result.hours, result.minutes, result.seconds, result.milliseconds, result.microseconds, result.nanoseconds));
|
||||
}
|
||||
|
||||
// 6. Assert: relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot.
|
||||
|
@ -1093,21 +1118,19 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
// spec is concerned, but the latter is more strictly typed for convenience.
|
||||
PlainDate* relative_to = nullptr;
|
||||
|
||||
// 2. Let years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, and increment each be the mathematical values of themselves.
|
||||
|
||||
// FIXME: assuming "smallestUnit" as the option name here leads to confusing error messages in some cases:
|
||||
// > new Temporal.Duration().total({ unit: "month" })
|
||||
// Uncaught exception: [RangeError] month is not a valid value for option smallestUnit
|
||||
// 3. If unit is "year", "month", or "week", and relativeTo is undefined, then
|
||||
// 2. If unit is "year", "month", or "week", and relativeTo is undefined, then
|
||||
if (unit.is_one_of("year"sv, "month"sv, "week"sv) && !relative_to_object) {
|
||||
// a. Throw a RangeError exception.
|
||||
return vm.throw_completion<RangeError>(global_object, ErrorType::OptionIsNotValidValue, unit, "smallestUnit"sv);
|
||||
}
|
||||
|
||||
// 4. Let zonedRelativeTo be undefined.
|
||||
// 3. Let zonedRelativeTo be undefined.
|
||||
ZonedDateTime* zoned_relative_to = nullptr;
|
||||
|
||||
// 5. If relativeTo is not undefined, then
|
||||
// 4. If relativeTo is not undefined, then
|
||||
if (relative_to_object) {
|
||||
// a. If relativeTo has an [[InitializedTemporalZonedDateTime]] internal slot, then
|
||||
if (is<ZonedDateTime>(relative_to_object)) {
|
||||
|
@ -1130,10 +1153,10 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
// c. Let calendar be relativeTo.[[Calendar]].
|
||||
calendar = &relative_to->calendar();
|
||||
}
|
||||
// 6. Else,
|
||||
// 5. Else,
|
||||
// a. NOTE: calendar will not be used below.
|
||||
|
||||
// 7. If unit is one of "year", "month", "week", or "day", then
|
||||
// 6. If unit is one of "year", "month", "week", or "day", then
|
||||
if (unit.is_one_of("year"sv, "month"sv, "week"sv, "day"sv)) {
|
||||
// a. Let nanoseconds be ! TotalDurationNanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0).
|
||||
auto nanoseconds_bigint = total_duration_nanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, Crypto::SignedBigInteger::create_from((i64)nanoseconds), 0);
|
||||
|
@ -1162,16 +1185,16 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
microseconds = 0;
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 8. Else,
|
||||
// 7. Else,
|
||||
else {
|
||||
// a. Let fractionalSeconds be nanoseconds × 10^-9 + microseconds × 10^-6 + milliseconds × 10^-3 + seconds.
|
||||
fractional_seconds = nanoseconds * 0.000000001 + microseconds * 0.000001 + milliseconds * 0.001 + seconds;
|
||||
}
|
||||
|
||||
// 9. Let remainder be undefined.
|
||||
// 8. Let remainder be undefined.
|
||||
double remainder = 0;
|
||||
|
||||
// 10. If unit is "year", then
|
||||
// 9. If unit is "year", then
|
||||
if (unit == "year"sv) {
|
||||
VERIFY(relative_to);
|
||||
|
||||
|
@ -1261,7 +1284,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
weeks = 0;
|
||||
days = 0;
|
||||
}
|
||||
// 11. Else if unit is "month", then
|
||||
// 10. Else if unit is "month", then
|
||||
else if (unit == "month"sv) {
|
||||
VERIFY(relative_to);
|
||||
|
||||
|
@ -1335,7 +1358,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
weeks = 0;
|
||||
days = 0;
|
||||
}
|
||||
// 12. Else if unit is "week", then
|
||||
// 11. Else if unit is "week", then
|
||||
else if (unit == "week"sv) {
|
||||
VERIFY(relative_to);
|
||||
|
||||
|
@ -1384,7 +1407,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
// j. Set days to 0.
|
||||
days = 0;
|
||||
}
|
||||
// 13. Else if unit is "day", then
|
||||
// 12. Else if unit is "day", then
|
||||
else if (unit == "day"sv) {
|
||||
// a. Let fractionalDays be days.
|
||||
auto fractional_days = days;
|
||||
|
@ -1395,7 +1418,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
// c. Set remainder to fractionalDays - days.
|
||||
remainder = fractional_days - days;
|
||||
}
|
||||
// 14. Else if unit is "hour", then
|
||||
// 13. Else if unit is "hour", then
|
||||
else if (unit == "hour"sv) {
|
||||
// a. Let fractionalHours be (fractionalSeconds / 60 + minutes) / 60 + hours.
|
||||
auto fractional_hours = (fractional_seconds / 60 + minutes) / 60 + hours;
|
||||
|
@ -1413,7 +1436,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
microseconds = 0;
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 15. Else if unit is "minute", then
|
||||
// 14. Else if unit is "minute", then
|
||||
else if (unit == "minute"sv) {
|
||||
// a. Let fractionalMinutes be fractionalSeconds / 60 + minutes.
|
||||
auto fractional_minutes = fractional_seconds / 60 + minutes;
|
||||
|
@ -1430,7 +1453,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
microseconds = 0;
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 16. Else if unit is "second", then
|
||||
// 15. Else if unit is "second", then
|
||||
else if (unit == "second"sv) {
|
||||
// a. Set seconds to ! RoundNumberToIncrement(fractionalSeconds, increment, roundingMode).
|
||||
seconds = (double)round_number_to_increment(fractional_seconds, increment, rounding_mode);
|
||||
|
@ -1443,7 +1466,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
microseconds = 0;
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 17. Else if unit is "millisecond", then
|
||||
// 16. Else if unit is "millisecond", then
|
||||
else if (unit == "millisecond"sv) {
|
||||
// a. Let fractionalMilliseconds be nanoseconds × 10^-6 + microseconds × 10^-3 + milliseconds.
|
||||
auto fractional_milliseconds = nanoseconds * 0.000001 + microseconds * 0.001 + milliseconds;
|
||||
|
@ -1458,7 +1481,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
microseconds = 0;
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 18. Else if unit is "microsecond", then
|
||||
// 17. Else if unit is "microsecond", then
|
||||
else if (unit == "microsecond"sv) {
|
||||
// a. Let fractionalMicroseconds be nanoseconds × 10^-3 + microseconds.
|
||||
auto fractional_microseconds = nanoseconds * 0.001 + microseconds;
|
||||
|
@ -1472,7 +1495,7 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
// d. Set nanoseconds to 0.
|
||||
nanoseconds = 0;
|
||||
}
|
||||
// 19. Else,
|
||||
// 18. Else,
|
||||
else {
|
||||
// a. Assert: unit is "nanosecond".
|
||||
VERIFY(unit == "nanosecond"sv);
|
||||
|
@ -1487,10 +1510,10 @@ ThrowCompletionOr<RoundedDuration> round_duration(GlobalObject& global_object, d
|
|||
remainder -= nanoseconds;
|
||||
}
|
||||
|
||||
// 20. Let duration be ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||||
// 19. Let duration be ! CreateDurationRecord(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||||
auto duration = create_duration_record(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
|
||||
|
||||
// 21. Return the Record { [[DurationRecord]]: duration, [[Remainder]]: remainder }.
|
||||
// 20. Return the Record { [[DurationRecord]]: duration, [[Remainder]]: remainder }.
|
||||
return RoundedDuration { .duration_record = duration, .remainder = remainder };
|
||||
}
|
||||
|
||||
|
@ -1582,81 +1605,76 @@ String temporal_duration_to_string(double years, double months, double weeks, do
|
|||
if (precision.has<StringView>())
|
||||
VERIFY(precision.get<StringView>() == "auto"sv);
|
||||
|
||||
// 1. Set seconds to the mathematical value of seconds.
|
||||
// 2. Set milliseconds to the mathematical value of milliseconds.
|
||||
// 3. Set microseconds to the mathematical value of microseconds.
|
||||
// 4. Set nanoseconds to the mathematical value of nanoseconds.
|
||||
|
||||
// 5. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||||
// 1. Let sign be ! DurationSign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds).
|
||||
auto sign = duration_sign(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
|
||||
|
||||
// 6. Set microseconds to microseconds + RoundTowardsZero(nanoseconds / 1000).
|
||||
// 2. Set microseconds to microseconds + RoundTowardsZero(nanoseconds / 1000).
|
||||
microseconds += trunc(nanoseconds / 1000);
|
||||
|
||||
// 7. Set nanoseconds to remainder(nanoseconds, 1000).
|
||||
// 3. Set nanoseconds to remainder(nanoseconds, 1000).
|
||||
nanoseconds = fmod(nanoseconds, 1000);
|
||||
|
||||
// 8. Set milliseconds to milliseconds + RoundTowardsZero(microseconds / 1000).
|
||||
// 4. Set milliseconds to milliseconds + RoundTowardsZero(microseconds / 1000).
|
||||
milliseconds += trunc(microseconds / 1000);
|
||||
|
||||
// 9. Set microseconds to remainder(microseconds, 1000).
|
||||
// 5. Set microseconds to remainder(microseconds, 1000).
|
||||
microseconds = fmod(microseconds, 1000);
|
||||
|
||||
// 10. Set seconds to seconds + RoundTowardsZero(milliseconds / 1000).
|
||||
// 6. Set seconds to seconds + RoundTowardsZero(milliseconds / 1000).
|
||||
seconds += trunc(milliseconds / 1000);
|
||||
|
||||
// 11. Set milliseconds to remainder(milliseconds, 1000).
|
||||
// 7. Set milliseconds to remainder(milliseconds, 1000).
|
||||
milliseconds = fmod(milliseconds, 1000);
|
||||
|
||||
// 12. Let datePart be "".
|
||||
// 8. Let datePart be "".
|
||||
StringBuilder date_part;
|
||||
|
||||
// 13. If years is not 0, then
|
||||
// 9. If years is not 0, then
|
||||
if (years != 0) {
|
||||
// a. Set datePart to the string concatenation of abs(years) formatted as a decimal number and the code unit 0x0059 (LATIN CAPITAL LETTER Y).
|
||||
date_part.appendff("{}", fabs(years));
|
||||
date_part.append('Y');
|
||||
}
|
||||
|
||||
// 14. If months is not 0, then
|
||||
// 10. If months is not 0, then
|
||||
if (months != 0) {
|
||||
// a. Set datePart to the string concatenation of datePart, abs(months) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
|
||||
date_part.appendff("{}", fabs(months));
|
||||
date_part.append('M');
|
||||
}
|
||||
|
||||
// 15. If weeks is not 0, then
|
||||
// 11. If weeks is not 0, then
|
||||
if (weeks != 0) {
|
||||
// a. Set datePart to the string concatenation of datePart, abs(weeks) formatted as a decimal number, and the code unit 0x0057 (LATIN CAPITAL LETTER W).
|
||||
date_part.appendff("{}", fabs(weeks));
|
||||
date_part.append('W');
|
||||
}
|
||||
|
||||
// 16. If days is not 0, then
|
||||
// 12. If days is not 0, then
|
||||
if (days != 0) {
|
||||
// a. Set datePart to the string concatenation of datePart, abs(days) formatted as a decimal number, and the code unit 0x0044 (LATIN CAPITAL LETTER D).
|
||||
date_part.appendff("{}", fabs(days));
|
||||
date_part.append('D');
|
||||
}
|
||||
|
||||
// 17. Let timePart be "".
|
||||
// 13. Let timePart be "".
|
||||
StringBuilder time_part;
|
||||
|
||||
// 18. If hours is not 0, then
|
||||
// 14. If hours is not 0, then
|
||||
if (hours != 0) {
|
||||
// a. Set timePart to the string concatenation of abs(hours) formatted as a decimal number and the code unit 0x0048 (LATIN CAPITAL LETTER H).
|
||||
time_part.appendff("{}", fabs(hours));
|
||||
time_part.append('H');
|
||||
}
|
||||
|
||||
// 19. If minutes is not 0, then
|
||||
// 15. If minutes is not 0, then
|
||||
if (minutes != 0) {
|
||||
// a. Set timePart to the string concatenation of timePart, abs(minutes) formatted as a decimal number, and the code unit 0x004D (LATIN CAPITAL LETTER M).
|
||||
time_part.appendff("{}", fabs(minutes));
|
||||
time_part.append('M');
|
||||
}
|
||||
|
||||
// 20. If any of seconds, milliseconds, microseconds, and nanoseconds are not 0; or years, months, weeks, days, hours, and minutes are all 0; or precision is not "auto"; then
|
||||
// 16. If any of seconds, milliseconds, microseconds, and nanoseconds are not 0; or years, months, weeks, days, hours, and minutes are all 0; or precision is not "auto"; then
|
||||
if ((seconds != 0 || milliseconds != 0 || microseconds != 0 || nanoseconds != 0) || (years == 0 && months == 0 && weeks == 0 && days == 0 && hours == 0 && minutes == 0) || (!precision.has<StringView>() || precision.get<StringView>() != "auto"sv)) {
|
||||
// a. Let fraction be abs(milliseconds) × 10^6 + abs(microseconds) × 10^3 + abs(nanoseconds).
|
||||
auto fraction = fabs(milliseconds) * 1'000'000 + fabs(microseconds) * 1'000 + fabs(nanoseconds);
|
||||
|
@ -1699,23 +1717,23 @@ String temporal_duration_to_string(double years, double months, double weeks, do
|
|||
time_part.append('S');
|
||||
}
|
||||
|
||||
// 21. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
|
||||
// 17. Let signPart be the code unit 0x002D (HYPHEN-MINUS) if sign < 0, and otherwise the empty String.
|
||||
auto sign_part = sign < 0 ? "-"sv : ""sv;
|
||||
|
||||
// 22. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
|
||||
// 18. Let result be the string concatenation of signPart, the code unit 0x0050 (LATIN CAPITAL LETTER P) and datePart.
|
||||
StringBuilder result;
|
||||
result.append(sign_part);
|
||||
result.append('P');
|
||||
result.append(date_part.string_view());
|
||||
|
||||
// 23. If timePart is not "", then
|
||||
// 19. If timePart is not "", then
|
||||
if (!time_part.is_empty()) {
|
||||
// a. Set result to the string concatenation of result, the code unit 0x0054 (LATIN CAPITAL LETTER T), and timePart.
|
||||
result.append('T');
|
||||
result.append(time_part.string_view());
|
||||
}
|
||||
|
||||
// 24. Return result.
|
||||
// 20. Return result.
|
||||
return result.to_string();
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::years_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Years]].
|
||||
// 3. Return 𝔽(duration.[[Years]]).
|
||||
return Value(duration->years());
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::months_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Months]].
|
||||
// 3. Return 𝔽(duration.[[Months]]).
|
||||
return Value(duration->months());
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::weeks_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Weeks]].
|
||||
// 3. Return 𝔽(duration.[[Weeks]]).
|
||||
return Value(duration->weeks());
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::days_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Days]].
|
||||
// 3. Return 𝔽(duration.[[Days]]).
|
||||
return Value(duration->days());
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::hours_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Hours]].
|
||||
// 3. Return 𝔽(duration.[[Hours]]).
|
||||
return Value(duration->hours());
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::minutes_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Minutes]].
|
||||
// 3. Return 𝔽(duration.[[Minutes]]).
|
||||
return Value(duration->minutes());
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::seconds_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Seconds]].
|
||||
// 3. Return 𝔽(duration.[[Seconds]]).
|
||||
return Value(duration->seconds());
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::milliseconds_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Milliseconds]].
|
||||
// 3. Return 𝔽(duration.[[Milliseconds]]).
|
||||
return Value(duration->milliseconds());
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::microseconds_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Microseconds]].
|
||||
// 3. Return 𝔽(duration.[[Microseconds]]).
|
||||
return Value(duration->microseconds());
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationPrototype::nanoseconds_getter)
|
|||
// 2. Perform ? RequireInternalSlot(duration, [[InitializedTemporalDuration]]).
|
||||
auto* duration = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. Return duration.[[Nanoseconds]].
|
||||
// 3. Return 𝔽(duration.[[Nanoseconds]]).
|
||||
return Value(duration->nanoseconds());
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ describe("correct behavior", () => {
|
|||
const dateTwo = new Temporal.PlainDate(2022, 12, 25);
|
||||
const sinceDuration = dateTwo.since(dateOne);
|
||||
|
||||
expect(sinceDuration.years).toBe(-0);
|
||||
expect(sinceDuration.months).toBe(-0);
|
||||
expect(sinceDuration.weeks).toBe(-0);
|
||||
expect(sinceDuration.years).toBe(0);
|
||||
expect(sinceDuration.months).toBe(0);
|
||||
expect(sinceDuration.weeks).toBe(0);
|
||||
expect(sinceDuration.days).toBe(406);
|
||||
expect(sinceDuration.hours).toBe(0);
|
||||
expect(sinceDuration.minutes).toBe(0);
|
||||
|
@ -30,10 +30,10 @@ describe("correct behavior", () => {
|
|||
const equalDateTwo = new Temporal.PlainDate(1, 1, 1);
|
||||
|
||||
const checkResults = result => {
|
||||
expect(result.years).toBe(-0);
|
||||
expect(result.months).toBe(-0);
|
||||
expect(result.weeks).toBe(-0);
|
||||
expect(result.days).toBe(-0);
|
||||
expect(result.years).toBe(0);
|
||||
expect(result.months).toBe(0);
|
||||
expect(result.weeks).toBe(0);
|
||||
expect(result.days).toBe(0);
|
||||
expect(result.hours).toBe(0);
|
||||
expect(result.minutes).toBe(0);
|
||||
expect(result.seconds).toBe(0);
|
||||
|
@ -53,9 +53,9 @@ describe("correct behavior", () => {
|
|||
const dateTwo = new Temporal.PlainDate(2022, 12, 25);
|
||||
const sinceDuration = dateOne.since(dateTwo);
|
||||
|
||||
expect(sinceDuration.years).toBe(-0);
|
||||
expect(sinceDuration.months).toBe(-0);
|
||||
expect(sinceDuration.weeks).toBe(-0);
|
||||
expect(sinceDuration.years).toBe(0);
|
||||
expect(sinceDuration.months).toBe(0);
|
||||
expect(sinceDuration.weeks).toBe(0);
|
||||
expect(sinceDuration.days).toBe(-406);
|
||||
expect(sinceDuration.hours).toBe(0);
|
||||
expect(sinceDuration.minutes).toBe(0);
|
||||
|
@ -106,9 +106,9 @@ describe("correct behavior", () => {
|
|||
const dateTwo = new Temporal.PlainDate(2022, 12, 25);
|
||||
const sinceDuration = dateTwo.since("2021-11-14");
|
||||
|
||||
expect(sinceDuration.years).toBe(-0);
|
||||
expect(sinceDuration.months).toBe(-0);
|
||||
expect(sinceDuration.weeks).toBe(-0);
|
||||
expect(sinceDuration.years).toBe(0);
|
||||
expect(sinceDuration.months).toBe(0);
|
||||
expect(sinceDuration.weeks).toBe(0);
|
||||
expect(sinceDuration.days).toBe(406);
|
||||
expect(sinceDuration.hours).toBe(0);
|
||||
expect(sinceDuration.minutes).toBe(0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue