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. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/date.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/objects.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/objects-inl.h" 93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 { 113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal { 123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kDaysIn4Years = 4 * 365 + 1; 153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kDaysIn100Years = 25 * kDaysIn4Years - 1; 163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kDaysIn400Years = 4 * kDaysIn100Years + 1; 173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kDays1970to2000 = 30 * 365 + 7; 183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years - 193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDays1970to2000; 203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kYearsOffset = 400000; 213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char kDaysInMonths[] = 223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid DateCache::ResetDateCache() { 263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kMaxStamp = Smi::kMaxValue; 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stamp_->value() >= kMaxStamp) { 283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stamp_ = Smi::FromInt(0); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stamp_ = Smi::FromInt(stamp_->value() + 1); 313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(stamp_ != Smi::FromInt(kInvalidStamp)); 333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < kDSTSize; ++i) { 343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ClearSegment(&dst_[i]); 353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dst_usage_counter_ = 0; 373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_ = &dst_[0]; 383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_ = &dst_[1]; 393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local_offset_ms_ = kInvalidLocalOffsetInMs; 403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_valid_ = false; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::ClearTimezoneCache(tz_cache_); 423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid DateCache::ClearSegment(DST* segment) { 463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch segment->start_sec = kMaxEpochTimeInSec; 473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch segment->end_sec = -kMaxEpochTimeInSec; 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch segment->offset_ms = 0; 493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch segment->last_used = 0; 503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid DateCache::YearMonthDayFromDays( 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int days, int* year, int* month, int* day) { 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (ymd_valid_) { 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check conservatively if the given 'days' has 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same year and month as the cached 'days'. 583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int new_day = ymd_day_ + (days - ymd_days_); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (new_day >= 1 && new_day <= 28) { 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_day_ = new_day; 613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_days_ = days; 623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *year = ymd_year_; 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *month = ymd_month_; 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *day = new_day; 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int save_days = days; 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days += kDaysOffset; 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *year = 400 * (days / kDaysIn400Years) - kYearsOffset; 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days %= kDaysIn400Years; 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(save_days, DaysFromYearMonth(*year, 0) + days); 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days--; 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int yd1 = days / kDaysIn100Years; 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days %= kDaysIn100Years; 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *year += 100 * yd1; 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days++; 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int yd2 = days / kDaysIn4Years; 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days %= kDaysIn4Years; 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *year += 4 * yd2; 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days--; 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int yd3 = days / 365; 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days %= 365; 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *year += yd3; 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_leap = (!yd1 || yd2) && !yd3; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(days >= -1); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_leap || (days >= 0)); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((days < 365) || (is_leap && (days < 366))); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0)))); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_leap || ((DaysFromYearMonth(*year, 0) + days) == save_days)); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!is_leap || ((DaysFromYearMonth(*year, 0) + days + 1) == save_days)); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days += is_leap; 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the date is after February. 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (days >= 31 + 28 + BoolToInt(is_leap)) { 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch days -= 31 + 28 + BoolToInt(is_leap); 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Find the date starting from March. 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 2; i < 12; i++) { 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (days < kDaysInMonths[i]) { 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *month = i; 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *day = days + 1; 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch days -= kDaysInMonths[i]; 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check January and February. 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (days < 31) { 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *month = 0; 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *day = days + 1; 1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *month = 1; 1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *day = days - 31 + 1; 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(DaysFromYearMonth(*year, *month) + *day - 1 == save_days); 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_valid_ = true; 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_year_ = *year; 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_month_ = *month; 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_day_ = *day; 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ymd_days_ = save_days; 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint DateCache::DaysFromYearMonth(int year, int month) { 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int day_from_month[] = {0, 31, 59, 90, 120, 151, 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 181, 212, 243, 273, 304, 334}; 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 182, 213, 244, 274, 305, 335}; 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch year += month / 12; 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch month %= 12; 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (month < 0) { 1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch year--; 1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch month += 12; 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(month >= 0); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(month < 12); 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // year_delta is an arbitrary number such that: 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // a) year_delta = -1 (mod 400) 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // b) year + year_delta > 0 for years in the range defined by 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Jan 1 1970. This is required so that we don't run into integer 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // division of negative numbers. 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // c) there shouldn't be an overflow for 32-bit integers in the following 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // operations. 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int year_delta = 399999; 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int base_day = 365 * (1970 + year_delta) + 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (1970 + year_delta) / 4 - 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (1970 + year_delta) / 100 + 1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (1970 + year_delta) / 400; 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int year1 = year + year_delta; 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int day_from_year = 365 * year1 + 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch year1 / 4 - 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch year1 / 100 + 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch year1 / 400 - 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch base_day; 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((year % 4 != 0) || (year % 100 == 0 && year % 400 != 0)) { 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return day_from_year + day_from_month[month]; 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return day_from_year + day_from_month_leap[month]; 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DateCache::BreakDownTime(int64_t time_ms, int* year, int* month, int* day, 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int* weekday, int* hour, int* min, int* sec, 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int* ms) { 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const days = DaysFromTime(time_ms); 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int const time_in_day_ms = TimeInDay(time_ms, days); 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch YearMonthDayFromDays(days, year, month, day); 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *weekday = Weekday(days); 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *hour = time_in_day_ms / (60 * 60 * 1000); 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *min = (time_in_day_ms / (60 * 1000)) % 60; 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *sec = (time_in_day_ms / 1000) % 60; 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *ms = time_in_day_ms % 1000; 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid DateCache::ExtendTheAfterSegment(int time_sec, int offset_ms) { 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (after_->offset_ms == offset_ms && 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->start_sec <= time_sec + kDefaultDSTDeltaInSec && 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch time_sec <= after_->end_sec) { 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Extend the after_ segment. 1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->start_sec = time_sec; 1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The after_ segment is either invalid or starts too late. 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (after_->start_sec <= after_->end_sec) { 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the after_ segment is valid, replace it with a new segment. 2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_ = LeastRecentlyUsedDST(before_); 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->start_sec = time_sec; 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->end_sec = time_sec; 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->offset_ms = offset_ms; 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->last_used = ++dst_usage_counter_; 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint DateCache::DaylightSavingsOffsetInMs(int64_t time_ms) { 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int time_sec = (time_ms >= 0 && time_ms <= kMaxEpochTimeInMs) 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? static_cast<int>(time_ms / 1000) 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : static_cast<int>(EquivalentTime(time_ms) / 1000); 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invalidate cache if the usage counter is close to overflow. 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that dst_usage_counter is incremented less than ten times 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in this function. 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (dst_usage_counter_ >= kMaxInt - 10) { 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dst_usage_counter_ = 0; 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < kDSTSize; ++i) { 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ClearSegment(&dst_[i]); 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Optimistic fast check. 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before_->start_sec <= time_sec && 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch time_sec <= before_->end_sec) { 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cache hit. 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->last_used = ++dst_usage_counter_; 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return before_->offset_ms; 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeDST(time_sec); 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(InvalidSegment(before_) || before_->start_sec <= time_sec); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(InvalidSegment(after_) || time_sec < after_->start_sec); 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (InvalidSegment(before_)) { 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cache miss. 2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->start_sec = time_sec; 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->end_sec = time_sec; 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->offset_ms = GetDaylightSavingsOffsetFromOS(time_sec); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->last_used = ++dst_usage_counter_; 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return before_->offset_ms; 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (time_sec <= before_->end_sec) { 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cache hit. 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->last_used = ++dst_usage_counter_; 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return before_->offset_ms; 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (time_sec > before_->end_sec + kDefaultDSTDeltaInSec) { 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the before_ segment ends too early, then just 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // query for the offset of the time_sec 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset_ms = GetDaylightSavingsOffsetFromOS(time_sec); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExtendTheAfterSegment(time_sec, offset_ms); 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This swap helps the optimistic fast check in subsequent invocations. 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DST* temp = before_; 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_ = after_; 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_ = temp; 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return offset_ms; 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now the time_sec is between 2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // before_->end_sec and before_->end_sec + default DST delta. 2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the usage counter of before_ since it is going to be used. 2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->last_used = ++dst_usage_counter_; 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if after_ segment is invalid or starts too late. 2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that start_sec of invalid segments is kMaxEpochTimeInSec. 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before_->end_sec + kDefaultDSTDeltaInSec <= after_->start_sec) { 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int new_after_start_sec = before_->end_sec + kDefaultDSTDeltaInSec; 2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int new_offset_ms = GetDaylightSavingsOffsetFromOS(new_after_start_sec); 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExtendTheAfterSegment(new_after_start_sec, new_offset_ms); 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!InvalidSegment(after_)); 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the usage counter of after_ since it is going to be used. 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->last_used = ++dst_usage_counter_; 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Now the time_sec is between before_->end_sec and after_->start_sec. 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only one daylight savings offset change can occur in this interval. 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before_->offset_ms == after_->offset_ms) { 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Merge two segments if they have the same offset. 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->end_sec = after_->end_sec; 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ClearSegment(after_); 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return before_->offset_ms; 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Binary search for daylight savings offset change point, 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // but give up if we don't find it in four iterations. 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 4; i >= 0; --i) { 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int delta = after_->start_sec - before_->end_sec; 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int middle_sec = (i == 0) ? time_sec : before_->end_sec + delta / 2; 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset_ms = GetDaylightSavingsOffsetFromOS(middle_sec); 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before_->offset_ms == offset_ms) { 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_->end_sec = middle_sec; 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (time_sec <= before_->end_sec) { 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return offset_ms; 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(after_->offset_ms == offset_ms); 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_->start_sec = middle_sec; 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (time_sec >= after_->start_sec) { 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This swap helps the optimistic fast check in subsequent invocations. 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DST* temp = before_; 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_ = after_; 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_ = temp; 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return offset_ms; 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 0; 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid DateCache::ProbeDST(int time_sec) { 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DST* before = NULL; 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DST* after = NULL; 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(before_ != after_); 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < kDSTSize; ++i) { 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (dst_[i].start_sec <= time_sec) { 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before == NULL || before->start_sec < dst_[i].start_sec) { 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before = &dst_[i]; 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (time_sec < dst_[i].end_sec) { 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (after == NULL || after->end_sec > dst_[i].end_sec) { 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after = &dst_[i]; 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If before or after segments were not found, 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // then set them to any invalid segment. 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (before == NULL) { 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before = InvalidSegment(before_) ? before_ : LeastRecentlyUsedDST(after); 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (after == NULL) { 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after = InvalidSegment(after_) && before != after_ 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? after_ : LeastRecentlyUsedDST(before); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(before != NULL); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(after != NULL); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(before != after); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(InvalidSegment(before) || before->start_sec <= time_sec); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(InvalidSegment(after) || time_sec < after->start_sec); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(InvalidSegment(before) || InvalidSegment(after) || 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before->end_sec < after->start_sec); 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch before_ = before; 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch after_ = after; 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochDateCache::DST* DateCache::LeastRecentlyUsedDST(DST* skip) { 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DST* result = NULL; 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < kDSTSize; ++i) { 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (&dst_[i] == skip) continue; 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (result == NULL || result->last_used > dst_[i].last_used) { 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result = &dst_[i]; 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ClearSegment(result); 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 376