Duration.h (8486B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef builtin_temporal_Duration_h 8 #define builtin_temporal_Duration_h 9 10 #include "mozilla/Assertions.h" 11 12 #include <stdint.h> 13 14 #include "builtin/temporal/TemporalTypes.h" 15 #include "js/RootingAPI.h" 16 #include "js/TypeDecls.h" 17 #include "js/Value.h" 18 #include "vm/NativeObject.h" 19 20 namespace js { 21 struct ClassSpec; 22 } 23 24 namespace js::temporal { 25 26 class DurationObject : public NativeObject { 27 public: 28 static const JSClass class_; 29 static const JSClass& protoClass_; 30 31 static constexpr uint32_t YEARS_SLOT = 0; 32 static constexpr uint32_t MONTHS_SLOT = 1; 33 static constexpr uint32_t WEEKS_SLOT = 2; 34 static constexpr uint32_t DAYS_SLOT = 3; 35 static constexpr uint32_t HOURS_SLOT = 4; 36 static constexpr uint32_t MINUTES_SLOT = 5; 37 static constexpr uint32_t SECONDS_SLOT = 6; 38 static constexpr uint32_t MILLISECONDS_SLOT = 7; 39 static constexpr uint32_t MICROSECONDS_SLOT = 8; 40 static constexpr uint32_t NANOSECONDS_SLOT = 9; 41 static constexpr uint32_t SLOT_COUNT = 10; 42 43 double years() const { return getFixedSlot(YEARS_SLOT).toNumber(); } 44 double months() const { return getFixedSlot(MONTHS_SLOT).toNumber(); } 45 double weeks() const { return getFixedSlot(WEEKS_SLOT).toNumber(); } 46 double days() const { return getFixedSlot(DAYS_SLOT).toNumber(); } 47 double hours() const { return getFixedSlot(HOURS_SLOT).toNumber(); } 48 double minutes() const { return getFixedSlot(MINUTES_SLOT).toNumber(); } 49 double seconds() const { return getFixedSlot(SECONDS_SLOT).toNumber(); } 50 double milliseconds() const { 51 return getFixedSlot(MILLISECONDS_SLOT).toNumber(); 52 } 53 double microseconds() const { 54 return getFixedSlot(MICROSECONDS_SLOT).toNumber(); 55 } 56 double nanoseconds() const { 57 return getFixedSlot(NANOSECONDS_SLOT).toNumber(); 58 } 59 60 private: 61 static const ClassSpec classSpec_; 62 }; 63 64 /** 65 * Extract the duration fields from the Duration object. 66 */ 67 inline Duration ToDuration(const DurationObject* duration) { 68 return { 69 duration->years(), duration->months(), 70 duration->weeks(), duration->days(), 71 duration->hours(), duration->minutes(), 72 duration->seconds(), duration->milliseconds(), 73 duration->microseconds(), duration->nanoseconds(), 74 }; 75 } 76 77 class Increment; 78 class CalendarValue; 79 class TimeZoneValue; 80 enum class TemporalRoundingMode; 81 enum class TemporalUnit; 82 83 /** 84 * DurationSign ( duration ) 85 */ 86 int32_t DurationSign(const Duration& duration); 87 88 /** 89 * DateDurationSign ( dateDuration ) 90 */ 91 int32_t DateDurationSign(const DateDuration& duration); 92 93 #ifdef DEBUG 94 /** 95 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, 96 * milliseconds, microseconds, nanoseconds ) 97 */ 98 bool IsValidDuration(const Duration& duration); 99 100 /** 101 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, 102 * milliseconds, microseconds, nanoseconds ) 103 */ 104 bool IsValidDuration(const DateDuration& duration); 105 106 /** 107 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, 108 * milliseconds, microseconds, nanoseconds ) 109 */ 110 bool IsValidDuration(const InternalDuration& duration); 111 #endif 112 113 /** 114 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, 115 * milliseconds, microseconds, nanoseconds ) 116 */ 117 bool ThrowIfInvalidDuration(JSContext* cx, const Duration& duration); 118 119 /** 120 * IsValidDuration ( years, months, weeks, days, hours, minutes, seconds, 121 * milliseconds, microseconds, nanoseconds ) 122 */ 123 inline bool IsValidTimeDuration(const TimeDuration& duration) { 124 MOZ_ASSERT(0 <= duration.nanoseconds && duration.nanoseconds <= 999'999'999); 125 126 // The absolute value of the seconds part of a time duration must be 127 // less-or-equal to `2**53 - 1` and the nanoseconds part must be less or equal 128 // to `999'999'999`. 129 // 130 // Add ±1 nanosecond to make the nanoseconds part zero, which enables faster 131 // codegen. 132 133 constexpr auto max = TimeDuration::max() + TimeDuration::fromNanoseconds(1); 134 static_assert(max.nanoseconds == 0); 135 136 constexpr auto min = TimeDuration::min() - TimeDuration::fromNanoseconds(1); 137 static_assert(min.nanoseconds == 0); 138 139 // Step 4. 140 return min < duration && duration < max; 141 } 142 143 /** 144 * TimeDurationFromComponents ( hours, minutes, seconds, milliseconds, 145 * microseconds, nanoseconds ) 146 */ 147 TimeDuration TimeDurationFromComponents(const Duration& duration); 148 149 /** 150 * CompareTimeDuration ( one, two ) 151 */ 152 inline int32_t CompareTimeDuration(const TimeDuration& one, 153 const TimeDuration& two) { 154 MOZ_ASSERT(IsValidTimeDuration(one)); 155 MOZ_ASSERT(IsValidTimeDuration(two)); 156 157 // Step 1. 158 if (one > two) { 159 return 1; 160 } 161 162 // Step 2. 163 if (one < two) { 164 return -1; 165 } 166 167 // Step 3. 168 return 0; 169 } 170 171 /** 172 * TimeDurationSign ( d ) 173 */ 174 inline int32_t TimeDurationSign(const TimeDuration& d) { 175 MOZ_ASSERT(IsValidTimeDuration(d)); 176 177 // Steps 1-3. 178 return CompareTimeDuration(d, TimeDuration{}); 179 } 180 181 /** 182 * ToInternalDurationRecord ( duration ) 183 */ 184 inline InternalDuration ToInternalDurationRecord(const Duration& duration) { 185 MOZ_ASSERT(IsValidDuration(duration)); 186 187 // Steps 1-3. 188 return {duration.toDateDuration(), TimeDurationFromComponents(duration)}; 189 } 190 191 /** 192 * ToInternalDurationRecordWith24HourDays ( duration ) 193 */ 194 InternalDuration ToInternalDurationRecordWith24HourDays( 195 const Duration& duration); 196 197 /** 198 * ToDateDurationRecordWithoutTime ( duration ) 199 */ 200 DateDuration ToDateDurationRecordWithoutTime(const Duration& duration); 201 202 /** 203 * TemporalDurationFromInternal ( internalDuration, largestUnit ) 204 */ 205 bool TemporalDurationFromInternal(JSContext* cx, 206 const TimeDuration& timeDuration, 207 TemporalUnit largestUnit, Duration* result); 208 209 /** 210 * TemporalDurationFromInternal ( internalDuration, largestUnit ) 211 */ 212 bool TemporalDurationFromInternal(JSContext* cx, 213 const InternalDuration& internalDuration, 214 TemporalUnit largestUnit, Duration* result); 215 216 /** 217 * TimeDurationFromEpochNanosecondsDifference ( one, two ) 218 */ 219 TimeDuration TimeDurationFromEpochNanosecondsDifference( 220 const EpochNanoseconds& one, const EpochNanoseconds& two); 221 222 /** 223 * CreateTemporalDuration ( years, months, weeks, days, hours, minutes, seconds, 224 * milliseconds, microseconds, nanoseconds [ , newTarget ] ) 225 */ 226 DurationObject* CreateTemporalDuration(JSContext* cx, const Duration& duration); 227 228 /** 229 * ToTemporalDuration ( item ) 230 */ 231 bool ToTemporalDuration(JSContext* cx, JS::Handle<JS::Value> item, 232 Duration* result); 233 234 /** 235 * RoundTimeDuration ( duration, increment, unit, roundingMode ) 236 */ 237 TimeDuration RoundTimeDuration(const TimeDuration& duration, 238 Increment increment, TemporalUnit unit, 239 TemporalRoundingMode roundingMode); 240 241 /** 242 * RoundRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime, 243 * timeZone, calendar, largestUnit, increment, smallestUnit, roundingMode ) 244 */ 245 bool RoundRelativeDuration( 246 JSContext* cx, const InternalDuration& duration, 247 const EpochNanoseconds& originEpochNs, const EpochNanoseconds& destEpochNs, 248 const ISODateTime& isoDateTime, JS::Handle<TimeZoneValue> timeZone, 249 JS::Handle<CalendarValue> calendar, TemporalUnit largestUnit, 250 Increment increment, TemporalUnit smallestUnit, 251 TemporalRoundingMode roundingMode, InternalDuration* result); 252 253 /** 254 * TotalRelativeDuration ( duration, originEpochNs, destEpochNs, isoDateTime, 255 * timeZone, calendar, unit ) 256 */ 257 bool TotalRelativeDuration(JSContext* cx, const InternalDuration& duration, 258 const EpochNanoseconds& originEpochNs, 259 const EpochNanoseconds& destEpochNs, 260 const ISODateTime& isoDateTime, 261 JS::Handle<TimeZoneValue> timeZone, 262 JS::Handle<CalendarValue> calendar, 263 TemporalUnit unit, double* result); 264 265 /** 266 * TotalTimeDuration ( timeDuration, unit ) 267 */ 268 double TotalTimeDuration(const TimeDuration& duration, TemporalUnit unit); 269 270 } /* namespace js::temporal */ 271 272 #endif /* builtin_temporal_Duration_h */