13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifndef V8_DATE_H_
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define V8_DATE_H_
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/globals.h"
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass DateCache {
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kMsPerMin = 60 * 1000;
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSecPerDay = 24 * 60 * 60;
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int64_t kMsPerDay = kSecPerDay * 1000;
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The largest time that can be passed to OS date-time library functions.
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kMaxEpochTimeInSec = kMaxInt;
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int64_t kMaxEpochTimeInMs =
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<int64_t>(kMaxInt) * 1000;
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The largest time that can be stored in JSDate.
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int64_t kMaxTimeInMs =
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<int64_t>(864000000) * 10000000;
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Conservative upper bound on time that can be stored in JSDate
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // before UTC conversion.
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int64_t kMaxTimeBeforeUTCInMs =
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      kMaxTimeInMs + 10 * kMsPerDay;
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sentinel that denotes an invalid local offset.
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kInvalidLocalOffsetInMs = kMaxInt;
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sentinel that denotes an invalid cache stamp.
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // It is an invariant of DateCache that cache stamp is non-negative.
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kInvalidStamp = -1;
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DateCache() : stamp_(0), tz_cache_(base::OS::CreateTimezoneCache()) {
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ResetDateCache();
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~DateCache() {
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    base::OS::DisposeTimezoneCache(tz_cache_);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    tz_cache_ = NULL;
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Clears cached timezone information and increments the cache stamp.
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ResetDateCache();
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Computes floor(time_ms / kMsPerDay).
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int DaysFromTime(int64_t time_ms) {
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (time_ms < 0) time_ms -= (kMsPerDay - 1);
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int>(time_ms / kMsPerDay);
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Computes modulo(time_ms, kMsPerDay) given that
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // days = floor(time_ms / kMsPerDay).
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int TimeInDay(int64_t time_ms, int days) {
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int>(time_ms - days * kMsPerDay);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Given the number of days since the epoch, computes the weekday.
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.6.
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int Weekday(int days) {
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int result = (days + 4) % 7;
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return result >= 0 ? result : result + 7;
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool IsLeap(int year) {
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.7.
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int LocalOffsetInMs() {
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (local_offset_ms_ == kInvalidLocalOffsetInMs)  {
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      local_offset_ms_ = GetLocalOffsetFromOS();
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return local_offset_ms_;
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* LocalTimezone(int64_t time_ms) {
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (time_ms < 0 || time_ms > kMaxEpochTimeInMs) {
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      time_ms = EquivalentTime(time_ms);
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return base::OS::LocalTimezone(static_cast<double>(time_ms), tz_cache_);
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.5.26
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int TimezoneOffset(int64_t time_ms) {
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int64_t local_ms = ToLocal(time_ms);
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int>((time_ms - local_ms) / kMsPerMin);
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.9
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t)
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int64_t ToLocal(int64_t time_ms) {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return time_ms + LocalOffsetInMs() + DaylightSavingsOffsetInMs(time_ms);
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.9
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int64_t ToUTC(int64_t time_ms) {
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We need to compute UTC time that corresponds to the given local time.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Literally following spec here leads to incorrect time computation at
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // the points were we transition to and from DST.
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The following shows that using DST for (t - LocalTZA - hour) produces
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // correct conversion.
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Consider transition to DST at local time L1.
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Let L0 = L1 - hour, L2 = L1 + hour,
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //     U1 = UTC time that corresponds to L1,
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //     U0 = U1 - hour.
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Transitioning to DST moves local clock one hour forward L1 => L2, so
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U0 = UTC time that corresponds to L0 = L0 - LocalTZA,
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U1 = UTC time that corresponds to L1 = L1 - LocalTZA,
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U1 = UTC time that corresponds to L2 = L2 - LocalTZA - hour.
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Note that DST(U0 - hour) = 0, DST(U0) = 0, DST(U1) = 1.
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour),
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U1 = L1 - LocalTZA - DST(L1 - LocalTZA - hour),
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U1 = L2 - LocalTZA - DST(L2 - LocalTZA - hour).
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Consider transition from DST at local time L1.
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Let L0 = L1 - hour,
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //     U1 = UTC time that corresponds to L1,
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //     U0 = U1 - hour, U2 = U1 + hour.
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Transitioning from DST moves local clock one hour back L1 => L0, so
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U0 = UTC time that corresponds to L0 (before transition)
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //    = L0 - LocalTZA - hour.
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U1 = UTC time that corresponds to L0 (after transition)
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    //    = L0 - LocalTZA = L1 - LocalTZA - hour
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U2 = UTC time that corresponds to L1 = L1 - LocalTZA.
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Note that DST(U0) = 1, DST(U1) = 0, DST(U2) = 0.
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour) = L0 - LocalTZA - DST(U0).
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // U2 = L1 - LocalTZA - DST(L1 - LocalTZA - hour) = L1 - LocalTZA - DST(U1).
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // It is impossible to get U1 from local time.
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    const int kMsPerHour = 3600 * 1000;
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    time_ms -= LocalOffsetInMs();
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return time_ms - DaylightSavingsOffsetInMs(time_ms - kMsPerHour);
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Computes a time equivalent to the given time according
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to ECMA 262 - 15.9.1.9.
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The issue here is that some library calls don't work right for dates
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // that cannot be represented using a non-negative signed 32 bit integer
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (measured in whole seconds based on the 1970 epoch).
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We solve this by mapping the time to a year with same leap-year-ness
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and same starting day for the year. The ECMAscript specification says
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // we must do this, but for compatibility with other browsers, we use
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the actual year if it is in the range 1970..2037
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int64_t EquivalentTime(int64_t time_ms) {
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int days = DaysFromTime(time_ms);
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int time_within_day_ms = static_cast<int>(time_ms - days * kMsPerDay);
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int year, month, day;
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    YearMonthDayFromDays(days, &year, &month, &day);
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int new_days = DaysFromYearMonth(EquivalentYear(year), month) + day - 1;
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int64_t>(new_days) * kMsPerDay + time_within_day_ms;
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns an equivalent year in the range [2008-2035] matching
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - leap year,
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // - week day of first day.
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.9.
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int EquivalentYear(int year) {
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int week_day = Weekday(DaysFromYearMonth(year, 0));
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int recent_year = (IsLeap(year) ? 1956 : 1967) + (week_day * 12) % 28;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Find the year in the range 2008..2037 that is equivalent mod 28.
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Add 3*28 to give a positive argument to the modulus operator.
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return 2008 + (recent_year + 3 * 28 - 2008) % 28;
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Given the number of days since the epoch, computes
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the corresponding year, month, and day.
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void YearMonthDayFromDays(int days, int* year, int* month, int* day);
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Computes the number of days since the epoch for
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the first day of the given month in the given year.
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int DaysFromYearMonth(int year, int month);
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Cache stamp is used for invalidating caches in JSDate.
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We increment the stamp each time when the timezone information changes.
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // JSDate objects perform stamp check and invalidate their caches if
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // their saved stamp is not equal to the current stamp.
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* stamp() { return stamp_; }
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void* stamp_address() { return &stamp_; }
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // These functions are virtual so that we can override them when testing.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) {
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    double time_ms = static_cast<double>(time_sec * 1000);
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return static_cast<int>(
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        base::OS::DaylightSavingsOffset(time_ms, tz_cache_));
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int GetLocalOffsetFromOS() {
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double offset = base::OS::LocalTimeOffset(tz_cache_);
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(offset < kInvalidLocalOffsetInMs);
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int>(offset);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The implementation relies on the fact that no time zones have
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // more than one daylight savings offset change per 19 days.
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In Egypt in 2010 they decided to suspend DST during Ramadan. This
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // led to a short interval where DST is in effect from September 10 to
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // September 30.
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kDefaultDSTDeltaInSec = 19 * kSecPerDay;
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Size of the Daylight Savings Time cache.
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kDSTSize = 32;
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Daylight Savings Time segment stores a segment of time where
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // daylight savings offset does not change.
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  struct DST {
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int start_sec;
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int end_sec;
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int offset_ms;
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int last_used;
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Computes the daylight savings offset for the given time.
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ECMA 262 - 15.9.1.8
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int DaylightSavingsOffsetInMs(int64_t time_ms);
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sets the before_ and the after_ segments from the DST cache such that
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the before_ segment starts earlier than the given time and
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the after_ segment start later than the given time.
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Both segments might be invalid.
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The last_used counters of the before_ and after_ are updated.
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ProbeDST(int time_sec);
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Finds the least recently used segment from the DST cache that is not
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // equal to the given 'skip' segment.
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DST* LeastRecentlyUsedDST(DST* skip);
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Extends the after_ segment with the given point or resets it
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // if it starts later than the given time + kDefaultDSTDeltaInSec.
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void ExtendTheAfterSegment(int time_sec, int offset_ms);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Makes the given segment invalid.
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void ClearSegment(DST* segment);
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool InvalidSegment(DST* segment) {
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return segment->start_sec > segment->end_sec;
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Smi* stamp_;
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Daylight Saving Time cache.
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DST dst_[kDSTSize];
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int dst_usage_counter_;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DST* before_;
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DST* after_;
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int local_offset_ms_;
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Year/Month/Day cache.
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool ymd_valid_;
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int ymd_days_;
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int ymd_year_;
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int ymd_month_;
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int ymd_day_;
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimezoneCache* tz_cache_;
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} }   // namespace v8::internal
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
282