Duration.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Optional.h>
  8. #include <LibJS/Heap/Handle.h>
  9. #include <LibJS/Runtime/Completion.h>
  10. #include <LibJS/Runtime/Object.h>
  11. #include <LibJS/Runtime/Temporal/PlainDate.h>
  12. #include <LibJS/Runtime/Temporal/PlainDateTime.h>
  13. #include <LibJS/Runtime/Temporal/ZonedDateTime.h>
  14. #include <LibJS/Runtime/VM.h>
  15. namespace JS::Temporal {
  16. class Duration final : public Object {
  17. JS_OBJECT(Duration, Object);
  18. public:
  19. Duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds, Object& prototype);
  20. virtual ~Duration() override = default;
  21. [[nodiscard]] double years() const { return m_years; }
  22. [[nodiscard]] double months() const { return m_months; }
  23. [[nodiscard]] double weeks() const { return m_weeks; }
  24. [[nodiscard]] double days() const { return m_days; }
  25. [[nodiscard]] double hours() const { return m_hours; }
  26. [[nodiscard]] double minutes() const { return m_minutes; }
  27. [[nodiscard]] double seconds() const { return m_seconds; }
  28. [[nodiscard]] double milliseconds() const { return m_milliseconds; }
  29. [[nodiscard]] double microseconds() const { return m_microseconds; }
  30. [[nodiscard]] double nanoseconds() const { return m_nanoseconds; }
  31. private:
  32. // 7.4 Properties of Temporal.Duration Instances, https://tc39.es/proposal-temporal/#sec-properties-of-temporal-duration-instances
  33. double m_years; // [[Years]]
  34. double m_months; // [[Months]]
  35. double m_weeks; // [[Weeks]]
  36. double m_days; // [[Days]]
  37. double m_hours; // [[Hours]]
  38. double m_minutes; // [[Minutes]]
  39. double m_seconds; // [[Seconds]]
  40. double m_milliseconds; // [[Milliseconds]]
  41. double m_microseconds; // [[Microseconds]]
  42. double m_nanoseconds; // [[Nanoseconds]]
  43. };
  44. // Used by ToTemporalDurationRecord to temporarily hold values
  45. struct TemporalDuration {
  46. double years;
  47. double months;
  48. double weeks;
  49. double days;
  50. double hours;
  51. double minutes;
  52. double seconds;
  53. double milliseconds;
  54. double microseconds;
  55. double nanoseconds;
  56. };
  57. // Used by ToPartialDuration to temporarily hold values
  58. struct PartialDuration {
  59. Optional<double> years;
  60. Optional<double> months;
  61. Optional<double> weeks;
  62. Optional<double> days;
  63. Optional<double> hours;
  64. Optional<double> minutes;
  65. Optional<double> seconds;
  66. Optional<double> milliseconds;
  67. Optional<double> microseconds;
  68. Optional<double> nanoseconds;
  69. };
  70. // Used by BalanceDuration to temporarily hold values
  71. struct BalancedDuration {
  72. double days;
  73. double hours;
  74. double minutes;
  75. double seconds;
  76. double milliseconds;
  77. double microseconds;
  78. double nanoseconds;
  79. };
  80. // Used by MoveRelativeDate to temporarily hold values
  81. struct MoveRelativeDateResult {
  82. Handle<PlainDateTime> relative_to;
  83. double days;
  84. };
  85. // Used by RoundDuration to temporarily hold values
  86. struct RoundedDuration {
  87. double years;
  88. double months;
  89. double weeks;
  90. double days;
  91. double hours;
  92. double minutes;
  93. double seconds;
  94. double milliseconds;
  95. double microseconds;
  96. double nanoseconds;
  97. double remainder;
  98. };
  99. // Used by UnbalanceDurationRelative to temporarily hold values
  100. struct UnbalancedDuration {
  101. double years;
  102. double months;
  103. double weeks;
  104. double days;
  105. };
  106. // Table 7: Properties of a TemporalDurationLike, https://tc39.es/proposal-temporal/#table-temporal-temporaldurationlike-properties
  107. template<typename StructT, typename ValueT>
  108. struct TemporalDurationLikeProperty {
  109. ValueT StructT::*internal_slot { nullptr };
  110. PropertyKey property;
  111. };
  112. template<typename StructT, typename ValueT>
  113. auto temporal_duration_like_properties = [](VM& vm) {
  114. using PropertyT = TemporalDurationLikeProperty<StructT, ValueT>;
  115. return AK::Array<PropertyT, 10> {
  116. PropertyT { &StructT::days, vm.names.days },
  117. PropertyT { &StructT::hours, vm.names.hours },
  118. PropertyT { &StructT::microseconds, vm.names.microseconds },
  119. PropertyT { &StructT::milliseconds, vm.names.milliseconds },
  120. PropertyT { &StructT::minutes, vm.names.minutes },
  121. PropertyT { &StructT::months, vm.names.months },
  122. PropertyT { &StructT::nanoseconds, vm.names.nanoseconds },
  123. PropertyT { &StructT::seconds, vm.names.seconds },
  124. PropertyT { &StructT::weeks, vm.names.weeks },
  125. PropertyT { &StructT::years, vm.names.years },
  126. };
  127. };
  128. ThrowCompletionOr<Duration*> to_temporal_duration(GlobalObject&, Value item);
  129. ThrowCompletionOr<TemporalDuration> to_temporal_duration_record(GlobalObject&, Object const& temporal_duration_like);
  130. i8 duration_sign(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds);
  131. bool is_valid_duration(double years, double months, double weeks, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, double nanoseconds);
  132. ThrowCompletionOr<PartialDuration> to_partial_duration(GlobalObject&, Value temporal_duration_like);
  133. ThrowCompletionOr<Duration*> 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);
  134. Duration* create_negated_temporal_duration(GlobalObject& global_object, Duration const& duration);
  135. ThrowCompletionOr<double> 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);
  136. BigInt* total_duration_nanoseconds(GlobalObject&, double days, double hours, double minutes, double seconds, double milliseconds, double microseconds, BigInt const& nanoseconds, double offset_shift);
  137. ThrowCompletionOr<BalancedDuration> 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);
  138. ThrowCompletionOr<UnbalancedDuration> unbalance_duration_relative(GlobalObject&, double years, double months, double weeks, double days, String const& largest_unit, Value relative_to);
  139. ThrowCompletionOr<MoveRelativeDateResult> move_relative_date(GlobalObject&, Object& calendar, PlainDateTime& relative_to, Duration& duration);
  140. ThrowCompletionOr<ZonedDateTime*> move_relative_zoned_date_time(GlobalObject&, ZonedDateTime&, double years, double months, double weeks, double days);
  141. ThrowCompletionOr<RoundedDuration> 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);
  142. ThrowCompletionOr<TemporalDuration> to_limited_temporal_duration(GlobalObject&, Value temporal_duration_like, Vector<StringView> const& disallowed_fields);
  143. 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<StringView, u8> const& precision);
  144. // 7.5.15 DaysUntil ( earlier, later ), https://tc39.es/proposal-temporal/#sec-temporal-daysuntil
  145. template<typename EarlierObjectType, typename LaterObjectType>
  146. double days_until(GlobalObject& global_object, EarlierObjectType& earlier, LaterObjectType& later)
  147. {
  148. // 1. Assert: earlier and later both have [[ISOYear]], [[ISOMonth]], and [[ISODay]] internal slots.
  149. // 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.
  150. // 2. Let difference be ! DifferenceISODate(earlier.[[ISOYear]], earlier.[[ISOMonth]], earlier.[[ISODay]], later.[[ISOYear]], later.[[ISOMonth]], later.[[ISODay]], "day").
  151. 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);
  152. // 3. Return difference.[[Days]].
  153. return difference.days;
  154. }
  155. }