LCOV - code coverage report
Current view: top level - js/public - Date.h (source / functions) Hit Total Coverage
Test: output.info Lines: 9 12 75.0 %
Date: 2017-07-14 16:53:18 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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/. */
       5             : 
       6             : /* JavaScript date/time computation and creation functions. */
       7             : 
       8             : #ifndef js_Date_h
       9             : #define js_Date_h
      10             : 
      11             : /*
      12             :  * Dates in JavaScript are defined by IEEE-754 double precision numbers from
      13             :  * the set:
      14             :  *
      15             :  *   { t ∈ ℕ : -8.64e15 ≤ t ≤ +8.64e15 } ∪ { NaN }
      16             :  *
      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.
      22             :  *
      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.
      27             :  *
      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.
      30             :  */
      31             : 
      32             : #include "mozilla/FloatingPoint.h"
      33             : #include "mozilla/MathAlgorithms.h"
      34             : 
      35             : #include "js/Conversions.h"
      36             : #include "js/Value.h"
      37             : 
      38             : struct JSContext;
      39             : 
      40             : namespace JS {
      41             : 
      42             : /**
      43             :  * Re-query the system to determine the current time zone adjustment from UTC,
      44             :  * including any component due to DST.  If the time zone has changed, this will
      45             :  * cause all Date object non-UTC methods and formatting functions to produce
      46             :  * appropriately adjusted results.
      47             :  *
      48             :  * Left to its own devices, SpiderMonkey itself may occasionally call this
      49             :  * method to attempt to keep up with system time changes.  However, no
      50             :  * particular frequency of checking is guaranteed.  Embedders unable to accept
      51             :  * occasional inaccuracies should call this method in response to system time
      52             :  * changes, or immediately before operations requiring instantaneous
      53             :  * correctness, to guarantee correct behavior.
      54             :  */
      55             : extern JS_PUBLIC_API(void)
      56             : ResetTimeZone();
      57             : 
      58             : class ClippedTime;
      59             : inline ClippedTime TimeClip(double time);
      60             : 
      61             : /*
      62             :  * |ClippedTime| represents the limited subset of dates/times described above.
      63             :  *
      64             :  * An invalid date/time may be created through the |ClippedTime::invalid|
      65             :  * method.  Otherwise, a |ClippedTime| may be created using the |TimeClip|
      66             :  * method.
      67             :  *
      68             :  * In typical use, the user might wish to manipulate a timestamp.  The user
      69             :  * performs a series of operations on it, but the final value might not be a
      70             :  * date as defined above -- it could have overflowed, acquired a fractional
      71             :  * component, &c.  So as a *final* step, the user passes that value through
      72             :  * |TimeClip| to produce a number restricted to JavaScript's date range.
      73             :  *
      74             :  * APIs that accept a JavaScript date value thus accept a |ClippedTime|, not a
      75             :  * double.  This ensures that date/time APIs will only ever receive acceptable
      76             :  * JavaScript dates.  This also forces users to perform any desired clipping,
      77             :  * as only the user knows what behavior is desired when clipping occurs.
      78             :  */
      79             : class ClippedTime
      80             : {
      81             :     double t;
      82             : 
      83         120 :     explicit ClippedTime(double time) : t(time) {}
      84             :     friend ClippedTime TimeClip(double time);
      85             : 
      86             :   public:
      87             :     // Create an invalid date.
      88          16 :     ClippedTime() : t(mozilla::UnspecifiedNaN<double>()) {}
      89             : 
      90             :     // Create an invalid date/time, more explicitly; prefer this to the default
      91             :     // constructor.
      92           0 :     static ClippedTime invalid() { return ClippedTime(); }
      93             : 
      94         137 :     double toDouble() const { return t; }
      95             : 
      96           0 :     bool isValid() const { return !mozilla::IsNaN(t); }
      97             : };
      98             : 
      99             : // ES6 20.3.1.15.
     100             : //
     101             : // Clip a double to JavaScript's date range (or to an invalid date) using the
     102             : // ECMAScript TimeClip algorithm.
     103             : inline ClippedTime
     104         120 : TimeClip(double time)
     105             : {
     106             :     // Steps 1-2.
     107         120 :     const double MaxTimeMagnitude = 8.64e15;
     108         120 :     if (!mozilla::IsFinite(time) || mozilla::Abs(time) > MaxTimeMagnitude)
     109           0 :         return ClippedTime(mozilla::UnspecifiedNaN<double>());
     110             : 
     111             :     // Step 3.
     112         120 :     return ClippedTime(ToInteger(time) + (+0.0));
     113             : }
     114             : 
     115             : // Produce a double Value from the given time.  Because times may be NaN,
     116             : // prefer using this to manual canonicalization.
     117             : inline Value
     118         121 : TimeValue(ClippedTime time)
     119             : {
     120         121 :     return DoubleValue(JS::CanonicalizeNaN(time.toDouble()));
     121             : }
     122             : 
     123             : // Create a new Date object whose [[DateValue]] internal slot contains the
     124             : // clipped |time|.  (Users who must represent times outside that range must use
     125             : // another representation.)
     126             : extern JS_PUBLIC_API(JSObject*)
     127             : NewDateObject(JSContext* cx, ClippedTime time);
     128             : 
     129             : // Year is a year, month is 0-11, day is 1-based.  The return value is a number
     130             : // of milliseconds since the epoch.
     131             : //
     132             : // Consistent with the MakeDate algorithm defined in ECMAScript, this value is
     133             : // *not* clipped!  Use JS::TimeClip if you need a clipped date.
     134             : JS_PUBLIC_API(double)
     135             : MakeDate(double year, unsigned month, unsigned day);
     136             : 
     137             : // Year is a year, month is 0-11, day is 1-based, and time is in milliseconds.
     138             : // The return value is a number of milliseconds since the epoch.
     139             : //
     140             : // Consistent with the MakeDate algorithm defined in ECMAScript, this value is
     141             : // *not* clipped!  Use JS::TimeClip if you need a clipped date.
     142             : JS_PUBLIC_API(double)
     143             : MakeDate(double year, unsigned month, unsigned day, double time);
     144             : 
     145             : // Takes an integer number of milliseconds since the epoch and returns the
     146             : // year.  Can return NaN, and will do so if NaN is passed in.
     147             : JS_PUBLIC_API(double)
     148             : YearFromTime(double time);
     149             : 
     150             : // Takes an integer number of milliseconds since the epoch and returns the
     151             : // month (0-11).  Can return NaN, and will do so if NaN is passed in.
     152             : JS_PUBLIC_API(double)
     153             : MonthFromTime(double time);
     154             : 
     155             : // Takes an integer number of milliseconds since the epoch and returns the
     156             : // day (1-based).  Can return NaN, and will do so if NaN is passed in.
     157             : JS_PUBLIC_API(double)
     158             : DayFromTime(double time);
     159             : 
     160             : // Takes an integer year and returns the number of days from epoch to the given
     161             : // year.
     162             : // NOTE: The calculation performed by this function is literally that given in
     163             : // the ECMAScript specification.  Nonfinite years, years containing fractional
     164             : // components, and years outside ECMAScript's date range are not handled with
     165             : // any particular intelligence.  Garbage in, garbage out.
     166             : JS_PUBLIC_API(double)
     167             : DayFromYear(double year);
     168             : 
     169             : // Takes an integer number of milliseconds since the epoch and an integer year,
     170             : // returns the number of days in that year. If |time| is nonfinite, returns NaN.
     171             : // Otherwise |time| *must* correspond to a time within the valid year |year|.
     172             : // This should usually be ensured by computing |year| as |JS::DayFromYear(time)|.
     173             : JS_PUBLIC_API(double)
     174             : DayWithinYear(double time, double year);
     175             : 
     176             : // Sets the time resolution for fingerprinting protection.
     177             : // If it's set to zero, then no rounding will happen.
     178             : JS_PUBLIC_API(void)
     179             : SetTimeResolutionUsec(uint32_t resolution);
     180             : 
     181             : } // namespace JS
     182             : 
     183             : #endif /* js_Date_h */

Generated by: LCOV version 1.13