summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/temporal/TemporalTypes.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /js/src/builtin/temporal/TemporalTypes.h
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/builtin/temporal/TemporalTypes.h')
-rw-r--r--js/src/builtin/temporal/TemporalTypes.h240
1 files changed, 188 insertions, 52 deletions
diff --git a/js/src/builtin/temporal/TemporalTypes.h b/js/src/builtin/temporal/TemporalTypes.h
index 654fd65a3b..b645a9a175 100644
--- a/js/src/builtin/temporal/TemporalTypes.h
+++ b/js/src/builtin/temporal/TemporalTypes.h
@@ -11,7 +11,9 @@
#include "mozilla/CheckedInt.h"
#include <stdint.h>
+#include <type_traits>
+#include "builtin/temporal/Int128.h"
#include "builtin/temporal/TemporalUnit.h"
namespace js::temporal {
@@ -181,15 +183,19 @@ struct SecondsAndNanoseconds {
/**
* Return the nanoseconds value.
- *
- * The returned nanoseconds amount can be invalid on overflow. The caller is
- * responsible for handling the overflow case.
*/
- constexpr mozilla::CheckedInt64 toNanoseconds() const {
- mozilla::CheckedInt64 nanos = seconds;
- nanos *= ToNanoseconds(TemporalUnit::Second);
- nanos += nanoseconds;
- return nanos;
+ constexpr Int128 toNanoseconds() const {
+ return Int128{seconds} * Int128{ToNanoseconds(TemporalUnit::Second)} +
+ Int128{nanoseconds};
+ }
+
+ /**
+ * Cast to a different representation.
+ */
+ template <class Other>
+ constexpr Other to() const {
+ static_assert(std::is_base_of_v<SecondsAndNanoseconds<Other>, Other>);
+ return Other{seconds, nanoseconds};
}
/**
@@ -209,7 +215,7 @@ struct SecondsAndNanoseconds {
*/
static constexpr Derived fromMilliseconds(int64_t milliseconds) {
int64_t seconds = milliseconds / 1'000;
- int32_t millis = milliseconds % 1'000;
+ int32_t millis = int32_t(milliseconds % 1'000);
if (millis < 0) {
seconds -= 1;
millis += 1'000;
@@ -222,7 +228,7 @@ struct SecondsAndNanoseconds {
*/
static constexpr Derived fromMicroseconds(int64_t microseconds) {
int64_t seconds = microseconds / 1'000'000;
- int32_t micros = microseconds % 1'000'000;
+ int32_t micros = int32_t(microseconds % 1'000'000);
if (micros < 0) {
seconds -= 1;
micros += 1'000'000;
@@ -235,7 +241,21 @@ struct SecondsAndNanoseconds {
*/
static constexpr Derived fromNanoseconds(int64_t nanoseconds) {
int64_t seconds = nanoseconds / 1'000'000'000;
- int32_t nanos = nanoseconds % 1'000'000'000;
+ int32_t nanos = int32_t(nanoseconds % 1'000'000'000);
+ if (nanos < 0) {
+ seconds -= 1;
+ nanos += 1'000'000'000;
+ }
+ return {seconds, nanos};
+ }
+
+ /**
+ * Create from a nanoseconds value.
+ */
+ static constexpr Derived fromNanoseconds(const Int128& nanoseconds) {
+ auto div = nanoseconds.divrem(Int128{1'000'000'000});
+ int64_t seconds = int64_t(div.first);
+ int32_t nanos = int32_t(div.second);
if (nanos < 0) {
seconds -= 1;
nanos += 1'000'000'000;
@@ -365,6 +385,32 @@ struct Instant final : SecondsAndNanoseconds<Instant> {
static constexpr Instant min() { return -max(); }
};
+// Minimum and maximum valid epoch day relative to midnight at the beginning of
+// 1 January 1970 UTC.
+//
+// NOTE in ISODateTimeWithinLimits:
+//
+// Temporal.PlainDateTime objects can represent points in time within 24 hours
+// (8.64 × 10**13 nanoseconds) of the Temporal.Instant boundaries. This ensures
+// that a Temporal.Instant object can be converted into a Temporal.PlainDateTime
+// object using any time zone.
+//
+// This limits the maximum valid date-time to +275760-09-13T23:59:59.999Z and
+// the minimum valid date-time -271821-04-19T00:00:00.001Z. The corresponding
+// maximum and minimum valid date values are therefore +275760-09-13 and
+// -271821-04-19. There are exactly 100'000'000 days from 1 January 1970 UTC to
+// the maximum valid date and -100'000'001 days to the minimum valid date.
+constexpr inline int32_t MinEpochDay = -100'000'001;
+constexpr inline int32_t MaxEpochDay = 100'000'000;
+
+static_assert(MinEpochDay ==
+ Instant::min().seconds / ToSeconds(TemporalUnit::Day) - 1);
+static_assert(MaxEpochDay ==
+ Instant::max().seconds / ToSeconds(TemporalUnit::Day));
+
+// Maximum number of days between two valid epoch days.
+constexpr inline int32_t MaxEpochDaysDuration = MaxEpochDay - MinEpochDay;
+
/**
* Plain date represents a date in the ISO 8601 calendar.
*/
@@ -437,6 +483,9 @@ struct PlainDateTime final {
}
};
+struct DateDuration;
+struct TimeDuration;
+
/**
* Duration represents the difference between dates or times. Each duration
* component is an integer and all components must have the same sign.
@@ -453,7 +502,7 @@ struct Duration final {
double microseconds = 0;
double nanoseconds = 0;
- bool operator==(const Duration& other) const {
+ constexpr bool operator==(const Duration& other) const {
return years == other.years && months == other.months &&
weeks == other.weeks && days == other.days && hours == other.hours &&
minutes == other.minutes && seconds == other.seconds &&
@@ -462,35 +511,14 @@ struct Duration final {
nanoseconds == other.nanoseconds;
}
- bool operator!=(const Duration& other) const { return !(*this == other); }
-
- /**
- * Return the date components of this duration.
- */
- Duration date() const { return {years, months, weeks, days}; }
-
- /**
- * Return the time components of this duration.
- */
- Duration time() const {
- return {
- 0,
- 0,
- 0,
- 0,
- hours,
- minutes,
- seconds,
- milliseconds,
- microseconds,
- nanoseconds,
- };
+ constexpr bool operator!=(const Duration& other) const {
+ return !(*this == other);
}
/**
* Return a new duration with every component negated.
*/
- Duration negate() const {
+ constexpr Duration negate() const {
// Add zero to convert -0 to +0.
return {
-years + (+0.0), -months + (+0.0), -weeks + (+0.0),
@@ -499,6 +527,11 @@ struct Duration final {
-nanoseconds + (+0.0),
};
}
+
+ /**
+ * Return the date components of this duration.
+ */
+ inline DateDuration toDateDuration() const;
};
/**
@@ -506,41 +539,144 @@ struct Duration final {
* component is an integer and all components must have the same sign.
*/
struct DateDuration final {
- double years = 0;
- double months = 0;
- double weeks = 0;
- double days = 0;
+ // abs(years) < 2**32
+ int64_t years = 0;
+
+ // abs(months) < 2**32
+ int64_t months = 0;
+
+ // abs(weeks) < 2**32
+ int64_t weeks = 0;
+
+ // abs(days) < ⌈(2**53) / (24 * 60 * 60)⌉
+ int64_t days = 0;
- Duration toDuration() { return {years, months, weeks, days}; }
+ constexpr bool operator==(const DateDuration& other) const {
+ return years == other.years && months == other.months &&
+ weeks == other.weeks && days == other.days;
+ }
+
+ constexpr bool operator!=(const DateDuration& other) const {
+ return !(*this == other);
+ }
+
+ constexpr Duration toDuration() const {
+ return {
+ double(years),
+ double(months),
+ double(weeks),
+ double(days),
+ };
+ }
};
+inline DateDuration Duration::toDateDuration() const {
+ return {int64_t(years), int64_t(months), int64_t(weeks), int64_t(days)};
+}
+
/**
* Time duration represents the difference between times. Each duration
* component is an integer and all components must have the same sign.
*/
struct TimeDuration final {
- double days = 0;
- double hours = 0;
- double minutes = 0;
- double seconds = 0;
- double milliseconds = 0;
+ // abs(days) < ⌈(2**53) / (24 * 60 * 60)⌉
+ int64_t days = 0;
+
+ // abs(hours) < ⌈(2**53) / (60 * 60)⌉
+ int64_t hours = 0;
+
+ // abs(minutes) < ⌈(2**53) / 60⌉
+ int64_t minutes = 0;
+
+ // abs(seconds) < (2**53)
+ int64_t seconds = 0;
+
+ // abs(milliseconds) < (2**53) * (1000**1)
+ int64_t milliseconds = 0;
+
+ // abs(microseconds) < (2**53) * (1000**2)
double microseconds = 0;
+
+ // abs(nanoseconds) < (2**53) * (1000**3)
double nanoseconds = 0;
- Duration toDuration() {
+ constexpr Duration toDuration() const {
return {0,
0,
0,
- days,
- hours,
- minutes,
- seconds,
- milliseconds,
+ double(days),
+ double(hours),
+ double(minutes),
+ double(seconds),
+ double(milliseconds),
microseconds,
nanoseconds};
}
};
+/**
+ * Normalized time duration with a seconds value in the range
+ * [-9'007'199'254'740'991, +9'007'199'254'740'991] and a nanoseconds value in
+ * the range [0, 999'999'999].
+ */
+struct NormalizedTimeDuration final
+ : SecondsAndNanoseconds<NormalizedTimeDuration> {
+ constexpr NormalizedTimeDuration& operator+=(
+ const NormalizedTimeDuration& other) {
+ *this = add(*this, other);
+ return *this;
+ }
+
+ constexpr NormalizedTimeDuration& operator-=(
+ const NormalizedTimeDuration& other) {
+ *this = subtract(*this, other);
+ return *this;
+ }
+
+ constexpr NormalizedTimeDuration operator+(
+ const NormalizedTimeDuration& other) const {
+ return add(*this, other);
+ }
+
+ constexpr NormalizedTimeDuration operator-(
+ const NormalizedTimeDuration& other) const {
+ return subtract(*this, other);
+ }
+
+ constexpr NormalizedTimeDuration operator-() const { return negate(*this); }
+
+ /**
+ * Returns the maximum normalized time duration value.
+ */
+ static constexpr NormalizedTimeDuration max() {
+ constexpr int64_t seconds = 0x1f'ffff'ffff'ffff;
+ constexpr int64_t nanos = 999'999'999;
+ return {seconds, nanos};
+ }
+
+ /**
+ * Returns the minimum normalized time duration value.
+ */
+ static constexpr NormalizedTimeDuration min() { return -max(); }
+};
+
+/**
+ * Duration represents the difference between dates or times. Each duration
+ * component is an integer and all components must have the same sign.
+ */
+struct NormalizedDuration final {
+ DateDuration date;
+ NormalizedTimeDuration time;
+
+ constexpr bool operator==(const NormalizedDuration& other) const {
+ return date == other.date && time == other.time;
+ }
+
+ constexpr bool operator!=(const NormalizedDuration& other) const {
+ return !(*this == other);
+ }
+};
+
} /* namespace js::temporal */
#endif /* builtin_temporal_TemporalTypes_h */