From 5f75b01bb1e25a374c517aedc11a88de597590ff Mon Sep 17 00:00:00 2001 From: "oleg@chromium.org" Date: Fri, 12 Mar 2010 13:01:32 +0000 Subject: [PATCH] Rewrite the function that converts timestamp to year, month and day in C++. Review URL: http://codereview.chromium.org/811006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4115 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/date-delay.js | 101 ++++++++--------- src/macros.py | 6 +- src/runtime.cc | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/runtime.h | 1 + 4 files changed, 371 insertions(+), 69 deletions(-) diff --git a/src/date-delay.js b/src/date-delay.js index c0180c2..f2ea1ec 100644 --- a/src/date-delay.js +++ b/src/date-delay.js @@ -293,55 +293,48 @@ function CalculateDateTable() { } -// Constructor for creating objects holding year, month, and date. -// Introduced to ensure the two return points in FromJulianDay match same map. -function DayTriplet(year, month, date) { - this.year = year; - this.month = month; - this.date = date; -} - -var julian_day_cache_triplet; -var julian_day_cache_day = $NaN; - -// Compute year, month, and day from modified Julian day. -// The missing days in 1582 are ignored for JavaScript compatibility. -function FromJulianDay(julian) { - if (julian_day_cache_day == julian) { - return julian_day_cache_triplet; +var ymd_from_time_cache = [$NaN, $NaN, $NaN]; +var ymd_from_time_cached_time = $NaN; + +function YearFromTime(t) { + if (t !== ymd_from_time_cached_time) { + // Limits according to ECMA 262 15.9.1.1 + if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) { + return $NaN; + } + + %DateYMDFromTime(t, ymd_from_time_cache); + ymd_from_time_cached_time = t } - var result; - // Avoid floating point and non-Smi maths in common case. This is also a period of - // time where leap years are very regular. The range is not too large to avoid overflow - // when doing the multiply-to-divide trick. - if (julian > kDayZeroInJulianDay && - (julian - kDayZeroInJulianDay) < 40177) { // 1970 - 2080 - var jsimple = (julian - kDayZeroInJulianDay) + 731; // Day 0 is 1st January 1968 - var y = 1968; - // Divide by 1461 by multiplying with 22967 and shifting down by 25! - var after_1968 = (jsimple * 22967) >> 25; - y += after_1968 << 2; - jsimple -= 1461 * after_1968; - var four_year_cycle = four_year_cycle_table[jsimple]; - result = new DayTriplet(y + (four_year_cycle >> kYearShift), - (four_year_cycle & kMonthMask) >> kMonthShift, - four_year_cycle & kDayMask); - } else { - var jalpha = FLOOR((julian - 1867216.25) / 36524.25); - var jb = julian + 1 + jalpha - FLOOR(0.25 * jalpha) + 1524; - var jc = FLOOR(6680.0 + ((jb-2439870) - 122.1)/365.25); - var jd = FLOOR(365 * jc + (0.25 * jc)); - var je = FLOOR((jb - jd)/30.6001); - var m = je - 1; - if (m > 12) m -= 13; - var y = jc - 4715; - if (m > 2) { --y; --m; } - var d = jb - jd - FLOOR(30.6001 * je); - result = new DayTriplet(y, m, d); + + return ymd_from_time_cache[0]; +} + +function MonthFromTime(t) { + if (t !== ymd_from_time_cached_time) { + // Limits according to ECMA 262 15.9.1.1 + if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) { + return $NaN; + } + %DateYMDFromTime(t, ymd_from_time_cache); + ymd_from_time_cached_time = t } - julian_day_cache_day = julian; - julian_day_cache_triplet = result; - return result; + + return ymd_from_time_cache[1]; +} + +function DateFromTime(t) { + if (t !== ymd_from_time_cached_time) { + // Limits according to ECMA 262 15.9.1.1 + if (!$isFinite(t) || t < -8640000000000000 || t > 8640000000000000) { + return $NaN; + } + + %DateYMDFromTime(t, ymd_from_time_cache); + ymd_from_time_cached_time = t + } + + return ymd_from_time_cache[2]; } @@ -577,11 +570,10 @@ function TwoDigitString(value) { function DateString(time) { - var YMD = FromJulianDay(DAY(time) + kDayZeroInJulianDay); return WeekDays[WeekDay(time)] + ' ' - + Months[YMD.month] + ' ' - + TwoDigitString(YMD.date) + ' ' - + YMD.year; + + Months[MonthFromTime(time)] + ' ' + + TwoDigitString(DateFromTime(time)) + ' ' + + YearFromTime(time); } @@ -590,11 +582,10 @@ var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July' function LongDateString(time) { - var YMD = FromJulianDay(DAY(time) + kDayZeroInJulianDay); return LongWeekDays[WeekDay(time)] + ', ' - + LongMonths[YMD.month] + ' ' - + TwoDigitString(YMD.date) + ', ' - + YMD.year; + + LongMonths[MonthFromTime(time)] + ' ' + + TwoDigitString(DateFromTime(time)) + ', ' + + YearFromTime(time); } diff --git a/src/macros.py b/src/macros.py index 9da2552..122b057 100644 --- a/src/macros.py +++ b/src/macros.py @@ -136,9 +136,9 @@ macro NUMBER_OF_CAPTURES(array) = ((array)[0]); # a type error is thrown. macro DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_ValueOf(arg) : ThrowDateTypeError()); macro DAY(time) = ($floor(time / 86400000)); -macro MONTH_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).month); -macro DATE_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).date); -macro YEAR_FROM_TIME(time) = (FromJulianDay(($floor(time / 86400000)) + 2440588).year); +macro MONTH_FROM_TIME(time) = (MonthFromTime(time)); +macro DATE_FROM_TIME(time) = (DateFromTime(time)); +macro YEAR_FROM_TIME(time) = (YearFromTime(time)); macro HOUR_FROM_TIME(time) = (Modulo($floor(time / 3600000), 24)); macro MIN_FROM_TIME(time) = (Modulo($floor(time / 60000), 60)); macro SEC_FROM_TIME(time) = (Modulo($floor(time / 1000), 60)); diff --git a/src/runtime.cc b/src/runtime.cc index 04ea02b..c95cc21 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -5128,14 +5128,7 @@ static Object* Runtime_Math_tan(Arguments args) { } -static Object* Runtime_DateMakeDay(Arguments args) { - NoHandleAllocation ha; - ASSERT(args.length() == 3); - - CONVERT_SMI_CHECKED(year, args[0]); - CONVERT_SMI_CHECKED(month, args[1]); - CONVERT_SMI_CHECKED(date, args[2]); - +static int MakeDay(int year, int month, int day) { static const int day_from_month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, @@ -5157,7 +5150,7 @@ static Object* Runtime_DateMakeDay(Arguments args) { // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of // Jan 1 1970. This is required so that we don't run into integer // division of negative numbers. - // c) there shouldn't be overflow for 32-bit integers in the following + // c) there shouldn't be an overflow for 32-bit integers in the following // operations. static const int year_delta = 399999; static const int base_day = 365 * (1970 + year_delta) + @@ -5173,10 +5166,327 @@ static Object* Runtime_DateMakeDay(Arguments args) { base_day; if (year % 4 || (year % 100 == 0 && year % 400 != 0)) { - return Smi::FromInt(day_from_year + day_from_month[month] + date - 1); + return day_from_year + day_from_month[month] + day - 1; } - return Smi::FromInt(day_from_year + day_from_month_leap[month] + date - 1); + return day_from_year + day_from_month_leap[month] + day - 1; +} + + +static Object* Runtime_DateMakeDay(Arguments args) { + NoHandleAllocation ha; + ASSERT(args.length() == 3); + + CONVERT_SMI_CHECKED(year, args[0]); + CONVERT_SMI_CHECKED(month, args[1]); + CONVERT_SMI_CHECKED(date, args[2]); + + return Smi::FromInt(MakeDay(year, month, date)); +} + + +static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1}; +static const int kDaysIn4Years = 4 * 365 + 1; +static const int kDaysIn100Years = 25 * kDaysIn4Years - 1; +static const int kDaysIn400Years = 4 * kDaysIn100Years + 1; +static const int kDays1970to2000 = 30 * 365 + 7; +static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years - + kDays1970to2000; +static const int kYearsOffset = 400000; + +static const char kDayInYear[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + +static const char kMonthInYear[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + + +// This function works for dates from 1970 to 2099. +static inline void DateYMDFromTimeAfter1970(int date, + int &year, int &month, int &day) { +#ifdef DEBUG + int save_date = date; // Need this for ASSERT in the end. +#endif + + year = 1970 + (4 * date + 2) / kDaysIn4Years; + date %= kDaysIn4Years; + + month = kMonthInYear[date]; + day = kDayInYear[date]; + + ASSERT(MakeDay(year, month, day) == save_date); +} + + +static inline void DateYMDFromTimeSlow(int date, + int &year, int &month, int &day) { +#ifdef DEBUG + int save_date = date; // Need this for ASSERT in the end. +#endif + + date += kDaysOffset; + year = 400 * (date / kDaysIn400Years) - kYearsOffset; + date %= kDaysIn400Years; + + ASSERT(MakeDay(year, 0, 1) + date == save_date); + + date--; + int yd1 = date / kDaysIn100Years; + date %= kDaysIn100Years; + year += 100 * yd1; + + date++; + int yd2 = date / kDaysIn4Years; + date %= kDaysIn4Years; + year += 4 * yd2; + + date--; + int yd3 = date / 365; + date %= 365; + year += yd3; + + bool is_leap = (!yd1 || yd2) && !yd3; + + ASSERT(date >= -1); + ASSERT(is_leap || date >= 0); + ASSERT(date < 365 || is_leap && date < 366); + ASSERT(is_leap == (year % 4 == 0 && (year % 100 || (year % 400 == 0)))); + ASSERT(is_leap || MakeDay(year, 0, 1) + date == save_date); + ASSERT(!is_leap || MakeDay(year, 0, 1) + date + 1 == save_date); + + if (is_leap) { + day = kDayInYear[2*365 + 1 + date]; + month = kMonthInYear[2*365 + 1 + date]; + } else { + day = kDayInYear[date]; + month = kMonthInYear[date]; + } + + ASSERT(MakeDay(year, month, day) == save_date); +} + + +static inline void DateYMDFromTime(int date, + int &year, int &month, int &day) { + if (date >= 0 && date < 32 * kDaysIn4Years) { + DateYMDFromTimeAfter1970(date, year, month, day); + } else { + DateYMDFromTimeSlow(date, year, month, day); + } +} + + +static Object* Runtime_DateYMDFromTime(Arguments args) { + NoHandleAllocation ha; + ASSERT(args.length() == 2); + + CONVERT_DOUBLE_CHECKED(t, args[0]); + CONVERT_CHECKED(JSArray, res_array, args[1]); + + int year, month, day; + DateYMDFromTime(static_cast(floor(t / 86400000)), year, month, day); + + res_array->SetElement(0, Smi::FromInt(year)); + res_array->SetElement(1, Smi::FromInt(month)); + res_array->SetElement(2, Smi::FromInt(day)); + + return Heap::undefined_value(); } diff --git a/src/runtime.h b/src/runtime.h index 4539048..143f636 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -204,6 +204,7 @@ namespace internal { F(DateLocalTimeOffset, 0, 1) \ F(DateDaylightSavingsOffset, 1, 1) \ F(DateMakeDay, 3, 1) \ + F(DateYMDFromTime, 2, 1) \ \ /* Numbers */ \ F(NumberIsFinite, 1, 1) \ -- 2.7.4