Bug 834988 - Clarify that all the DST-offset methods take a time in UTC seconds, and that the internal fields store UTC values. Also add documentation comments by the related methods. r=dmandelin
authorJeff Walden <jwalden@mit.edu>
Fri, 25 Jan 2013 16:50:24 -0800
changeset 130024 aba0f5b6013c55a4903ae60f35e5124d70773d53
parent 130023 42042277940bacaf8442d5ec79ed2b078c5ab806
child 130025 4baea9b16379fe875c96dcee6928b23e88387539
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmandelin
bugs834988
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 834988 - Clarify that all the DST-offset methods take a time in UTC seconds, and that the internal fields store UTC values. Also add documentation comments by the related methods. r=dmandelin
js/src/jsdate.cpp
js/src/vm/DateTime.cpp
js/src/vm/DateTime.h
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -392,18 +392,18 @@ DaylightSavingTA(double t, DateTimeInfo 
      * many OSes, map it to an equivalent year before asking.
      */
     if (t < 0.0 || t > 2145916800000.0) {
         int year = EquivalentYearForDST(int(YearFromTime(t)));
         double day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
         t = MakeDate(day, TimeWithinDay(t));
     }
 
-    int64_t timeMilliseconds = static_cast<int64_t>(t);
-    int64_t offsetMilliseconds = dtInfo->getDSTOffsetMilliseconds(timeMilliseconds);
+    int64_t utcMilliseconds = static_cast<int64_t>(t);
+    int64_t offsetMilliseconds = dtInfo->getDSTOffsetMilliseconds(utcMilliseconds);
     return static_cast<double>(offsetMilliseconds);
 }
 
 static double
 AdjustTime(double date, DateTimeInfo *dtInfo)
 {
     double t = DaylightSavingTA(date, dtInfo) + dtInfo->localTZA();
     t = (dtInfo->localTZA() >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
--- a/js/src/vm/DateTime.cpp
+++ b/js/src/vm/DateTime.cpp
@@ -156,123 +156,117 @@ js::DateTimeInfo::DateTimeInfo()
 {
     // Set to a totally impossible TZA so that the comparison above will fail
     // and all fields will be properly initialized.
     localTZA_ = MOZ_DOUBLE_NaN();
     updateTimeZoneAdjustment();
 }
 
 int64_t
-js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t localTimeSeconds)
+js::DateTimeInfo::computeDSTOffsetMilliseconds(int64_t utcSeconds)
 {
-    MOZ_ASSERT(localTimeSeconds >= 0);
-    MOZ_ASSERT(localTimeSeconds <= MaxUnixTimeT);
+    MOZ_ASSERT(utcSeconds >= 0);
+    MOZ_ASSERT(utcSeconds <= MaxUnixTimeT);
 
 #if defined(XP_WIN)
     // Windows does not follow POSIX. Updates to the TZ environment variable
     // are not reflected immediately on that platform as they are on UNIX
     // systems without this call.
     _tzset();
 #endif
 
     struct tm tm;
-    if (!ComputeLocalTime(static_cast<time_t>(localTimeSeconds), &tm))
+    if (!ComputeLocalTime(static_cast<time_t>(utcSeconds), &tm))
         return 0;
 
-    int32_t utcToLocalOffsetSeconds = UTCToLocalStandardOffsetSeconds();
-
-    int32_t dayoff = int32_t((localTimeSeconds + utcToLocalOffsetSeconds) % SecondsPerDay);
+    int32_t dayoff = int32_t((utcSeconds + UTCToLocalStandardOffsetSeconds()) % SecondsPerDay);
     int32_t tmoff = tm.tm_sec + (tm.tm_min * SecondsPerMinute) + (tm.tm_hour * SecondsPerHour);
 
     int32_t diff = tmoff - dayoff;
 
     if (diff < 0)
         diff += SecondsPerDay;
 
     return diff * msPerSecond;
 }
 
 int64_t
-js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t localTimeMilliseconds)
+js::DateTimeInfo::getDSTOffsetMilliseconds(int64_t utcMilliseconds)
 {
     sanityCheck();
 
-    int64_t localTimeSeconds = localTimeMilliseconds / msPerSecond;
+    int64_t utcSeconds = utcMilliseconds / msPerSecond;
 
-    if (localTimeSeconds > MaxUnixTimeT) {
-        localTimeSeconds = MaxUnixTimeT;
-    } else if (localTimeSeconds < 0) {
+    if (utcSeconds > MaxUnixTimeT) {
+        utcSeconds = MaxUnixTimeT;
+    } else if (utcSeconds < 0) {
         /* Go ahead a day to make localtime work (does not work with 0). */
-        localTimeSeconds = SecondsPerDay;
+        utcSeconds = SecondsPerDay;
     }
 
     /*
      * NB: Be aware of the initial range values when making changes to this
      *     code: the first call to this method, with those initial range
      *     values, must result in a cache miss.
      */
 
-    if (rangeStartSeconds <= localTimeSeconds &&
-        localTimeSeconds <= rangeEndSeconds) {
+    if (rangeStartSeconds <= utcSeconds && utcSeconds <= rangeEndSeconds)
         return offsetMilliseconds;
-    }
 
-    if (oldRangeStartSeconds <= localTimeSeconds &&
-        localTimeSeconds <= oldRangeEndSeconds) {
+    if (oldRangeStartSeconds <= utcSeconds && utcSeconds <= oldRangeEndSeconds)
         return oldOffsetMilliseconds;
-    }
 
     oldOffsetMilliseconds = offsetMilliseconds;
     oldRangeStartSeconds = rangeStartSeconds;
     oldRangeEndSeconds = rangeEndSeconds;
 
-    if (rangeStartSeconds <= localTimeSeconds) {
+    if (rangeStartSeconds <= utcSeconds) {
         int64_t newEndSeconds = Min(rangeEndSeconds + RangeExpansionAmount, MaxUnixTimeT);
-        if (newEndSeconds >= localTimeSeconds) {
+        if (newEndSeconds >= utcSeconds) {
             int64_t endOffsetMilliseconds = computeDSTOffsetMilliseconds(newEndSeconds);
             if (endOffsetMilliseconds == offsetMilliseconds) {
                 rangeEndSeconds = newEndSeconds;
                 return offsetMilliseconds;
             }
 
-            offsetMilliseconds = computeDSTOffsetMilliseconds(localTimeSeconds);
+            offsetMilliseconds = computeDSTOffsetMilliseconds(utcSeconds);
             if (offsetMilliseconds == endOffsetMilliseconds) {
-                rangeStartSeconds = localTimeSeconds;
+                rangeStartSeconds = utcSeconds;
                 rangeEndSeconds = newEndSeconds;
             } else {
-                rangeEndSeconds = localTimeSeconds;
+                rangeEndSeconds = utcSeconds;
             }
             return offsetMilliseconds;
         }
 
-        offsetMilliseconds = computeDSTOffsetMilliseconds(localTimeSeconds);
-        rangeStartSeconds = rangeEndSeconds = localTimeSeconds;
+        offsetMilliseconds = computeDSTOffsetMilliseconds(utcSeconds);
+        rangeStartSeconds = rangeEndSeconds = utcSeconds;
         return offsetMilliseconds;
     }
 
     int64_t newStartSeconds = Max<int64_t>(rangeStartSeconds - RangeExpansionAmount, 0);
-    if (newStartSeconds <= localTimeSeconds) {
+    if (newStartSeconds <= utcSeconds) {
         int64_t startOffsetMilliseconds = computeDSTOffsetMilliseconds(newStartSeconds);
         if (startOffsetMilliseconds == offsetMilliseconds) {
             rangeStartSeconds = newStartSeconds;
             return offsetMilliseconds;
         }
 
-        offsetMilliseconds = computeDSTOffsetMilliseconds(localTimeSeconds);
+        offsetMilliseconds = computeDSTOffsetMilliseconds(utcSeconds);
         if (offsetMilliseconds == startOffsetMilliseconds) {
             rangeStartSeconds = newStartSeconds;
-            rangeEndSeconds = localTimeSeconds;
+            rangeEndSeconds = utcSeconds;
         } else {
-            rangeStartSeconds = localTimeSeconds;
+            rangeStartSeconds = utcSeconds;
         }
         return offsetMilliseconds;
     }
 
-    rangeStartSeconds = rangeEndSeconds = localTimeSeconds;
-    offsetMilliseconds = computeDSTOffsetMilliseconds(localTimeSeconds);
+    rangeStartSeconds = rangeEndSeconds = utcSeconds;
+    offsetMilliseconds = computeDSTOffsetMilliseconds(utcSeconds);
     return offsetMilliseconds;
 }
 
 void
 js::DateTimeInfo::sanityCheck()
 {
     MOZ_ASSERT(rangeStartSeconds <= rangeEndSeconds);
     MOZ_ASSERT_IF(rangeStartSeconds == INT64_MIN, rangeEndSeconds == INT64_MIN);
--- a/js/src/vm/DateTime.h
+++ b/js/src/vm/DateTime.h
@@ -93,42 +93,56 @@ TimeClip(double time)
  * a time that a site might display.  (One could imagine an adaptive duration
  * that accommodates near-DST-change dates better; we don't believe the
  * potential win from better caching offsets the loss from extra complexity.)
  */
 class DateTimeInfo
 {
   public:
     DateTimeInfo();
-    int64_t getDSTOffsetMilliseconds(int64_t localTimeMilliseconds);
+
+    /*
+     * Get the DST offset in milliseconds at a UTC time.  This is usually
+     * either 0 or |msPerSecond * SecondsPerHour|, but at least one exotic time
+     * zone (Lord Howe Island, Australia) has a fractional-hour offset, just to
+     * keep things interesting.
+     */
+    int64_t getDSTOffsetMilliseconds(int64_t utcMilliseconds);
+
     void updateTimeZoneAdjustment();
 
     /* ES5 15.9.1.7. */
     double localTZA() { return localTZA_; }
 
   private:
-    int64_t computeDSTOffsetMilliseconds(int64_t localTimeSeconds);
-
     /*
      * The current local time zone adjustment, cached because retrieving this
      * dynamically is Slow, and a certain venerable benchmark which shall not
      * be named depends on it being fast.
      *
      * SpiderMonkey occasionally and arbitrarily updates this value from the
      * system time zone to attempt to keep this reasonably up-to-date.  If
      * temporary inaccuracy can't be tolerated, JSAPI clients may call
      * JS_ClearDateCaches to forcibly sync this with the system time zone.
      */
     double localTZA_;
 
+    /*
+     * Compute the DST offset at the given UTC time in seconds from the epoch.
+     * (getDSTOffsetMilliseconds attempts to return a cached value, but in case
+     * of a cache miss it calls this method.  The cache is represented through
+     * the offset* and *{Start,End}Seconds fields below.)
+     */
+    int64_t computeDSTOffsetMilliseconds(int64_t utcSeconds);
+
     int64_t offsetMilliseconds;
-    int64_t rangeStartSeconds, rangeEndSeconds;
+    int64_t rangeStartSeconds, rangeEndSeconds; // UTC-based
 
     int64_t oldOffsetMilliseconds;
-    int64_t oldRangeStartSeconds, oldRangeEndSeconds;
+    int64_t oldRangeStartSeconds, oldRangeEndSeconds; // UTC-based
 
     static const int64_t MaxUnixTimeT = 2145859200; /* time_t 12/31/2037 */
 
     static const int64_t RangeExpansionAmount = 30 * SecondsPerDay;
 
     void sanityCheck();
 };