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

Generated by: LCOV version 1.10