summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/temporal/ZonedDateTime.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/temporal/ZonedDateTime.h')
-rw-r--r--js/src/builtin/temporal/ZonedDateTime.h280
1 files changed, 280 insertions, 0 deletions
diff --git a/js/src/builtin/temporal/ZonedDateTime.h b/js/src/builtin/temporal/ZonedDateTime.h
new file mode 100644
index 0000000000..73e3a3384f
--- /dev/null
+++ b/js/src/builtin/temporal/ZonedDateTime.h
@@ -0,0 +1,280 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef builtin_temporal_ZonedDateTime_h
+#define builtin_temporal_ZonedDateTime_h
+
+#include "mozilla/Assertions.h"
+
+#include <stdint.h>
+
+#include "builtin/temporal/Calendar.h"
+#include "builtin/temporal/Instant.h"
+#include "builtin/temporal/TemporalTypes.h"
+#include "builtin/temporal/TimeZone.h"
+#include "js/RootingAPI.h"
+#include "js/TypeDecls.h"
+#include "js/Value.h"
+#include "vm/NativeObject.h"
+
+class JS_PUBLIC_API JSTracer;
+
+namespace js {
+struct ClassSpec;
+}
+
+namespace js::temporal {
+
+class ZonedDateTimeObject : public NativeObject {
+ public:
+ static const JSClass class_;
+ static const JSClass& protoClass_;
+
+ static constexpr uint32_t SECONDS_SLOT = 0;
+ static constexpr uint32_t NANOSECONDS_SLOT = 1;
+ static constexpr uint32_t TIMEZONE_SLOT = 2;
+ static constexpr uint32_t CALENDAR_SLOT = 3;
+ static constexpr uint32_t SLOT_COUNT = 4;
+
+ int64_t seconds() const {
+ double seconds = getFixedSlot(SECONDS_SLOT).toNumber();
+ MOZ_ASSERT(-8'640'000'000'000 <= seconds && seconds <= 8'640'000'000'000);
+ return int64_t(seconds);
+ }
+
+ int32_t nanoseconds() const {
+ int32_t nanoseconds = getFixedSlot(NANOSECONDS_SLOT).toInt32();
+ MOZ_ASSERT(0 <= nanoseconds && nanoseconds <= 999'999'999);
+ return nanoseconds;
+ }
+
+ TimeZoneValue timeZone() const {
+ return TimeZoneValue(getFixedSlot(TIMEZONE_SLOT));
+ }
+
+ CalendarValue calendar() const {
+ return CalendarValue(getFixedSlot(CALENDAR_SLOT));
+ }
+
+ private:
+ static const ClassSpec classSpec_;
+};
+/**
+ * Extract the instant fields from the ZonedDateTime object.
+ */
+inline Instant ToInstant(const ZonedDateTimeObject* zonedDateTime) {
+ return {zonedDateTime->seconds(), zonedDateTime->nanoseconds()};
+}
+
+class ZonedDateTime {
+ Instant instant_;
+ TimeZoneValue timeZone_;
+ CalendarValue calendar_;
+
+ public:
+ ZonedDateTime() = default;
+
+ ZonedDateTime(const Instant& instant, const TimeZoneValue& timeZone,
+ const CalendarValue& calendar)
+ : instant_(instant), timeZone_(timeZone), calendar_(calendar) {
+ MOZ_ASSERT(IsValidEpochInstant(instant));
+ MOZ_ASSERT(timeZone);
+ MOZ_ASSERT(calendar);
+ }
+
+ explicit ZonedDateTime(const ZonedDateTimeObject* obj)
+ : ZonedDateTime(ToInstant(obj), obj->timeZone(), obj->calendar()) {}
+
+ const auto& instant() const { return instant_; }
+
+ const auto& timeZone() const { return timeZone_; }
+
+ const auto& calendar() const { return calendar_; }
+
+ explicit operator bool() const { return !!timeZone_ && !!calendar_; }
+
+ void trace(JSTracer* trc) {
+ timeZone_.trace(trc);
+ calendar_.trace(trc);
+ }
+
+ const auto* timeZoneDoNotUse() const { return &timeZone_; }
+ const auto* calendarDoNotUse() const { return &calendar_; }
+};
+
+enum class TemporalDisambiguation;
+enum class TemporalOffset;
+enum class TemporalOverflow;
+enum class TemporalUnit;
+
+/**
+ * CreateTemporalZonedDateTime ( epochNanoseconds, timeZone, calendar [ ,
+ * newTarget ] )
+ */
+ZonedDateTimeObject* CreateTemporalZonedDateTime(
+ JSContext* cx, const Instant& instant, JS::Handle<TimeZoneValue> timeZone,
+ JS::Handle<CalendarValue> calendar);
+
+/**
+ * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ ,
+ * overflow ] )
+ */
+bool AddDaysToZonedDateTime(JSContext* cx, const Instant& instant,
+ const PlainDateTime& dateTime,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::Handle<CalendarValue> calendar, double days,
+ TemporalOverflow overflow, Instant* result);
+
+/**
+ * AddDaysToZonedDateTime ( instant, dateTime, timeZoneRec, calendar, days [ ,
+ * overflow ] )
+ */
+bool AddDaysToZonedDateTime(JSContext* cx, const Instant& instant,
+ const PlainDateTime& dateTime,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::Handle<CalendarValue> calendar, double days,
+ Instant* result);
+
+/**
+ * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months,
+ * weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds
+ * [ , precalculatedPlainDateTime [ , options ] ] )
+ */
+bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::Handle<CalendarRecord> calendar,
+ const Duration& duration, Instant* result);
+
+/**
+ * AddZonedDateTime ( epochNanoseconds, timeZoneRec, calendarRec, years, months,
+ * weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds
+ * [ , precalculatedPlainDateTime [ , options ] ] )
+ */
+bool AddZonedDateTime(JSContext* cx, const Instant& epochNanoseconds,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::Handle<CalendarRecord> calendar,
+ const Duration& duration, const PlainDateTime& dateTime,
+ Instant* result);
+
+/**
+ * DifferenceZonedDateTime ( ns1, ns2, timeZoneRec, calendarRec, largestUnit,
+ * options, precalculatedPlainDateTime )
+ */
+bool DifferenceZonedDateTime(JSContext* cx, const Instant& ns1,
+ const Instant& ns2,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::Handle<CalendarRecord> calendar,
+ TemporalUnit largestUnit,
+ const PlainDateTime& precalculatedPlainDateTime,
+ Duration* result);
+
+struct NanosecondsAndDays final {
+ JS::BigInt* days = nullptr;
+ int64_t daysInt = 0;
+ InstantSpan nanoseconds;
+ InstantSpan dayLength;
+
+ double daysNumber() const;
+
+ void trace(JSTracer* trc);
+
+ static NanosecondsAndDays from(int64_t days, const InstantSpan& nanoseconds,
+ const InstantSpan& dayLength) {
+ return {nullptr, days, nanoseconds, dayLength};
+ }
+
+ static NanosecondsAndDays from(JS::BigInt* days,
+ const InstantSpan& nanoseconds,
+ const InstantSpan& dayLength) {
+ return {days, 0, nanoseconds, dayLength};
+ }
+};
+
+/**
+ * NanosecondsToDays ( nanoseconds, zonedRelativeTo, timeZoneRec [ ,
+ * precalculatedPlainDateTime ] )
+ */
+bool NanosecondsToDays(JSContext* cx, const InstantSpan& nanoseconds,
+ JS::Handle<ZonedDateTime> zonedRelativeTo,
+ JS::Handle<TimeZoneRecord> timeZone,
+ JS::MutableHandle<NanosecondsAndDays> result);
+
+/**
+ * NanosecondsToDays ( nanoseconds, zonedRelativeTo, timeZoneRec [ ,
+ * precalculatedPlainDateTime ] )
+ */
+bool NanosecondsToDays(JSContext* cx, const InstantSpan& nanoseconds,
+ JS::Handle<ZonedDateTime> zonedRelativeTo,
+ JS::Handle<TimeZoneRecord> timeZone,
+ const PlainDateTime& precalculatedPlainDateTime,
+ JS::MutableHandle<NanosecondsAndDays> result);
+
+enum class OffsetBehaviour { Option, Exact, Wall };
+
+enum class MatchBehaviour { MatchExactly, MatchMinutes };
+
+/**
+ * InterpretISODateTimeOffset ( year, month, day, hour, minute, second,
+ * millisecond, microsecond, nanosecond, offsetBehaviour, offsetNanoseconds,
+ * timeZoneRec, disambiguation, offsetOption, matchBehaviour )
+ */
+bool InterpretISODateTimeOffset(JSContext* cx, const PlainDateTime& dateTime,
+ OffsetBehaviour offsetBehaviour,
+ int64_t offsetNanoseconds,
+ JS::Handle<TimeZoneRecord> timeZone,
+ TemporalDisambiguation disambiguation,
+ TemporalOffset offsetOption,
+ MatchBehaviour matchBehaviour, Instant* result);
+
+} /* namespace js::temporal */
+
+namespace js {
+
+template <typename Wrapper>
+class WrappedPtrOperations<temporal::ZonedDateTime, Wrapper> {
+ const auto& container() const {
+ return static_cast<const Wrapper*>(this)->get();
+ }
+
+ public:
+ explicit operator bool() const { return bool(container()); }
+
+ const auto& instant() const { return container().instant(); }
+
+ JS::Handle<temporal::TimeZoneValue> timeZone() const {
+ return JS::Handle<temporal::TimeZoneValue>::fromMarkedLocation(
+ container().timeZoneDoNotUse());
+ }
+
+ JS::Handle<temporal::CalendarValue> calendar() const {
+ return JS::Handle<temporal::CalendarValue>::fromMarkedLocation(
+ container().calendarDoNotUse());
+ }
+};
+
+template <typename Wrapper>
+class WrappedPtrOperations<temporal::NanosecondsAndDays, Wrapper> {
+ const auto& object() const {
+ return static_cast<const Wrapper*>(this)->get();
+ }
+
+ public:
+ double daysNumber() const { return object().daysNumber(); }
+
+ JS::Handle<JS::BigInt*> days() const {
+ return JS::Handle<JS::BigInt*>::fromMarkedLocation(&object().days);
+ }
+
+ int64_t daysInt() const { return object().daysInt; }
+
+ temporal::InstantSpan nanoseconds() const { return object().nanoseconds; }
+
+ temporal::InstantSpan dayLength() const { return object().dayLength; }
+};
+
+} /* namespace js */
+
+#endif /* builtin_temporal_ZonedDateTime_h */