LCOV - code coverage report
Current view: top level - src - date.h (source / functions) Hit Total Coverage
Test: app.info Lines: 34 34 100.0 %
Date: 2019-01-20 Functions: 5 6 83.3 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_DATE_H_
       6             : #define V8_DATE_H_
       7             : 
       8             : #include "src/base/timezone-cache.h"
       9             : #include "src/globals.h"
      10             : #include "src/objects/smi.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : class DateCache {
      16             :  public:
      17             :   static const int kMsPerMin = 60 * 1000;
      18             :   static const int kSecPerDay = 24 * 60 * 60;
      19             :   static const int64_t kMsPerDay = kSecPerDay * 1000;
      20             :   static const int64_t kMsPerMonth = kMsPerDay * 30;
      21             : 
      22             :   // The largest time that can be passed to OS date-time library functions.
      23             :   static const int kMaxEpochTimeInSec = kMaxInt;
      24             :   static const int64_t kMaxEpochTimeInMs =
      25             :       static_cast<int64_t>(kMaxInt) * 1000;
      26             : 
      27             :   // The largest time that can be stored in JSDate.
      28             :   static const int64_t kMaxTimeInMs =
      29             :       static_cast<int64_t>(864000000) * 10000000;
      30             : 
      31             :   // Conservative upper bound on time that can be stored in JSDate
      32             :   // before UTC conversion.
      33             :   static const int64_t kMaxTimeBeforeUTCInMs = kMaxTimeInMs + kMsPerMonth;
      34             : 
      35             :   // Sentinel that denotes an invalid local offset.
      36             :   static const int kInvalidLocalOffsetInMs = kMaxInt;
      37             :   // Sentinel that denotes an invalid cache stamp.
      38             :   // It is an invariant of DateCache that cache stamp is non-negative.
      39             :   static const int kInvalidStamp = -1;
      40             : 
      41             :   DateCache();
      42             : 
      43       62873 :   virtual ~DateCache() {
      44       62873 :     delete tz_cache_;
      45       62873 :     tz_cache_ = nullptr;
      46       62868 :   }
      47             : 
      48             : 
      49             :   // Clears cached timezone information and increments the cache stamp.
      50             :   void ResetDateCache();
      51             : 
      52             : 
      53             :   // Computes floor(time_ms / kMsPerDay).
      54             :   static int DaysFromTime(int64_t time_ms) {
      55       93950 :     if (time_ms < 0) time_ms -= (kMsPerDay - 1);
      56       93950 :     return static_cast<int>(time_ms / kMsPerDay);
      57             :   }
      58             : 
      59             : 
      60             :   // Computes modulo(time_ms, kMsPerDay) given that
      61             :   // days = floor(time_ms / kMsPerDay).
      62             :   static int TimeInDay(int64_t time_ms, int days) {
      63       76931 :     return static_cast<int>(time_ms - days * kMsPerDay);
      64             :   }
      65             : 
      66             :   // ECMA 262 - ES#sec-timeclip TimeClip (time)
      67             :   static double TimeClip(double time);
      68             : 
      69             :   // Given the number of days since the epoch, computes the weekday.
      70             :   // ECMA 262 - 15.9.1.6.
      71             :   int Weekday(int days) {
      72      144236 :     int result = (days + 4) % 7;
      73      144236 :     return result >= 0 ? result : result + 7;
      74             :   }
      75             : 
      76             : 
      77             :   bool IsLeap(int year) {
      78       16812 :     return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
      79             :   }
      80             : 
      81             :   // ECMA 262 - ES#sec-local-time-zone-adjustment
      82             :   int LocalOffsetInMs(int64_t time, bool is_utc) {
      83      122071 :     return GetLocalOffsetFromOS(time, is_utc);
      84             :   }
      85             : 
      86             : 
      87       53361 :   const char* LocalTimezone(int64_t time_ms) {
      88       53361 :     if (time_ms < 0 || time_ms > kMaxEpochTimeInMs) {
      89       16812 :       time_ms = EquivalentTime(time_ms);
      90             :     }
      91       53361 :     bool is_dst = DaylightSavingsOffsetInMs(time_ms) != 0;
      92       53361 :     const char** name = is_dst ? &dst_tz_name_ : &tz_name_;
      93       53361 :     if (*name == nullptr) {
      94         120 :       *name = tz_cache_->LocalTimezone(static_cast<double>(time_ms));
      95             :     }
      96       53361 :     return *name;
      97             :   }
      98             : 
      99             :   // ECMA 262 - 15.9.5.26
     100             :   int TimezoneOffset(int64_t time_ms) {
     101             :     int64_t local_ms = ToLocal(time_ms);
     102       53487 :     return static_cast<int>((time_ms - local_ms) / kMsPerMin);
     103             :   }
     104             : 
     105             :   // ECMA 262 - ES#sec-localtime-t
     106             :   // LocalTime(t) = t + LocalTZA(t, true)
     107             :   int64_t ToLocal(int64_t time_ms) {
     108      119037 :     return time_ms + LocalOffsetInMs(time_ms, true);
     109             :   }
     110             : 
     111             :   // ECMA 262 - ES#sec-utc-t
     112             :   // UTC(t) = t - LocalTZA(t, false)
     113             :   int64_t ToUTC(int64_t time_ms) {
     114        3034 :     return time_ms - LocalOffsetInMs(time_ms, false);
     115             :   }
     116             : 
     117             : 
     118             :   // Computes a time equivalent to the given time according
     119             :   // to ECMA 262 - 15.9.1.9.
     120             :   // The issue here is that some library calls don't work right for dates
     121             :   // that cannot be represented using a non-negative signed 32 bit integer
     122             :   // (measured in whole seconds based on the 1970 epoch).
     123             :   // We solve this by mapping the time to a year with same leap-year-ness
     124             :   // and same starting day for the year. The ECMAscript specification says
     125             :   // we must do this, but for compatibility with other browsers, we use
     126             :   // the actual year if it is in the range 1970..2037
     127       16812 :   int64_t EquivalentTime(int64_t time_ms) {
     128             :     int days = DaysFromTime(time_ms);
     129       16812 :     int time_within_day_ms = static_cast<int>(time_ms - days * kMsPerDay);
     130             :     int year, month, day;
     131       16812 :     YearMonthDayFromDays(days, &year, &month, &day);
     132       16812 :     int new_days = DaysFromYearMonth(EquivalentYear(year), month) + day - 1;
     133       16812 :     return static_cast<int64_t>(new_days) * kMsPerDay + time_within_day_ms;
     134             :   }
     135             : 
     136             :   // Returns an equivalent year in the range [2008-2035] matching
     137             :   // - leap year,
     138             :   // - week day of first day.
     139             :   // ECMA 262 - 15.9.1.9.
     140       16812 :   int EquivalentYear(int year) {
     141       16812 :     int week_day = Weekday(DaysFromYearMonth(year, 0));
     142       16812 :     int recent_year = (IsLeap(year) ? 1956 : 1967) + (week_day * 12) % 28;
     143             :     // Find the year in the range 2008..2037 that is equivalent mod 28.
     144             :     // Add 3*28 to give a positive argument to the modulus operator.
     145       16812 :     return 2008 + (recent_year + 3 * 28 - 2008) % 28;
     146             :   }
     147             : 
     148             :   // Given the number of days since the epoch, computes
     149             :   // the corresponding year, month, and day.
     150             :   void YearMonthDayFromDays(int days, int* year, int* month, int* day);
     151             : 
     152             :   // Computes the number of days since the epoch for
     153             :   // the first day of the given month in the given year.
     154             :   int DaysFromYearMonth(int year, int month);
     155             : 
     156             :   // Breaks down the time value.
     157             :   void BreakDownTime(int64_t time_ms, int* year, int* month, int* day,
     158             :                      int* weekday, int* hour, int* min, int* sec, int* ms);
     159             : 
     160             :   // Cache stamp is used for invalidating caches in JSDate.
     161             :   // We increment the stamp each time when the timezone information changes.
     162             :   // JSDate objects perform stamp check and invalidate their caches if
     163             :   // their saved stamp is not equal to the current stamp.
     164             :   Smi stamp() { return stamp_; }
     165             :   void* stamp_address() { return &stamp_; }
     166             : 
     167             :   // These functions are virtual so that we can override them when testing.
     168       19290 :   virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) {
     169       19290 :     double time_ms = static_cast<double>(time_sec * 1000);
     170       19290 :     return static_cast<int>(tz_cache_->DaylightSavingsOffset(time_ms));
     171             :   }
     172             : 
     173             :   virtual int GetLocalOffsetFromOS(int64_t time_ms, bool is_utc);
     174             : 
     175             :  private:
     176             :   // The implementation relies on the fact that no time zones have
     177             :   // more than one daylight savings offset change per 19 days.
     178             :   // In Egypt in 2010 they decided to suspend DST during Ramadan. This
     179             :   // led to a short interval where DST is in effect from September 10 to
     180             :   // September 30.
     181             :   static const int kDefaultDSTDeltaInSec = 19 * kSecPerDay;
     182             : 
     183             :   // Size of the Daylight Savings Time cache.
     184             :   static const int kDSTSize = 32;
     185             : 
     186             :   // Daylight Savings Time segment stores a segment of time where
     187             :   // daylight savings offset does not change.
     188             :   struct DST {
     189             :     int start_sec;
     190             :     int end_sec;
     191             :     int offset_ms;
     192             :     int last_used;
     193             :   };
     194             : 
     195             :   // Computes the daylight savings offset for the given time.
     196             :   // ECMA 262 - 15.9.1.8
     197             :   int DaylightSavingsOffsetInMs(int64_t time_ms);
     198             : 
     199             :   // Sets the before_ and the after_ segments from the DST cache such that
     200             :   // the before_ segment starts earlier than the given time and
     201             :   // the after_ segment start later than the given time.
     202             :   // Both segments might be invalid.
     203             :   // The last_used counters of the before_ and after_ are updated.
     204             :   void ProbeDST(int time_sec);
     205             : 
     206             :   // Finds the least recently used segment from the DST cache that is not
     207             :   // equal to the given 'skip' segment.
     208             :   DST* LeastRecentlyUsedDST(DST* skip);
     209             : 
     210             :   // Extends the after_ segment with the given point or resets it
     211             :   // if it starts later than the given time + kDefaultDSTDeltaInSec.
     212             :   inline void ExtendTheAfterSegment(int time_sec, int offset_ms);
     213             : 
     214             :   // Makes the given segment invalid.
     215             :   inline void ClearSegment(DST* segment);
     216             : 
     217             :   bool InvalidSegment(DST* segment) {
     218             :     return segment->start_sec > segment->end_sec;
     219             :   }
     220             : 
     221             :   Smi stamp_;
     222             : 
     223             :   // Daylight Saving Time cache.
     224             :   DST dst_[kDSTSize];
     225             :   int dst_usage_counter_;
     226             :   DST* before_;
     227             :   DST* after_;
     228             : 
     229             :   int local_offset_ms_;
     230             : 
     231             :   // Year/Month/Day cache.
     232             :   bool ymd_valid_;
     233             :   int ymd_days_;
     234             :   int ymd_year_;
     235             :   int ymd_month_;
     236             :   int ymd_day_;
     237             : 
     238             :   // Timezone name cache
     239             :   const char* tz_name_;
     240             :   const char* dst_tz_name_;
     241             : 
     242             :   base::TimezoneCache* tz_cache_;
     243             : };
     244             : 
     245             : }  // namespace internal
     246             : }  // namespace v8
     247             : 
     248             : #endif  // V8_DATE_H_

Generated by: LCOV version 1.10