/* * Copyright (c) 2021, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace JS::Temporal { class Duration final : public Object { JS_OBJECT(Duration, Object); public: Duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object& prototype); virtual ~Duration() override = default; [[nodiscard]] double years() const { return m_years; } [[nodiscard]] double months() const { return m_months; } [[nodiscard]] double weeks() const { return m_weeks; } [[nodiscard]] double days() const { return m_days; } [[nodiscard]] double hours() const { return m_hours; } [[nodiscard]] double minutes() const { return m_minutes; } [[nodiscard]] double seconds() const { return m_seconds; } [[nodiscard]] double milliseconds() const { return m_milliseconds; } [[nodiscard]] double microseconds() const { return m_microseconds; } [[nodiscard]] double nanoseconds() const { return m_nanoseconds; } private: // 7.4 Properties of Temporal.Duration Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-duration-instances double m_years; // [[Years]] double m_months; // [[Months]] double m_weeks; // [[Weeks]] double m_days; // [[Days]] double m_hours; // [[Hours]] double m_minutes; // [[Minutes]] double m_seconds; // [[Seconds]] double m_milliseconds; // [[Milliseconds]] double m_microseconds; // [[Microseconds]] double m_nanoseconds; // [[Nanoseconds]] }; // Used by ToTemporalDurationRecord to temporarily hold values struct TemporalDuration { double years; double months; double weeks; double days; double hours; double minutes; double seconds; double milliseconds; double microseconds; double nanoseconds; }; // Used by ToPartialDuration to temporarily hold values struct PartialDuration { Optional years; Optional months; Optional weeks; Optional days; Optional hours; Optional minutes; Optional seconds; Optional milliseconds; Optional microseconds; Optional nanoseconds; }; // Used by BalanceDuration to temporarily hold values struct BalancedDuration { double days; double hours; double minutes; double seconds; double milliseconds; double microseconds; double nanoseconds; }; // Used by MoveRelativeDate to temporarily hold values struct MoveRelativeDateResult { Handle relative_to; double days; }; // Used by RoundDuration to temporarily hold values struct RoundedDuration { double years; double months; double weeks; double days; double hours; double minutes; double seconds; double milliseconds; double microseconds; double nanoseconds; double remainder; }; // Used by UnbalanceDurationRelative to temporarily hold values struct UnbalancedDuration { double years; double months; double weeks; double days; }; // Table 7: Properties of a TemporalDurationLike, https://tc39.es/proposal-temporal/#table-temporal-temporaldurationlike-properties template struct TemporalDurationLikeProperty { ValueT StructT::*internal_slot { nullptr }; PropertyKey property; }; template auto temporal_duration_like_properties = [](VM& vm) { using PropertyT = TemporalDurationLikeProperty; return AK::Array { PropertyT { &StructT::days, vm.names.days }, PropertyT { &StructT::hours, vm.names.hours }, PropertyT { &StructT::microseconds, vm.names.microseconds }, PropertyT { &StructT::milliseconds, vm.names.milliseconds }, PropertyT { &StructT::minutes, vm.names.minutes }, PropertyT { &StructT::months, vm.names.months }, PropertyT { &StructT::nanoseconds, vm.names.nanoseconds }, PropertyT { &StructT::seconds, vm.names.seconds }, PropertyT { &StructT::weeks, vm.names.weeks }, PropertyT { &StructT::years, vm.names.years }, }; }; ThrowCompletionOr to_temporal_duration(GlobalObject&, Value item); ThrowCompletionOr to_temporal_duration_record(GlobalObject&, Object const& temporal_duration_like); i8 duration_sign(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); bool is_valid_duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); ThrowCompletionOr to_partial_duration(GlobalObject&, Value temporal_duration_like); ThrowCompletionOr create_temporal_duration(GlobalObject&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, FunctionObject const* new_target = nullptr); Duration* create_negated_temporal_duration(GlobalObject& global_object, Duration const& duration); ThrowCompletionOr calculate_offset_shift(GlobalObject&, Value relative_to_value, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds); BigInt* total_duration_nanoseconds(GlobalObject&, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, BigInt const& nanoseconds, double offset_shift); ThrowCompletionOr balance_duration(GlobalObject&, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, BigInt const& nanoseconds, String const& largest_unit, Object* relative_to = nullptr); ThrowCompletionOr unbalance_duration_relative(GlobalObject&, double years, double months, double weeks, double days, String const& largest_unit, Value relative_to); ThrowCompletionOr move_relative_date(GlobalObject&, Object& calendar, PlainDateTime& relative_to, Duration& duration); ThrowCompletionOr move_relative_zoned_date_time(GlobalObject&, ZonedDateTime&, double years, double months, double weeks, double days); ThrowCompletionOr round_duration(GlobalObject&, double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, u32 increment, StringView unit, StringView rounding_mode, Object* relative_to_object = nullptr); ThrowCompletionOr to_limited_temporal_duration(GlobalObject&, Value temporal_duration_like, Vector const& disallowed_fields); String temporal_duration_to_string(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Variant const& precision); // 7.5.15 DaysUntil ( earlier, later ), https://tc39.es/proposal-temporal/#sec-temporal-daysuntil template double days_until(GlobalObject& global_object, EarlierObjectType& earlier, LaterObjectType& later) { // 1. Assert: earlier and later both have [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots. // NOTE: We could enforce this via concepts, but the compiler would complain anyway if either of the types doesn't have the methods used below. // 2. Let difference be ! DifferenceISODate(earlier.[[ISOYear]], earlier.[[ISOMonth]], earlier.[[ISODay]], later.[[ISOYear]], later.[[ISOMonth]], later.[[ISODay]], "day"). auto difference = difference_iso_date(global_object, earlier.iso_year(), earlier.iso_month(), earlier.iso_day(), later.iso_year(), later.iso_month(), later.iso_day(), "day"sv); // 3. Return difference.[[Days]]. return difference.days; } }