2021-07-07 17:41:37 +01:00
/*
2023-01-26 15:48:03 +00:00
* Copyright ( c ) 2021 - 2023 , Linus Groh < linusg @ serenityos . org >
2021-07-11 21:04:11 +03:00
* Copyright ( c ) 2021 , Idan Horowitz < idan . horowitz @ serenityos . org >
2021-07-07 17:41:37 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-11-23 13:41:50 +01:00
# include <AK/TypeCasts.h>
2021-08-31 00:15:36 +01:00
# include <AK/Variant.h>
2021-07-07 17:41:37 +01:00
# include <LibCrypto/BigInt/SignedBigInteger.h>
# include <LibJS/Runtime/AbstractOperations.h>
2021-09-16 22:32:37 +01:00
# include <LibJS/Runtime/Completion.h>
2022-10-14 09:47:17 -04:00
# include <LibJS/Runtime/Date.h>
2021-07-07 17:41:37 +01:00
# include <LibJS/Runtime/GlobalObject.h>
2021-07-11 21:04:11 +03:00
# include <LibJS/Runtime/Temporal/AbstractOperations.h>
2021-08-31 00:15:36 +01:00
# include <LibJS/Runtime/Temporal/Calendar.h>
2021-07-07 17:41:37 +01:00
# include <LibJS/Runtime/Temporal/Instant.h>
# include <LibJS/Runtime/Temporal/InstantConstructor.h>
2021-07-11 21:04:11 +03:00
# include <LibJS/Runtime/Temporal/PlainDateTime.h>
# include <LibJS/Runtime/Temporal/TimeZone.h>
2021-08-01 17:58:08 +01:00
# include <LibJS/Runtime/Temporal/ZonedDateTime.h>
2021-07-07 17:41:37 +01:00
namespace JS : : Temporal {
// 8 Temporal.Instant Objects, https://tc39.es/proposal-temporal/#sec-temporal-instant-objects
2021-09-09 21:18:08 +01:00
Instant : : Instant ( BigInt const & nanoseconds , Object & prototype )
2022-12-14 12:17:58 +01:00
: Object ( ConstructWithPrototypeTag : : Tag , prototype )
2021-07-07 17:41:37 +01:00
, m_nanoseconds ( nanoseconds )
{
}
void Instant : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( & m_nanoseconds ) ;
}
// 8.5.1 IsValidEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds
bool is_valid_epoch_nanoseconds ( BigInt const & epoch_nanoseconds )
2022-10-14 09:47:17 -04:00
{
return is_valid_epoch_nanoseconds ( epoch_nanoseconds . big_integer ( ) ) ;
}
// 8.5.1 IsValidEpochNanoseconds ( epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidepochnanoseconds
bool is_valid_epoch_nanoseconds ( Crypto : : SignedBigInteger const & epoch_nanoseconds )
2021-07-07 17:41:37 +01:00
{
// 1. Assert: Type(epochNanoseconds) is BigInt.
2022-05-06 19:28:56 +02:00
// 2. If ℝ (epochNanoseconds) < nsMinInstant or ℝ (epochNanoseconds) > nsMaxInstant, then
2022-10-14 09:47:17 -04:00
if ( epoch_nanoseconds < ns_min_instant | | epoch_nanoseconds > ns_max_instant ) {
2021-07-07 17:41:37 +01:00
// a. Return false.
return false ;
}
// 3. Return true.
return true ;
}
// 8.5.2 CreateTemporalInstant ( epochNanoseconds [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporalinstant
2022-08-20 08:52:42 +01:00
ThrowCompletionOr < Instant * > create_temporal_instant ( VM & vm , BigInt const & epoch_nanoseconds , FunctionObject const * new_target )
2021-07-07 17:41:37 +01:00
{
2022-08-20 08:52:42 +01:00
auto & realm = * vm . current_realm ( ) ;
2021-07-07 17:41:37 +01:00
// 1. Assert: Type(epochNanoseconds) is BigInt.
// 2. Assert: ! IsValidEpochNanoseconds(epochNanoseconds) is true.
VERIFY ( is_valid_epoch_nanoseconds ( epoch_nanoseconds ) ) ;
2022-03-10 17:04:46 +01:00
// 3. If newTarget is not present, set newTarget to %Temporal.Instant%.
2021-07-07 17:41:37 +01:00
if ( ! new_target )
2022-08-27 00:54:55 +01:00
new_target = realm . intrinsics ( ) . temporal_instant_constructor ( ) ;
2021-07-07 17:41:37 +01:00
// 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.Instant.prototype%", « [[InitializedTemporalInstant]], [[Nanoseconds]] »).
// 5. Set object.[[Nanoseconds]] to epochNanoseconds.
2022-12-14 18:34:32 +00:00
auto object = TRY ( ordinary_create_from_constructor < Instant > ( vm , * new_target , & Intrinsics : : temporal_instant_prototype , epoch_nanoseconds ) ) ;
2021-07-07 17:41:37 +01:00
// 6. Return object.
2022-12-14 18:34:32 +00:00
return object . ptr ( ) ;
2021-07-07 17:41:37 +01:00
}
2021-07-11 21:04:11 +03:00
// 8.5.3 ToTemporalInstant ( item ), https://tc39.es/proposal-temporal/#sec-temporal-totemporalinstant
2022-08-20 08:52:42 +01:00
ThrowCompletionOr < Instant * > to_temporal_instant ( VM & vm , Value item )
2021-07-11 21:04:11 +03:00
{
// 1. If Type(item) is Object, then
if ( item . is_object ( ) ) {
// a. If item has an [[InitializedTemporalInstant]] internal slot, then
if ( is < Instant > ( item . as_object ( ) ) ) {
// i. Return item.
return & static_cast < Instant & > ( item . as_object ( ) ) ;
}
2021-08-01 17:58:08 +01:00
2021-07-11 21:04:11 +03:00
// b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then
2021-08-01 17:58:08 +01:00
if ( is < ZonedDateTime > ( item . as_object ( ) ) ) {
auto & zoned_date_time = static_cast < ZonedDateTime & > ( item . as_object ( ) ) ;
// i. Return ! CreateTemporalInstant(item.[[Nanoseconds]]).
2022-08-20 08:52:42 +01:00
return create_temporal_instant ( vm , zoned_date_time . nanoseconds ( ) ) ;
2021-08-01 17:58:08 +01:00
}
2021-07-11 21:04:11 +03:00
}
// 2. Let string be ? ToString(item).
2023-01-26 15:46:03 +00:00
auto string = TRY ( item . to_string ( vm ) ) ;
2021-07-11 21:04:11 +03:00
// 3. Let epochNanoseconds be ? ParseTemporalInstant(string).
2022-08-20 08:52:42 +01:00
auto * epoch_nanoseconds = TRY ( parse_temporal_instant ( vm , string ) ) ;
2021-07-11 21:04:11 +03:00
2021-07-19 00:20:34 +01:00
// 4. Return ! CreateTemporalInstant(ℤ (epochNanoseconds)).
2022-08-20 08:52:42 +01:00
return create_temporal_instant ( vm , * epoch_nanoseconds ) ;
2021-07-11 21:04:11 +03:00
}
// 8.5.4 ParseTemporalInstant ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalinstant
2023-01-26 15:46:03 +00:00
ThrowCompletionOr < BigInt * > parse_temporal_instant ( VM & vm , StringView iso_string )
2021-07-11 21:04:11 +03:00
{
// 1. Assert: Type(isoString) is String.
// 2. Let result be ? ParseTemporalInstantString(isoString).
2022-08-20 08:52:42 +01:00
auto result = TRY ( parse_temporal_instant_string ( vm , iso_string ) ) ;
2021-07-11 21:04:11 +03:00
// 3. Let offsetString be result.[[TimeZoneOffsetString]].
2021-09-16 17:48:04 +01:00
auto & offset_string = result . time_zone_offset ;
2021-07-11 21:04:11 +03:00
// 4. Assert: offsetString is not undefined.
VERIFY ( offset_string . has_value ( ) ) ;
2022-10-14 09:47:17 -04:00
// 5. Let utc be GetUTCEpochNanoseconds(result.[[Year]], result.[[Month]], result.[[Day]], result.[[Hour]], result.[[Minute]], result.[[Second]], result.[[Millisecond]], result.[[Microsecond]], result.[[Nanosecond]]).
auto utc = get_utc_epoch_nanoseconds ( result . year , result . month , result . day , result . hour , result . minute , result . second , result . millisecond , result . microsecond , result . nanosecond ) ;
2021-07-11 21:04:11 +03:00
2022-10-14 11:42:12 -04:00
// 6. If IsTimeZoneOffsetString(offsetString) is false, throw a RangeError exception.
if ( ! is_time_zone_offset_string ( * offset_string ) )
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidTimeZoneName , * offset_string ) ;
// 7. Let offsetNanoseconds be ParseTimeZoneOffsetString(offsetString).
auto offset_nanoseconds = parse_time_zone_offset_string ( * offset_string ) ;
2021-07-11 21:04:11 +03:00
2022-06-23 19:38:38 +01:00
// 7. Let result be utc - ℤ (offsetNanoseconds).
2022-10-14 09:47:17 -04:00
auto result_ns = utc . minus ( Crypto : : SignedBigInteger { offset_nanoseconds } ) ;
2022-03-10 19:47:38 +01:00
2022-06-23 19:38:38 +01:00
// 8. If ! IsValidEpochNanoseconds(result) is false, then
2022-10-14 09:47:17 -04:00
if ( ! is_valid_epoch_nanoseconds ( result_ns ) ) {
2022-03-10 19:47:38 +01:00
// a. Throw a RangeError exception.
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidEpochNanoseconds ) ;
2022-03-10 19:47:38 +01:00
}
2022-06-23 19:38:38 +01:00
// 9. Return result.
2022-12-06 22:03:52 +00:00
return BigInt : : create ( vm , move ( result_ns ) ) . ptr ( ) ;
2021-07-11 21:04:11 +03:00
}
2021-08-08 11:04:30 +01:00
// 8.5.5 CompareEpochNanoseconds ( epochNanosecondsOne, epochNanosecondsTwo ), https://tc39.es/proposal-temporal/#sec-temporal-compareepochnanoseconds
2021-07-11 21:18:48 +03:00
i32 compare_epoch_nanoseconds ( BigInt const & epoch_nanoseconds_one , BigInt const & epoch_nanoseconds_two )
{
// 1. If epochNanosecondsOne > epochNanosecondsTwo, return 1.
if ( epoch_nanoseconds_one . big_integer ( ) > epoch_nanoseconds_two . big_integer ( ) )
return 1 ;
// 2. If epochNanosecondsOne < epochNanosecondsTwo, return -1.
if ( epoch_nanoseconds_one . big_integer ( ) < epoch_nanoseconds_two . big_integer ( ) )
return - 1 ;
// 3. Return 0.
return 0 ;
}
2021-08-07 00:31:08 +01:00
// 8.5.6 AddInstant ( epochNanoseconds, hours, minutes, seconds, milliseconds, microseconds, nanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-addinstant
2022-08-20 08:52:42 +01:00
ThrowCompletionOr < BigInt * > add_instant ( VM & vm , BigInt const & epoch_nanoseconds , double hours , double minutes , double seconds , double milliseconds , double microseconds , double nanoseconds )
2021-08-07 00:31:08 +01:00
{
VERIFY ( hours = = trunc ( hours ) & & minutes = = trunc ( minutes ) & & seconds = = trunc ( seconds ) & & milliseconds = = trunc ( milliseconds ) & & microseconds = = trunc ( microseconds ) & & nanoseconds = = trunc ( nanoseconds ) ) ;
2022-03-09 23:51:53 +01:00
// 1. Let result be epochNanoseconds + ℤ (nanoseconds) + ℤ (microseconds) × 1000ℤ + ℤ (milliseconds) × 10^6ℤ + ℤ (seconds) × 10^9ℤ + ℤ (minutes) × 60ℤ × 10^9ℤ + ℤ (hours) × 3600ℤ × 10^9ℤ .
2022-12-06 22:03:52 +00:00
auto result = BigInt : : create ( vm ,
2021-08-07 00:31:08 +01:00
epoch_nanoseconds . big_integer ( )
2022-08-26 00:49:50 +02:00
. plus ( Crypto : : SignedBigInteger { nanoseconds } )
. plus ( Crypto : : SignedBigInteger { microseconds } . multiplied_by ( Crypto : : SignedBigInteger { 1'000 } ) )
. plus ( Crypto : : SignedBigInteger { milliseconds } . multiplied_by ( Crypto : : SignedBigInteger { 1'000'000 } ) )
. plus ( Crypto : : SignedBigInteger { seconds } . multiplied_by ( Crypto : : SignedBigInteger { 1'000'000'000 } ) )
. plus ( Crypto : : SignedBigInteger { minutes } . multiplied_by ( Crypto : : SignedBigInteger { 60 } ) . multiplied_by ( Crypto : : SignedBigInteger { 1'000'000'000 } ) )
. plus ( Crypto : : SignedBigInteger { hours } . multiplied_by ( Crypto : : SignedBigInteger { 3600 } ) . multiplied_by ( Crypto : : SignedBigInteger { 1'000'000'000 } ) ) ) ;
2021-08-07 00:31:08 +01:00
2022-03-09 23:51:53 +01:00
// 2. If ! IsValidEpochNanoseconds(result) is false, throw a RangeError exception.
2021-09-16 22:32:37 +01:00
if ( ! is_valid_epoch_nanoseconds ( * result ) )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidEpochNanoseconds ) ;
2021-08-07 00:31:08 +01:00
2022-03-09 23:51:53 +01:00
// 3. Return result.
2022-12-06 22:03:52 +00:00
return result . ptr ( ) ;
2021-08-07 00:31:08 +01:00
}
2021-09-06 21:21:57 +03:00
// 8.5.7 DifferenceInstant ( ns1, ns2, roundingIncrement, smallestUnit, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-differenceinstant
2022-08-20 08:52:42 +01:00
BigInt * difference_instant ( VM & vm , BigInt const & nanoseconds1 , BigInt const & nanoseconds2 , u64 rounding_increment , StringView smallest_unit , StringView rounding_mode )
2021-09-06 21:21:57 +03:00
{
// 1. Assert: Type(ns1) is BigInt.
// 2. Assert: Type(ns2) is BigInt.
2022-04-29 21:09:10 +02:00
// 3. Return ! RoundTemporalInstant(ns2 - ns1, roundingIncrement, smallestUnit, roundingMode).
2022-12-06 22:03:52 +00:00
return round_temporal_instant ( vm , BigInt : : create ( vm , nanoseconds2 . big_integer ( ) . minus ( nanoseconds1 . big_integer ( ) ) ) , rounding_increment , smallest_unit , rounding_mode ) ;
2021-09-06 21:21:57 +03:00
}
2021-07-11 23:49:05 +03:00
// 8.5.8 RoundTemporalInstant ( ns, increment, unit, roundingMode ), https://tc39.es/proposal-temporal/#sec-temporal-roundtemporalinstant
2022-08-20 08:52:42 +01:00
BigInt * round_temporal_instant ( VM & vm , BigInt const & nanoseconds , u64 increment , StringView unit , StringView rounding_mode )
2021-07-11 23:49:05 +03:00
{
// 1. Assert: Type(ns) is BigInt.
u64 increment_nanoseconds ;
// 2. If unit is "hour", then
2021-09-06 22:46:55 +03:00
if ( unit = = " hour " sv ) {
2021-07-11 23:49:05 +03:00
// a. Let incrementNs be increment × 3.6 × 10^12.
increment_nanoseconds = increment * 3600000000000 ;
}
// 3. Else if unit is "minute", then
2021-09-06 22:46:55 +03:00
else if ( unit = = " minute " sv ) {
2021-07-11 23:49:05 +03:00
// a. Let incrementNs be increment × 6 × 10^10.
increment_nanoseconds = increment * 60000000000 ;
}
// 4. Else if unit is "second", then
2021-09-06 22:46:55 +03:00
else if ( unit = = " second " sv ) {
2021-07-11 23:49:05 +03:00
// a. Let incrementNs be increment × 10^9.
increment_nanoseconds = increment * 1000000000 ;
}
// 5. Else if unit is "millisecond", then
2021-09-06 22:46:55 +03:00
else if ( unit = = " millisecond " sv ) {
2021-07-11 23:49:05 +03:00
// a. Let incrementNs be increment × 10^6.
increment_nanoseconds = increment * 1000000 ;
}
// 6. Else if unit is "microsecond", then
2021-09-06 22:46:55 +03:00
else if ( unit = = " microsecond " sv ) {
2021-07-11 23:49:05 +03:00
// a. Let incrementNs be increment × 10^3.
increment_nanoseconds = increment * 1000 ;
}
// 7. Else,
else {
2021-07-19 00:20:34 +01:00
// a. Assert: unit is "nanosecond".
2021-09-06 22:46:55 +03:00
VERIFY ( unit = = " nanosecond " sv ) ;
2021-07-19 00:20:34 +01:00
// b. Let incrementNs be increment.
2021-07-11 23:49:05 +03:00
increment_nanoseconds = increment ;
}
2022-06-15 00:58:04 +01:00
// 8. Return RoundNumberToIncrementAsIfPositive(ℝ (ns), incrementNs, roundingMode).
2022-12-06 22:03:52 +00:00
return BigInt : : create ( vm , round_number_to_increment_as_if_positive ( nanoseconds . big_integer ( ) , increment_nanoseconds , rounding_mode ) ) ;
2021-07-11 23:49:05 +03:00
}
2021-08-31 00:15:36 +01:00
// 8.5.9 TemporalInstantToString ( instant, timeZone, precision ), https://tc39.es/proposal-temporal/#sec-temporal-temporalinstanttostring
2023-01-26 15:48:03 +00:00
ThrowCompletionOr < String > temporal_instant_to_string ( VM & vm , Instant & instant , Value time_zone , Variant < StringView , u8 > const & precision )
2021-08-31 00:15:36 +01:00
{
// 1. Assert: Type(instant) is Object.
// 2. Assert: instant has an [[InitializedTemporalInstant]] internal slot.
// 3. Let outputTimeZone be timeZone.
auto output_time_zone = time_zone ;
// 4. If outputTimeZone is undefined, then
if ( output_time_zone . is_undefined ( ) ) {
2022-01-13 19:25:36 +01:00
// a. Set outputTimeZone to ! CreateTemporalTimeZone("UTC").
2023-01-26 16:06:23 +00:00
output_time_zone = MUST_OR_THROW_OOM ( create_temporal_time_zone ( vm , " UTC " sv ) ) ;
2021-08-31 00:15:36 +01:00
}
// 5. Let isoCalendar be ! GetISO8601Calendar().
2022-08-20 08:52:42 +01:00
auto * iso_calendar = get_iso8601_calendar ( vm ) ;
2021-08-31 00:15:36 +01:00
// 6. Let dateTime be ? BuiltinTimeZoneGetPlainDateTimeFor(outputTimeZone, instant, isoCalendar).
2022-08-20 08:52:42 +01:00
auto * date_time = TRY ( builtin_time_zone_get_plain_date_time_for ( vm , output_time_zone , instant , * iso_calendar ) ) ;
2021-08-31 00:15:36 +01:00
2023-01-14 02:52:09 +01:00
// 7. Let dateTimeString be ! TemporalDateTimeToString(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], undefined, precision, "never").
2023-01-26 15:57:49 +00:00
auto date_time_string = MUST_OR_THROW_OOM ( temporal_date_time_to_string ( vm , date_time - > iso_year ( ) , date_time - > iso_month ( ) , date_time - > iso_day ( ) , date_time - > iso_hour ( ) , date_time - > iso_minute ( ) , date_time - > iso_second ( ) , date_time - > iso_millisecond ( ) , date_time - > iso_microsecond ( ) , date_time - > iso_nanosecond ( ) , nullptr , precision , " never " sv ) ) ;
2021-08-31 00:15:36 +01:00
2023-01-26 15:48:03 +00:00
String time_zone_string ;
2021-08-31 00:15:36 +01:00
// 8. If timeZone is undefined, then
if ( time_zone . is_undefined ( ) ) {
// a. Let timeZoneString be "Z".
2023-02-25 16:40:37 +01:00
time_zone_string = " Z " _short_string ;
2021-08-31 00:15:36 +01:00
}
// 9. Else,
else {
2021-11-04 16:45:54 +01:00
// a. Let offsetNs be ? GetOffsetNanosecondsFor(timeZone, instant).
2022-08-20 08:52:42 +01:00
auto offset_ns = TRY ( get_offset_nanoseconds_for ( vm , time_zone , instant ) ) ;
2021-11-04 16:45:54 +01:00
// b. Let timeZoneString be ! FormatISOTimeZoneOffsetString(offsetNs).
2023-01-26 16:10:45 +00:00
time_zone_string = MUST_OR_THROW_OOM ( format_iso_time_zone_offset_string ( vm , offset_ns ) ) ;
2021-08-31 00:15:36 +01:00
}
// 10. Return the string-concatenation of dateTimeString and timeZoneString.
2023-01-26 15:48:03 +00:00
return TRY_OR_THROW_OOM ( vm , String : : formatted ( " {}{} " , date_time_string , time_zone_string ) ) ;
2021-08-31 00:15:36 +01:00
}
2022-05-07 13:32:19 +02:00
// 8.5.10 DifferenceTemporalInstant ( operation, instant, other, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencetemporalinstant
2022-08-20 08:52:42 +01:00
ThrowCompletionOr < Duration * > difference_temporal_instant ( VM & vm , DifferenceOperation operation , Instant const & instant , Value other_value , Value options_value )
2022-05-07 13:32:19 +02:00
{
2022-06-09 20:51:12 +01:00
// 1. If operation is since, let sign be -1. Otherwise, let sign be 1.
i8 sign = operation = = DifferenceOperation : : Since ? - 1 : 1 ;
2022-05-07 13:32:19 +02:00
2022-06-09 20:51:12 +01:00
// 2. Set other to ? ToTemporalInstant(other).
2022-08-20 08:52:42 +01:00
auto * other = TRY ( to_temporal_instant ( vm , other_value ) ) ;
2022-05-07 13:32:19 +02:00
2022-06-24 00:27:29 +01:00
// 3. Let settings be ? GetDifferenceSettings(operation, options, time, « », "nanosecond", "second").
2022-08-20 08:52:42 +01:00
auto settings = TRY ( get_difference_settings ( vm , operation , options_value , UnitGroup : : Time , { } , { " nanosecond " sv } , " second " sv ) ) ;
2022-05-07 13:32:19 +02:00
2022-06-24 00:27:29 +01:00
// 4. Let roundedNs be ! DifferenceInstant(instant.[[Nanoseconds]], other.[[Nanoseconds]], settings.[[RoundingIncrement]], settings.[[SmallestUnit]], settings.[[RoundingMode]]).
2022-08-20 08:52:42 +01:00
auto * rounded_ns = difference_instant ( vm , instant . nanoseconds ( ) , other - > nanoseconds ( ) , settings . rounding_increment , settings . smallest_unit , settings . rounding_mode ) ;
2022-05-07 13:32:19 +02:00
2022-06-24 00:27:29 +01:00
// 5. Assert: The following steps cannot fail due to overflow in the Number domain because abs(roundedNs) ≤ 2 × nsMaxInstant.
2022-05-07 13:32:19 +02:00
2022-06-24 00:27:29 +01:00
// 6. Let result be ! BalanceDuration(0, 0, 0, 0, 0, 0, roundedNs, settings.[[LargestUnit]]).
2022-08-20 08:52:42 +01:00
auto result = MUST ( balance_duration ( vm , 0 , 0 , 0 , 0 , 0 , 0 , rounded_ns - > big_integer ( ) , settings . largest_unit ) ) ;
2022-05-07 13:32:19 +02:00
2022-06-24 00:27:29 +01:00
// 7. Return ! CreateTemporalDuration(0, 0, 0, 0, sign × result.[[Hours]], sign × result.[[Minutes]], sign × result.[[Seconds]], sign × result.[[Milliseconds]], sign × result.[[Microseconds]], sign × result.[[Nanoseconds]]).
2022-08-20 08:52:42 +01:00
return MUST ( create_temporal_duration ( vm , 0 , 0 , 0 , 0 , sign * result . hours , sign * result . minutes , sign * result . seconds , sign * result . milliseconds , sign * result . microseconds , sign * result . nanoseconds ) ) ;
2022-05-07 13:32:19 +02:00
}
// 8.5.11 AddDurationToOrSubtractDurationFromInstant ( operation, instant, temporalDurationLike ), https://tc39.es/proposal-temporal/#sec-temporal-adddurationtoorsubtractdurationfrominstant
2022-08-20 08:52:42 +01:00
ThrowCompletionOr < Instant * > add_duration_to_or_subtract_duration_from_instant ( VM & vm , ArithmeticOperation operation , Instant const & instant , Value temporal_duration_like )
2022-05-06 19:01:15 +02:00
{
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
i8 sign = operation = = ArithmeticOperation : : Subtract ? - 1 : 1 ;
2022-06-09 20:56:03 +01:00
// 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
2022-08-20 08:52:42 +01:00
auto duration = TRY ( to_temporal_duration_record ( vm , temporal_duration_like ) ) ;
2022-06-09 20:56:03 +01:00
// 3. If duration.[[Days]] is not 0, throw a RangeError exception.
if ( duration . days ! = 0 )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidDurationPropertyValueNonZero , " days " , duration . days ) ;
2022-06-09 20:56:03 +01:00
// 4. If duration.[[Months]] is not 0, throw a RangeError exception.
if ( duration . months ! = 0 )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidDurationPropertyValueNonZero , " months " , duration . months ) ;
2022-06-09 20:56:03 +01:00
// 5. If duration.[[Weeks]] is not 0, throw a RangeError exception.
if ( duration . weeks ! = 0 )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidDurationPropertyValueNonZero , " weeks " , duration . weeks ) ;
2022-06-09 20:56:03 +01:00
// 6. If duration.[[Years]] is not 0, throw a RangeError exception.
if ( duration . years ! = 0 )
2022-08-16 20:33:17 +01:00
return vm . throw_completion < RangeError > ( ErrorType : : TemporalInvalidDurationPropertyValueNonZero , " years " , duration . years ) ;
2022-05-06 19:01:15 +02:00
2022-06-09 20:56:03 +01:00
// 7. Let ns be ? AddInstant(instant.[[Nanoseconds]], sign × duration.[[Hours]], sign × duration.[[Minutes]], sign × duration.[[Seconds]], sign × duration.[[Milliseconds]], sign × duration.[[Microseconds]], sign × duration.[[Nanoseconds]]).
2022-08-20 08:52:42 +01:00
auto * ns = TRY ( add_instant ( vm , instant . nanoseconds ( ) , sign * duration . hours , sign * duration . minutes , sign * duration . seconds , sign * duration . milliseconds , sign * duration . microseconds , sign * duration . nanoseconds ) ) ;
2022-05-06 19:01:15 +02:00
2022-06-09 20:56:03 +01:00
// 8. Return ! CreateTemporalInstant(ns).
2022-08-20 08:52:42 +01:00
return MUST ( create_temporal_instant ( vm , * ns ) ) ;
2022-05-06 19:01:15 +02:00
}
2021-07-07 17:41:37 +01:00
}