ZonedDateTime.h (6296B)
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_ZonedDateTime_h 8 #define builtin_temporal_ZonedDateTime_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Attributes.h" 12 13 #include <stdint.h> 14 15 #include "builtin/temporal/Calendar.h" 16 #include "builtin/temporal/Instant.h" 17 #include "builtin/temporal/TemporalTypes.h" 18 #include "builtin/temporal/TimeZone.h" 19 #include "js/RootingAPI.h" 20 #include "js/TypeDecls.h" 21 #include "js/Value.h" 22 #include "vm/NativeObject.h" 23 24 class JS_PUBLIC_API JSTracer; 25 26 namespace js { 27 struct ClassSpec; 28 } 29 30 namespace js::temporal { 31 32 class ZonedDateTimeObject : public NativeObject { 33 public: 34 static const JSClass class_; 35 static const JSClass& protoClass_; 36 37 static constexpr uint32_t SECONDS_SLOT = 0; 38 static constexpr uint32_t NANOSECONDS_SLOT = 1; 39 static constexpr uint32_t TIMEZONE_SLOT = 2; 40 static constexpr uint32_t CALENDAR_SLOT = 3; 41 static constexpr uint32_t SLOT_COUNT = 4; 42 43 /** 44 * Extract the epoch nanoseconds fields from this ZonedDateTime object. 45 */ 46 EpochNanoseconds epochNanoseconds() const { 47 double seconds = getFixedSlot(SECONDS_SLOT).toNumber(); 48 MOZ_ASSERT(-8'640'000'000'000 <= seconds && seconds <= 8'640'000'000'000); 49 50 int32_t nanoseconds = getFixedSlot(NANOSECONDS_SLOT).toInt32(); 51 MOZ_ASSERT(0 <= nanoseconds && nanoseconds <= 999'999'999); 52 53 return {{int64_t(seconds), nanoseconds}}; 54 } 55 56 TimeZoneValue timeZone() const { 57 return TimeZoneValue(getFixedSlot(TIMEZONE_SLOT)); 58 } 59 60 CalendarValue calendar() const { 61 return CalendarValue(getFixedSlot(CALENDAR_SLOT)); 62 } 63 64 private: 65 static const ClassSpec classSpec_; 66 }; 67 68 class MOZ_STACK_CLASS ZonedDateTime final { 69 EpochNanoseconds epochNanoseconds_; 70 TimeZoneValue timeZone_; 71 CalendarValue calendar_; 72 73 public: 74 ZonedDateTime() = default; 75 76 ZonedDateTime(const EpochNanoseconds& epochNanoseconds, 77 const TimeZoneValue& timeZone, const CalendarValue& calendar) 78 : epochNanoseconds_(epochNanoseconds), 79 timeZone_(timeZone), 80 calendar_(calendar) { 81 MOZ_ASSERT(IsValidEpochNanoseconds(epochNanoseconds)); 82 MOZ_ASSERT(timeZone); 83 MOZ_ASSERT(calendar); 84 } 85 86 explicit ZonedDateTime(const ZonedDateTimeObject* obj) 87 : ZonedDateTime(obj->epochNanoseconds(), obj->timeZone(), 88 obj->calendar()) {} 89 90 const auto& epochNanoseconds() const { return epochNanoseconds_; } 91 92 const auto& timeZone() const { return timeZone_; } 93 94 const auto& calendar() const { return calendar_; } 95 96 explicit operator bool() const { return !!timeZone_ && !!calendar_; } 97 98 void trace(JSTracer* trc) { 99 timeZone_.trace(trc); 100 calendar_.trace(trc); 101 } 102 103 const auto* timeZoneDoNotUse() const { return &timeZone_; } 104 const auto* calendarDoNotUse() const { return &calendar_; } 105 }; 106 107 struct DifferenceSettings; 108 enum class TemporalDisambiguation; 109 enum class TemporalOffset; 110 enum class TemporalUnit; 111 112 /** 113 * CreateTemporalZonedDateTime ( epochNanoseconds, timeZone, calendar [ , 114 * newTarget ] ) 115 */ 116 ZonedDateTimeObject* CreateTemporalZonedDateTime( 117 JSContext* cx, const EpochNanoseconds& epochNanoseconds, 118 JS::Handle<TimeZoneValue> timeZone, JS::Handle<CalendarValue> calendar); 119 120 /** 121 * AddZonedDateTime ( epochNanoseconds, timeZone, calendar, duration, overflow ) 122 */ 123 bool AddZonedDateTime(JSContext* cx, JS::Handle<ZonedDateTime> zonedDateTime, 124 const InternalDuration& duration, 125 EpochNanoseconds* result); 126 127 /** 128 * DifferenceZonedDateTimeWithRounding ( ns1, ns2, timeZone, calendar, 129 * largestUnit, roundingIncrement, smallestUnit, roundingMode ) 130 */ 131 bool DifferenceZonedDateTimeWithRounding( 132 JSContext* cx, JS::Handle<ZonedDateTime> zonedDateTime, 133 const EpochNanoseconds& ns2, const DifferenceSettings& settings, 134 InternalDuration* result); 135 136 /** 137 * DifferenceZonedDateTimeWithTotal ( ns1, ns2, timeZone, calendar, unit ) 138 */ 139 bool DifferenceZonedDateTimeWithTotal(JSContext* cx, 140 JS::Handle<ZonedDateTime> zonedDateTime, 141 const EpochNanoseconds& ns2, 142 TemporalUnit unit, double* result); 143 144 enum class OffsetBehaviour { Option, Exact, Wall }; 145 146 enum class MatchBehaviour { MatchExactly, MatchMinutes }; 147 148 /** 149 * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, 150 * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) 151 */ 152 bool InterpretISODateTimeOffset( 153 JSContext* cx, const ISODateTime& dateTime, OffsetBehaviour offsetBehaviour, 154 int64_t offsetNanoseconds, JS::Handle<TimeZoneValue> timeZone, 155 TemporalDisambiguation disambiguation, TemporalOffset offsetOption, 156 MatchBehaviour matchBehaviour, EpochNanoseconds* result); 157 158 /** 159 * InterpretISODateTimeOffset ( isoDate, time, offsetBehaviour, 160 * offsetNanoseconds, timeZone, disambiguation, offsetOption, matchBehaviour ) 161 */ 162 bool InterpretISODateTimeOffset( 163 JSContext* cx, const ISODate& isoDate, OffsetBehaviour offsetBehaviour, 164 int64_t offsetNanoseconds, JS::Handle<TimeZoneValue> timeZone, 165 TemporalDisambiguation disambiguation, TemporalOffset offsetOption, 166 MatchBehaviour matchBehaviour, EpochNanoseconds* result); 167 168 } /* namespace js::temporal */ 169 170 namespace js { 171 172 template <typename Wrapper> 173 class WrappedPtrOperations<temporal::ZonedDateTime, Wrapper> { 174 const auto& container() const { 175 return static_cast<const Wrapper*>(this)->get(); 176 } 177 178 public: 179 explicit operator bool() const { return bool(container()); } 180 181 const auto& epochNanoseconds() const { 182 return container().epochNanoseconds(); 183 } 184 185 JS::Handle<temporal::TimeZoneValue> timeZone() const { 186 return JS::Handle<temporal::TimeZoneValue>::fromMarkedLocation( 187 container().timeZoneDoNotUse()); 188 } 189 190 JS::Handle<temporal::CalendarValue> calendar() const { 191 return JS::Handle<temporal::CalendarValue>::fromMarkedLocation( 192 container().calendarDoNotUse()); 193 } 194 }; 195 196 } /* namespace js */ 197 198 #endif /* builtin_temporal_ZonedDateTime_h */