Bug 1814798 - pt 1. Add bool to enable/disable PHC at runtime r=glandium
[gecko.git] / js / public / Date.h
blobdd82415624e1f05eaad818d68b8588ffb1b64ab1
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* JavaScript date/time computation and creation functions. */
8 #ifndef js_Date_h
9 #define js_Date_h
12 * Dates in JavaScript are defined by IEEE-754 double precision numbers from
13 * the set:
15 * { t ∈ ℕ : -8.64e15 ≤ t ≤ +8.64e15 } ∪ { NaN }
17 * The single NaN value represents any invalid-date value. All other values
18 * represent idealized durations in milliseconds since the UTC epoch. (Leap
19 * seconds are ignored; leap days are not.) +0 is the only zero in this set.
20 * The limit represented by 8.64e15 milliseconds is 100 million days either
21 * side of 00:00 January 1, 1970 UTC.
23 * Dates in the above set are represented by the |ClippedTime| class. The
24 * double type is a superset of the above set, so it *may* (but need not)
25 * represent a date. Use ECMAScript's |TimeClip| method to produce a date from
26 * a double.
28 * Date *objects* are simply wrappers around |TimeClip|'d numbers, with a bunch
29 * of accessor methods to the various aspects of the represented date.
32 #include "mozilla/FloatingPoint.h" // mozilla::{IsFinite,}, mozilla::UnspecifiedNaN
33 #include "mozilla/MathAlgorithms.h" // mozilla::Abs
35 #include "js/Conversions.h" // JS::ToInteger
36 #include "js/TypeDecls.h"
37 #include "js/Value.h" // JS::CanonicalizeNaN, JS::DoubleValue, JS::Value
39 namespace JS {
41 /**
42 * Re-query the system to determine the current time zone adjustment from UTC,
43 * including any component due to DST. If the time zone has changed, this will
44 * cause all Date object non-UTC methods and formatting functions to produce
45 * appropriately adjusted results.
47 * Left to its own devices, SpiderMonkey itself may occasionally try to detect
48 * system time changes. However, no particular frequency of checking is
49 * guaranteed. Embedders unable to accept occasional inaccuracies should call
50 * this method in response to system time changes, or immediately before
51 * operations requiring instantaneous correctness, to guarantee correct
52 * behavior.
54 extern JS_PUBLIC_API void ResetTimeZone();
56 class ClippedTime;
57 inline ClippedTime TimeClip(double time);
60 * |ClippedTime| represents the limited subset of dates/times described above.
62 * An invalid date/time may be created through the |ClippedTime::invalid|
63 * method. Otherwise, a |ClippedTime| may be created using the |TimeClip|
64 * method.
66 * In typical use, the user might wish to manipulate a timestamp. The user
67 * performs a series of operations on it, but the final value might not be a
68 * date as defined above -- it could have overflowed, acquired a fractional
69 * component, &c. So as a *final* step, the user passes that value through
70 * |TimeClip| to produce a number restricted to JavaScript's date range.
72 * APIs that accept a JavaScript date value thus accept a |ClippedTime|, not a
73 * double. This ensures that date/time APIs will only ever receive acceptable
74 * JavaScript dates. This also forces users to perform any desired clipping,
75 * as only the user knows what behavior is desired when clipping occurs.
77 class ClippedTime {
78 double t = mozilla::UnspecifiedNaN<double>();
80 explicit ClippedTime(double time) : t(time) {}
81 friend ClippedTime TimeClip(double time);
83 public:
84 // Create an invalid date.
85 ClippedTime() = default;
87 // Create an invalid date/time, more explicitly; prefer this to the default
88 // constructor.
89 static ClippedTime invalid() { return ClippedTime(); }
91 double toDouble() const { return t; }
93 bool isValid() const { return !std::isnan(t); }
96 // ES6 20.3.1.15.
98 // Clip a double to JavaScript's date range (or to an invalid date) using the
99 // ECMAScript TimeClip algorithm.
100 inline ClippedTime TimeClip(double time) {
101 // Steps 1-2.
102 const double MaxTimeMagnitude = 8.64e15;
103 if (!std::isfinite(time) || mozilla::Abs(time) > MaxTimeMagnitude) {
104 return ClippedTime(mozilla::UnspecifiedNaN<double>());
107 // Step 3.
108 return ClippedTime(ToInteger(time));
111 // Produce a double Value from the given time. Because times may be NaN,
112 // prefer using this to manual canonicalization.
113 inline Value TimeValue(ClippedTime time) {
114 return CanonicalizedDoubleValue(time.toDouble());
117 // Create a new Date object whose [[DateValue]] internal slot contains the
118 // clipped |time|. (Users who must represent times outside that range must use
119 // another representation.)
120 extern JS_PUBLIC_API JSObject* NewDateObject(JSContext* cx, ClippedTime time);
123 * Create a new Date object for a year/month/day-of-month/hour/minute/second.
125 * The created date is initialized with the time value
127 * TimeClip(UTC(MakeDate(MakeDay(year, mon, mday),
128 * MakeTime(hour, min, sec, 0.0))))
130 * where each function/operation is as specified in ECMAScript.
132 extern JS_PUBLIC_API JSObject* NewDateObject(JSContext* cx, int year, int mon,
133 int mday, int hour, int min,
134 int sec);
137 * On success, returns true, setting |*isDate| to true if |obj| is a Date
138 * object or a wrapper around one, or to false if not. Returns false on
139 * failure.
141 * This method returns true with |*isDate == false| when passed an ES6 proxy
142 * whose target is a Date, or when passed a revoked proxy.
144 extern JS_PUBLIC_API bool ObjectIsDate(JSContext* cx, Handle<JSObject*> obj,
145 bool* isDate);
147 // Year is a year, month is 0-11, day is 1-based. The return value is a number
148 // of milliseconds since the epoch.
150 // Consistent with the MakeDate algorithm defined in ECMAScript, this value is
151 // *not* clipped! Use JS::TimeClip if you need a clipped date.
152 JS_PUBLIC_API double MakeDate(double year, unsigned month, unsigned day);
154 // Year is a year, month is 0-11, day is 1-based, and time is in milliseconds.
155 // The return value is a number of milliseconds since the epoch.
157 // Consistent with the MakeDate algorithm defined in ECMAScript, this value is
158 // *not* clipped! Use JS::TimeClip if you need a clipped date.
159 JS_PUBLIC_API double MakeDate(double year, unsigned month, unsigned day,
160 double time);
162 // Takes an integer number of milliseconds since the epoch and returns the
163 // year. Can return NaN, and will do so if NaN is passed in.
164 JS_PUBLIC_API double YearFromTime(double time);
166 // Takes an integer number of milliseconds since the epoch and returns the
167 // month (0-11). Can return NaN, and will do so if NaN is passed in.
168 JS_PUBLIC_API double MonthFromTime(double time);
170 // Takes an integer number of milliseconds since the epoch and returns the
171 // day (1-based). Can return NaN, and will do so if NaN is passed in.
172 JS_PUBLIC_API double DayFromTime(double time);
174 // Takes an integer year and returns the number of days from epoch to the given
175 // year.
176 // NOTE: The calculation performed by this function is literally that given in
177 // the ECMAScript specification. Nonfinite years, years containing fractional
178 // components, and years outside ECMAScript's date range are not handled with
179 // any particular intelligence. Garbage in, garbage out.
180 JS_PUBLIC_API double DayFromYear(double year);
182 // Takes an integer number of milliseconds since the epoch and an integer year,
183 // returns the number of days in that year. If |time| is nonfinite, returns NaN.
184 // Otherwise |time| *must* correspond to a time within the valid year |year|.
185 // This should usually be ensured by computing |year| as
186 // |JS::DayFromYear(time)|.
187 JS_PUBLIC_API double DayWithinYear(double time, double year);
189 // The callback will be a wrapper function that accepts a double (the time
190 // to clamp and jitter). Inside the JS Engine, other parameters that may be
191 // needed are all constant, so they are handled inside the wrapper function
192 using ReduceMicrosecondTimePrecisionCallback = double (*)(double, JSContext*);
194 // Set a callback into the toolkit/components/resistfingerprinting function that
195 // will centralize time resolution and jitter into one place.
196 JS_PUBLIC_API void SetReduceMicrosecondTimePrecisionCallback(
197 ReduceMicrosecondTimePrecisionCallback callback);
199 // Sets the time resolution for fingerprinting protection, and whether jitter
200 // should occur. If resolution is set to zero, then no rounding or jitter will
201 // occur. This is used if the callback above is not specified.
202 JS_PUBLIC_API void SetTimeResolutionUsec(uint32_t resolution, bool jitter);
204 } // namespace JS
206 #endif /* js_Date_h */