v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
date.cc
Go to the documentation of this file.
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#include "src/date/date.h"
6
7#include <limits>
8
13#ifdef V8_INTL_SUPPORT
15#endif
17
18namespace v8 {
19namespace internal {
20
21static const int kDaysIn4Years = 4 * 365 + 1;
22static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
23static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
24static const int kDays1970to2000 = 30 * 365 + 7;
25static const int kDaysOffset =
27static const int kYearsOffset = 400000;
28static const char kDaysInMonths[] = {31, 28, 31, 30, 31, 30,
29 31, 31, 30, 31, 30, 31};
30
32 : stamp_(kNullAddress),
33 tz_cache_(
34#ifdef V8_INTL_SUPPORT
35 Intl::CreateTimeZoneCache()
36#else
37 base::OS::CreateTimezoneCache()
38#endif
39 ) {
41}
42
44 base::TimezoneCache::TimeZoneDetection time_zone_detection) {
45 if (stamp_.value() >= Smi::kMaxValue) {
46 stamp_ = Smi::zero();
47 } else {
49 }
51 for (int i = 0; i < kCacheSize; ++i) {
53 }
55 before_ = &cache_[0];
56 after_ = &cache_[1];
57 ymd_valid_ = false;
58#ifdef V8_INTL_SUPPORT
59 if (!v8_flags.icu_timezone_data) {
60#endif
62#ifdef V8_INTL_SUPPORT
63 }
64#endif
65 tz_cache_->Clear(time_zone_detection);
66 tz_name_ = nullptr;
67 dst_tz_name_ = nullptr;
68}
69
71 segment->start_ms = 0;
72 segment->end_ms = -1;
73 segment->offset_ms = 0;
74 segment->last_used = 0;
75}
76
77void DateCache::YearMonthDayFromDays(int days, int* year, int* month,
78 int* day) {
79 if (ymd_valid_) {
80 // Check conservatively if the given 'days' has
81 // the same year and month as the cached 'days'.
82 int new_day = ymd_day_ + (days - ymd_days_);
83 if (new_day >= 1 && new_day <= 28) {
84 ymd_day_ = new_day;
86 *year = ymd_year_;
87 *month = ymd_month_;
88 *day = new_day;
89 return;
90 }
91 }
92 int save_days = days;
93
95 *year = 400 * (days / kDaysIn400Years) - kYearsOffset;
97
98 DCHECK_EQ(save_days, DaysFromYearMonth(*year, 0) + days);
99
100 days--;
101 int yd1 = days / kDaysIn100Years;
103 *year += 100 * yd1;
104
105 days++;
106 int yd2 = days / kDaysIn4Years;
108 *year += 4 * yd2;
109
110 days--;
111 int yd3 = days / 365;
112 days %= 365;
113 *year += yd3;
114
115 bool is_leap = (!yd1 || yd2) && !yd3;
116
117 DCHECK_GE(days, -1);
118 DCHECK(is_leap || (days >= 0));
119 DCHECK((days < 365) || (is_leap && (days < 366)));
120 DCHECK(is_leap == ((*year % 4 == 0) && (*year % 100 || (*year % 400 == 0))));
121 DCHECK(is_leap || ((DaysFromYearMonth(*year, 0) + days) == save_days));
122 DCHECK(!is_leap || ((DaysFromYearMonth(*year, 0) + days + 1) == save_days));
123
124 days += is_leap;
125
126 // Check if the date is after February.
127 if (days >= 31 + 28 + (is_leap ? 1 : 0)) {
128 days -= 31 + 28 + (is_leap ? 1 : 0);
129 // Find the date starting from March.
130 for (int i = 2; i < 12; i++) {
131 if (days < kDaysInMonths[i]) {
132 *month = i;
133 *day = days + 1;
134 break;
135 }
136 days -= kDaysInMonths[i];
137 }
138 } else {
139 // Check January and February.
140 if (days < 31) {
141 *month = 0;
142 *day = days + 1;
143 } else {
144 *month = 1;
145 *day = days - 31 + 1;
146 }
147 }
148 DCHECK(DaysFromYearMonth(*year, *month) + *day - 1 == save_days);
149 ymd_valid_ = true;
150 ymd_year_ = *year;
151 ymd_month_ = *month;
152 ymd_day_ = *day;
153 ymd_days_ = save_days;
154}
155
156int DateCache::DaysFromYearMonth(int year, int month) {
157 static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
158 181, 212, 243, 273, 304, 334};
159 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
160 182, 213, 244, 274, 305, 335};
161
162 year += month / 12;
163 month %= 12;
164 if (month < 0) {
165 year--;
166 month += 12;
167 }
168
169 DCHECK_GE(month, 0);
170 DCHECK_LT(month, 12);
171
172 // year_delta is an arbitrary number such that:
173 // a) year_delta = -1 (mod 400)
174 // b) year + year_delta > 0 for years in the range defined by
175 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
176 // Jan 1 1970. This is required so that we don't run into integer
177 // division of negative numbers.
178 // c) there shouldn't be an overflow for 32-bit integers in the following
179 // operations.
180 static const int year_delta = 399999;
181 static const int base_day =
182 365 * (1970 + year_delta) + (1970 + year_delta) / 4 -
183 (1970 + year_delta) / 100 + (1970 + year_delta) / 400;
184
185 int year1 = year + year_delta;
186 int day_from_year =
187 365 * year1 + year1 / 4 - year1 / 100 + year1 / 400 - base_day;
188
189 if ((year % 4 != 0) || (year % 100 == 0 && year % 400 != 0)) {
190 return day_from_year + day_from_month[month];
191 }
192 return day_from_year + day_from_month_leap[month];
193}
194
195void DateCache::BreakDownTime(int64_t time_ms, int* year, int* month, int* day,
196 int* weekday, int* hour, int* min, int* sec,
197 int* ms) {
198 int const days = DaysFromTime(time_ms);
199 int const time_in_day_ms = TimeInDay(time_ms, days);
200 YearMonthDayFromDays(days, year, month, day);
201 *weekday = Weekday(days);
202 *hour = time_in_day_ms / (60 * 60 * 1000);
203 *min = (time_in_day_ms / (60 * 1000)) % 60;
204 *sec = (time_in_day_ms / 1000) % 60;
205 *ms = time_in_day_ms % 1000;
206}
207
208// Implements LocalTimeZonedjustment(t, isUTC)
209// ECMA 262 - ES#sec-local-time-zone-adjustment
210int DateCache::GetLocalOffsetFromOS(int64_t time_ms, bool is_utc) {
211 double offset;
212#ifdef V8_INTL_SUPPORT
213 if (v8_flags.icu_timezone_data) {
214 offset = tz_cache_->LocalTimeOffset(static_cast<double>(time_ms), is_utc);
215 } else {
216#endif
217 // When ICU timezone data is not used, we need to compute the timezone
218 // offset for a given local time.
219 //
220 // The following shows that using DST for (t - LocalTZA - hour) produces
221 // correct conversion where LocalTZA is the timezone offset in winter (no
222 // DST) and the timezone offset is assumed to have no historical change.
223 // Note that it does not work for the past and the future if LocalTZA (no
224 // DST) is different from the current LocalTZA (no DST). For instance,
225 // this will break for Europe/Moscow in 2012 ~ 2013 because LocalTZA was
226 // 4h instead of the current 3h (as of 2018).
227 //
228 // Consider transition to DST at local time L1.
229 // Let L0 = L1 - hour, L2 = L1 + hour,
230 // U1 = UTC time that corresponds to L1,
231 // U0 = U1 - hour.
232 // Transitioning to DST moves local clock one hour forward L1 => L2, so
233 // U0 = UTC time that corresponds to L0 = L0 - LocalTZA,
234 // U1 = UTC time that corresponds to L1 = L1 - LocalTZA,
235 // U1 = UTC time that corresponds to L2 = L2 - LocalTZA - hour.
236 // Note that DST(U0 - hour) = 0, DST(U0) = 0, DST(U1) = 1.
237 // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour),
238 // U1 = L1 - LocalTZA - DST(L1 - LocalTZA - hour),
239 // U1 = L2 - LocalTZA - DST(L2 - LocalTZA - hour).
240 //
241 // Consider transition from DST at local time L1.
242 // Let L0 = L1 - hour,
243 // U1 = UTC time that corresponds to L1,
244 // U0 = U1 - hour, U2 = U1 + hour.
245 // Transitioning from DST moves local clock one hour back L1 => L0, so
246 // U0 = UTC time that corresponds to L0 (before transition)
247 // = L0 - LocalTZA - hour.
248 // U1 = UTC time that corresponds to L0 (after transition)
249 // = L0 - LocalTZA = L1 - LocalTZA - hour
250 // U2 = UTC time that corresponds to L1 = L1 - LocalTZA.
251 // Note that DST(U0) = 1, DST(U1) = 0, DST(U2) = 0.
252 // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour) = L0 - LocalTZA - DST(U0).
253 // U2 = L1 - LocalTZA - DST(L1 - LocalTZA - hour) = L1 - LocalTZA - DST(U1).
254 // It is impossible to get U1 from local time.
256 // This gets the constant LocalTZA (arguments are ignored).
258 tz_cache_->LocalTimeOffset(static_cast<double>(time_ms), is_utc);
259 }
261 if (!is_utc) {
262 const int kMsPerHour = 3600 * 1000;
263 time_ms -= (offset + kMsPerHour);
264 }
266#ifdef V8_INTL_SUPPORT
267 }
268#endif
270 return static_cast<int>(offset);
271}
272
273void DateCache::ExtendTheAfterSegment(int64_t time_ms, int offset_ms) {
274 if (!InvalidSegment(after_) && after_->offset_ms == offset_ms &&
276 time_ms <= after_->end_ms) {
277 // Extend the after_ segment.
278 after_->start_ms = time_ms;
279 } else {
280 // The after_ segment is either invalid or starts too late.
281 if (!InvalidSegment(after_)) {
282 // If the after_ segment is valid, replace it with a new segment.
284 }
285 after_->start_ms = time_ms;
286 after_->end_ms = time_ms;
287 after_->offset_ms = offset_ms;
289 }
290}
291
292int DateCache::LocalOffsetInMs(int64_t time_ms, bool is_utc) {
293 if (!is_utc) {
294 return GetLocalOffsetFromOS(time_ms, is_utc);
295 }
296#ifdef ENABLE_SLOW_DCHECKS
297 int known_correct_result = 0;
298 if (v8_flags.enable_slow_asserts) {
299 // When slow DCHECKs are enabled, we always retrieve the known good result
300 // (slow) and check that the result produced by the cache matches it.
301 known_correct_result = GetLocalOffsetFromOS(time_ms, is_utc);
302 }
303#endif // ENABLE_SLOW_DCHECKS
304 // Invalidate cache if the usage counter is close to overflow.
305 // Note that cache_usage_counter is incremented less than ten times
306 // in this function.
307 if (cache_usage_counter_ >= kMaxInt - 10) {
309 for (int i = 0; i < kCacheSize; ++i) {
311 }
312 }
313
314 // Optimistic fast check.
315 if (before_->start_ms <= time_ms && time_ms <= before_->end_ms) {
316 // Cache hit.
318 SLOW_DCHECK(before_->offset_ms == known_correct_result);
319 return before_->offset_ms;
320 }
321
322 ProbeCache(time_ms);
323
325 DCHECK(InvalidSegment(after_) || time_ms < after_->start_ms);
326
327 if (InvalidSegment(before_)) {
328 // Cache miss.
329 before_->start_ms = time_ms;
330 before_->end_ms = time_ms;
331 before_->offset_ms = GetLocalOffsetFromOS(time_ms, is_utc);
333 SLOW_DCHECK(before_->offset_ms == known_correct_result);
334 return before_->offset_ms;
335 }
336
337 if (time_ms <= before_->end_ms) {
338 // Cache hit.
340 SLOW_DCHECK(before_->offset_ms == known_correct_result);
341 return before_->offset_ms;
342 }
343
345 // If the before_ segment ends too early, then just
346 // query for the offset of the time_ms
347 int offset_ms = GetLocalOffsetFromOS(time_ms, is_utc);
348 ExtendTheAfterSegment(time_ms, offset_ms);
349 // This swap helps the optimistic fast check in subsequent invocations.
350 CacheItem* temp = before_;
351 before_ = after_;
352 after_ = temp;
353 SLOW_DCHECK(offset_ms == known_correct_result);
354 return offset_ms;
355 }
356
357 // Now the time_ms is between
358 // before_->end_ms and before_->end_ms + default time zone offset delta.
359 // Update the usage counter of before_ since it is going to be used.
361
362 // Check if after_ segment is invalid or starts too late.
363 int64_t new_after_start_ms =
365 if (InvalidSegment(after_) || new_after_start_ms <= after_->start_ms) {
366 int new_offset_ms = GetLocalOffsetFromOS(new_after_start_ms, is_utc);
367 ExtendTheAfterSegment(new_after_start_ms, new_offset_ms);
368 } else {
370 // Update the usage counter of after_ since it is going to be used.
372 }
373
374 // Now the time_ms is between before_->end_ms and after_->start_ms.
375 // Only one daylight savings offset change can occur in this interval.
376
378 // Merge two segments if they have the same offset.
381 SLOW_DCHECK(before_->offset_ms == known_correct_result);
382 return before_->offset_ms;
383 }
384
385 // Binary search for time zone offset change point,
386 // but give up if we don't find it in five iterations.
387 for (int i = 4; i >= 0; --i) {
388 int64_t delta = after_->start_ms - before_->end_ms;
389 int64_t middle_sec = (i == 0) ? time_ms : before_->end_ms + delta / 2;
390 int offset_ms = GetLocalOffsetFromOS(middle_sec, is_utc);
391 if (before_->offset_ms == offset_ms) {
392 before_->end_ms = middle_sec;
393 if (time_ms <= before_->end_ms) {
394 SLOW_DCHECK(offset_ms == known_correct_result);
395 return offset_ms;
396 }
397 // If we didn't return, we can't be in the last iteration.
398 DCHECK_GT(i, 0);
399 } else {
400 DCHECK(after_->offset_ms == offset_ms);
401 after_->start_ms = middle_sec;
402 if (time_ms >= after_->start_ms) {
403 // This swap helps the optimistic fast check in subsequent invocations.
404 CacheItem* temp = before_;
405 before_ = after_;
406 after_ = temp;
407 SLOW_DCHECK(offset_ms == known_correct_result);
408 return offset_ms;
409 }
410 // If we didn't return, we can't be in the last iteration.
411 DCHECK_GT(i, 0);
412 }
413 }
414 // During the last iteration, we set middle_sec = time_ms and return via one
415 // of the two return statements above. Thus, we never end up here.
416 UNREACHABLE();
417}
418
419void DateCache::ProbeCache(int64_t time_ms) {
420 CacheItem* before = nullptr;
421 CacheItem* after = nullptr;
423
424 for (int i = 0; i < kCacheSize; ++i) {
425 if (InvalidSegment(&cache_[i])) {
426 continue;
427 }
428 if (cache_[i].start_ms <= time_ms) {
429 if (before == nullptr || before->start_ms < cache_[i].start_ms) {
430 before = &cache_[i];
431 }
432 } else if (time_ms < cache_[i].end_ms) {
433 if (after == nullptr || after->end_ms > cache_[i].end_ms) {
434 after = &cache_[i];
435 }
436 }
437 }
438
439 // If before or after segments were not found,
440 // then set them to any invalid segment.
441 if (before == nullptr) {
442 before =
444 }
445 if (after == nullptr) {
446 after = InvalidSegment(after_) && before != after_
447 ? after_
449 }
450
451 DCHECK_NOT_NULL(before);
452 DCHECK_NOT_NULL(after);
453 DCHECK(before != after);
454 DCHECK(InvalidSegment(before) || before->start_ms <= time_ms);
455 DCHECK(InvalidSegment(after) || time_ms < after->start_ms);
456 DCHECK(InvalidSegment(before) || InvalidSegment(after) ||
457 before->end_ms < after->start_ms);
458
459 before_ = before;
460 after_ = after;
461}
462
464 CacheItem* result = nullptr;
465 for (int i = 0; i < kCacheSize; ++i) {
466 if (&cache_[i] == skip) continue;
467 if (result == nullptr || result->last_used > cache_[i].last_used) {
468 result = &cache_[i];
469 }
470 }
472 return result;
473}
474
475namespace {
476
477// ES6 section 20.3.1.1 Time Values and Time Range
478const double kMinYear = -1000000.0;
479const double kMaxYear = -kMinYear;
480const double kMinMonth = -10000000.0;
481const double kMaxMonth = -kMinMonth;
482
483const double kMsPerDay = 86400000.0;
484
485const double kMsPerSecond = 1000.0;
486const double kMsPerMinute = 60000.0;
487const double kMsPerHour = 3600000.0;
488
489} // namespace
490
491double MakeDate(double day, double time) {
492 if (std::isfinite(day) && std::isfinite(time)) {
493 return time + day * kMsPerDay;
494 }
495 return std::numeric_limits<double>::quiet_NaN();
496}
497
498double MakeDay(double year, double month, double date) {
499 if ((kMinYear <= year && year <= kMaxYear) &&
500 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
501 int y = FastD2I(year);
502 int m = FastD2I(month);
503 y += m / 12;
504 m %= 12;
505 if (m < 0) {
506 m += 12;
507 y -= 1;
508 }
509 DCHECK_LE(0, m);
510 DCHECK_LT(m, 12);
511
512 // kYearDelta is an arbitrary number such that:
513 // a) kYearDelta = -1 (mod 400)
514 // b) year + kYearDelta > 0 for years in the range defined by
515 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
516 // Jan 1 1970. This is required so that we don't run into integer
517 // division of negative numbers.
518 // c) there shouldn't be an overflow for 32-bit integers in the following
519 // operations.
520 static const int kYearDelta = 399999;
521 static const int kBaseDay =
522 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
523 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
524 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
525 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
526 kBaseDay;
527 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
528 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
529 181, 212, 243, 273, 304, 334};
530 day_from_year += kDayFromMonth[m];
531 } else {
532 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
533 182, 213, 244, 274, 305, 335};
534 day_from_year += kDayFromMonth[m];
535 }
536 return static_cast<double>(day_from_year - 1) + DoubleToInteger(date);
537 }
538 return std::numeric_limits<double>::quiet_NaN();
539}
540
541double MakeTime(double hour, double min, double sec, double ms) {
542 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
543 std::isfinite(ms)) {
544 double const h = DoubleToInteger(hour);
545 double const m = DoubleToInteger(min);
546 double const s = DoubleToInteger(sec);
547 double const milli = DoubleToInteger(ms);
548 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
549 }
550 return std::numeric_limits<double>::quiet_NaN();
551}
552
553namespace {
554
555const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
556 "Thu", "Fri", "Sat"};
557const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
558 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
559
560template <class... Args>
561DateBuffer FormatDate(const char* format, Args... args) {
562 DateBuffer buffer;
563 SmallStringOptimizedAllocator<DateBuffer::kInlineSize> allocator(&buffer);
564 StringStream sstream(&allocator);
565 sstream.Add(format, args...);
566 buffer.resize(sstream.length());
567 return buffer;
568}
569
570} // namespace
571
572DateBuffer ToDateString(double time_val, DateCache* date_cache,
573 ToDateStringMode mode) {
574 if (std::isnan(time_val)) {
575 return FormatDate("Invalid Date");
576 }
577 int64_t time_ms = static_cast<int64_t>(time_val);
578 int64_t local_time_ms = (mode == ToDateStringMode::kUTCDateAndTime ||
580 ? time_ms
581 : date_cache->ToLocal(time_ms);
582 int year, month, day, weekday, hour, min, sec, ms;
583 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
584 &min, &sec, &ms);
585 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
586 int timezone_hour = std::abs(timezone_offset) / 60;
587 int timezone_min = std::abs(timezone_offset) % 60;
588 const char* local_timezone = date_cache->LocalTimezone(time_ms);
589 switch (mode) {
591 return FormatDate((year < 0) ? "%s %s %02d %05d" : "%s %s %02d %04d",
592 kShortWeekDays[weekday], kShortMonths[month], day,
593 year);
595 return FormatDate("%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
596 (timezone_offset < 0) ? '-' : '+', timezone_hour,
597 timezone_min, local_timezone);
599 return FormatDate(
600 (year < 0) ? "%s %s %02d %05d %02d:%02d:%02d GMT%c%02d%02d (%s)"
601 : "%s %s %02d %04d %02d:%02d:%02d GMT%c%02d%02d (%s)",
602 kShortWeekDays[weekday], kShortMonths[month], day, year, hour, min,
603 sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
604 local_timezone);
606 return FormatDate((year < 0) ? "%s, %02d %s %05d %02d:%02d:%02d GMT"
607 : "%s, %02d %s %04d %02d:%02d:%02d GMT",
608 kShortWeekDays[weekday], day, kShortMonths[month], year,
609 hour, min, sec);
611 if (year >= 0 && year <= 9999) {
612 return FormatDate("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
613 month + 1, day, hour, min, sec, ms);
614 } else if (year < 0) {
615 return FormatDate("-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
616 month + 1, day, hour, min, sec, ms);
617 } else {
618 return FormatDate("+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
619 month + 1, day, hour, min, sec, ms);
620 }
621 }
622 UNREACHABLE();
623}
624
625// ES6 section 20.3.1.16 Date Time String Format
627 str = String::Flatten(isolate, str);
628 double out[DateParser::OUTPUT_SIZE];
630 String::FlatContent str_content = str->GetFlatContent(no_gc);
631 bool result;
632 if (str_content.IsOneByte()) {
633 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), out);
634 } else {
635 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), out);
636 }
637 if (!result) return std::numeric_limits<double>::quiet_NaN();
638 double const day = MakeDay(out[DateParser::YEAR], out[DateParser::MONTH],
639 out[DateParser::DAY]);
640 double const time =
643 double date = MakeDate(day, time);
644 if (std::isnan(out[DateParser::UTC_OFFSET])) {
647 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
648 } else {
649 return std::numeric_limits<double>::quiet_NaN();
650 }
651 } else {
652 date -= out[DateParser::UTC_OFFSET] * 1000.0;
653 }
655 return std::numeric_limits<double>::quiet_NaN();
656 }
657 return date;
658}
659
660} // namespace internal
661} // namespace v8
#define SLOW_DCHECK(condition)
Definition checks.h:21
virtual double LocalTimeOffset(double time_ms, bool is_utc)=0
virtual void Clear(TimeZoneDetection time_zone_detection)=0
int DaysFromYearMonth(int year, int month)
Definition date.cc:156
void BreakDownTime(int64_t time_ms, int *year, int *month, int *day, int *weekday, int *hour, int *min, int *sec, int *ms)
Definition date.cc:195
static int TimeInDay(int64_t time_ms, int days)
Definition date.h:62
bool InvalidSegment(CacheItem *segment)
Definition date.h:224
int DaylightSavingsOffsetInMs(int64_t time_ms)
Definition date.h:200
int LocalOffsetInMs(int64_t time, bool is_utc)
Definition date.cc:292
void YearMonthDayFromDays(int days, int *year, int *month, int *day)
Definition date.cc:77
void ExtendTheAfterSegment(int64_t time_sec, int offset_ms)
Definition date.cc:273
static const int kDefaultTimeZoneOffsetDeltaInMs
Definition date.h:186
static const int kInvalidStamp
Definition date.h:41
Tagged< Smi > stamp_
Definition date.h:228
const char * LocalTimezone(int64_t time_ms)
Definition date.h:94
base::TimezoneCache * tz_cache_
Definition date.h:249
int64_t ToLocal(int64_t time_ms)
Definition date.h:114
CacheItem * LeastRecentlyUsedCacheItem(CacheItem *skip)
Definition date.cc:463
static bool TryTimeClip(double *time)
Definition date.h:70
int Weekday(int days)
Definition date.h:82
CacheItem cache_[kCacheSize]
Definition date.h:231
static int DaysFromTime(int64_t time_ms)
Definition date.h:55
static const int kInvalidLocalOffsetInMs
Definition date.h:38
void ClearSegment(CacheItem *segment)
Definition date.cc:70
virtual int GetLocalOffsetFromOS(int64_t time_ms, bool is_utc)
Definition date.cc:210
void ResetDateCache(base::TimezoneCache::TimeZoneDetection time_zone_detection)
Definition date.cc:43
void ProbeCache(int64_t time_ms)
Definition date.cc:419
const char * tz_name_
Definition date.h:246
const char * dst_tz_name_
Definition date.h:247
CacheItem * after_
Definition date.h:234
int TimezoneOffset(int64_t time_ms)
Definition date.h:107
static const int kCacheSize
Definition date.h:188
CacheItem * before_
Definition date.h:233
static const int64_t kMaxTimeBeforeUTCInMs
Definition date.h:35
static bool Parse(Isolate *isolate, base::Vector< Char > str, double *output)
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static constexpr Tagged< Smi > zero()
Definition smi.h:99
static constexpr int kMaxValue
Definition smi.h:101
base::Vector< const uint8_t > ToOneByteVector() const
Definition string.h:139
base::Vector< const base::uc16 > ToUC16Vector() const
Definition string.h:145
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
V8_INLINE constexpr int32_t value() const
Definition tagged.h:427
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
int32_t offset
double hour
double days
DateRecord date
ZoneVector< RpoNumber > & result
int m
Definition mul-fft.cc:294
static const int kDaysOffset
Definition date.cc:25
static const char kDaysInMonths[]
Definition date.cc:28
double MakeDate(double day, double time)
Definition date.cc:491
static const int kDaysIn4Years
Definition date.cc:21
ToDateStringMode
Definition date.h:265
double DoubleToInteger(double x)
static const int kDaysIn100Years
Definition date.cc:22
DateBuffer ToDateString(double time_val, DateCache *date_cache, ToDateStringMode mode)
Definition date.cc:572
base::SmallVector< char, 128 > DateBuffer
Definition date.h:263
static const int kDays1970to2000
Definition date.cc:24
double MakeDay(double year, double month, double date)
Definition date.cc:498
double MakeTime(double hour, double min, double sec, double ms)
Definition date.cc:541
int FastD2I(double x)
V8_EXPORT_PRIVATE FlagValues v8_flags
static const int kYearsOffset
Definition date.cc:27
static constexpr Address kNullAddress
Definition v8-internal.h:53
constexpr int kMaxInt
Definition globals.h:374
double ParseDateTimeString(Isolate *isolate, DirectHandle< String > str)
Definition date.cc:626
static const int kDaysIn400Years
Definition date.cc:23
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487