39 static const int kDaysIn4Years = 4 * 365 + 1;
40 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
41 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
42 static const int kDays1970to2000 = 30 * 365 + 7;
43 static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
45 static const int kYearsOffset = 400000;
46 static const char kDaysInMonths[] =
47 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
53 if (stamp_->
value() > kMaxStamp) {
57 for (
int i = 0; i < kDSTSize; ++i) {
58 ClearSegment(&dst_[i]);
60 dst_usage_counter_ = 0;
69 void DateCache::ClearSegment(DST* segment) {
72 segment->offset_ms = 0;
73 segment->last_used = 0;
78 int days,
int* year,
int* month,
int* day) {
82 int new_day = ymd_day_ + (days - ymd_days_);
83 if (new_day >= 1 && new_day <= 28) {
95 *year = 400 * (days / kDaysIn400Years) - kYearsOffset;
96 days %= kDaysIn400Years;
101 int yd1 = days / kDaysIn100Years;
102 days %= kDaysIn100Years;
106 int yd2 = days / kDaysIn4Years;
107 days %= kDaysIn4Years;
111 int yd3 = days / 365;
116 bool is_leap = (!yd1 || yd2) && !yd3;
119 ASSERT(is_leap || (days >= 0));
120 ASSERT((days < 365) || (is_leap && (days < 366)));
121 ASSERT(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0))));
128 if (days >= 31 + 28 + is_leap) {
129 days -= 31 + 28 + is_leap;
131 for (
int i = 2; i < 12; i++) {
132 if (days < kDaysInMonths[i]) {
137 days -= kDaysInMonths[i];
146 *day = days - 31 + 1;
154 ymd_days_ = save_days;
159 static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
160 181, 212, 243, 273, 304, 334};
161 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
162 182, 213, 244, 274, 305, 335};
182 static const int year_delta = 399999;
183 static const int base_day = 365 * (1970 + year_delta) +
184 (1970 + year_delta) / 4 -
185 (1970 + year_delta) / 100 +
186 (1970 + year_delta) / 400;
188 int year1 = year + year_delta;
189 int day_from_year = 365 * year1 +
195 if ((year % 4 != 0) || (year % 100 == 0 && year % 400 != 0)) {
196 return day_from_year + day_from_month[month];
198 return day_from_year + day_from_month_leap[month];
202 void DateCache::ExtendTheAfterSegment(
int time_sec,
int offset_ms) {
203 if (after_->offset_ms == offset_ms &&
204 after_->start_sec <= time_sec + kDefaultDSTDeltaInSec &&
205 time_sec <= after_->end_sec) {
207 after_->start_sec = time_sec;
210 if (after_->start_sec <= after_->end_sec) {
212 after_ = LeastRecentlyUsedDST(before_);
214 after_->start_sec = time_sec;
215 after_->end_sec = time_sec;
216 after_->offset_ms = offset_ms;
217 after_->last_used = ++dst_usage_counter_;
222 int DateCache::DaylightSavingsOffsetInMs(int64_t time_ms) {
224 ? static_cast<int>(time_ms / 1000)
230 if (dst_usage_counter_ >=
kMaxInt - 10) {
231 dst_usage_counter_ = 0;
232 for (
int i = 0; i < kDSTSize; ++i) {
233 ClearSegment(&dst_[i]);
238 if (before_->start_sec <= time_sec &&
239 time_sec <= before_->end_sec) {
241 before_->last_used = ++dst_usage_counter_;
242 return before_->offset_ms;
247 ASSERT(InvalidSegment(before_) || before_->start_sec <= time_sec);
248 ASSERT(InvalidSegment(after_) || time_sec < after_->start_sec);
250 if (InvalidSegment(before_)) {
252 before_->start_sec = time_sec;
253 before_->end_sec = time_sec;
255 before_->last_used = ++dst_usage_counter_;
256 return before_->offset_ms;
259 if (time_sec <= before_->end_sec) {
261 before_->last_used = ++dst_usage_counter_;
262 return before_->offset_ms;
265 if (time_sec > before_->end_sec + kDefaultDSTDeltaInSec) {
269 ExtendTheAfterSegment(time_sec, offset_ms);
280 before_->last_used = ++dst_usage_counter_;
284 if (before_->end_sec + kDefaultDSTDeltaInSec <= after_->start_sec) {
285 int new_after_start_sec = before_->end_sec + kDefaultDSTDeltaInSec;
287 ExtendTheAfterSegment(new_after_start_sec, new_offset_ms);
289 ASSERT(!InvalidSegment(after_));
291 after_->last_used = ++dst_usage_counter_;
297 if (before_->offset_ms == after_->offset_ms) {
299 before_->end_sec = after_->end_sec;
300 ClearSegment(after_);
301 return before_->offset_ms;
306 for (
int i = 4; i >= 0; --i) {
307 int delta = after_->start_sec - before_->end_sec;
308 int middle_sec = (i == 0) ? time_sec : before_->end_sec + delta / 2;
310 if (before_->offset_ms == offset_ms) {
311 before_->end_sec = middle_sec;
312 if (time_sec <= before_->end_sec) {
316 ASSERT(after_->offset_ms == offset_ms);
317 after_->start_sec = middle_sec;
318 if (time_sec >= after_->start_sec) {
332 void DateCache::ProbeDST(
int time_sec) {
335 ASSERT(before_ != after_);
337 for (
int i = 0; i < kDSTSize; ++i) {
338 if (dst_[i].start_sec <= time_sec) {
339 if (before ==
NULL || before->start_sec < dst_[i].start_sec) {
342 }
else if (time_sec < dst_[i].end_sec) {
343 if (after ==
NULL || after->end_sec > dst_[i].end_sec) {
351 if (before ==
NULL) {
352 before = InvalidSegment(before_) ? before_ : LeastRecentlyUsedDST(after);
355 after = InvalidSegment(after_) && before != after_
356 ? after_ : LeastRecentlyUsedDST(before);
362 ASSERT(InvalidSegment(before) || before->start_sec <= time_sec);
363 ASSERT(InvalidSegment(after) || time_sec < after->start_sec);
364 ASSERT(InvalidSegment(before) || InvalidSegment(after) ||
365 before->end_sec < after->start_sec);
372 DateCache::DST* DateCache::LeastRecentlyUsedDST(DST* skip) {
374 for (
int i = 0; i < kDSTSize; ++i) {
375 if (&dst_[i] == skip)
continue;
376 if (result ==
NULL || result->last_used > dst_[i].last_used) {
380 ClearSegment(result);
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static Smi * FromInt(int value)
static void ClearTimezoneCache(TimezoneCache *cache)
static const int64_t kMaxEpochTimeInMs
#define ASSERT(condition)
static const int kInvalidStamp
static const int kMaxEpochTimeInSec
virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec)
static const int kInvalidLocalOffsetInMs
int DaysFromYearMonth(int year, int month)
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
static const int kMaxValue
int64_t EquivalentTime(int64_t time_ms)