Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 "use strict";
      6 
      7 // This file relies on the fact that the following declarations have been made
      8 // in v8natives.js:
      9 // var $isFinite = GlobalIsFinite;
     10 
     11 var $Date = global.Date;
     12 
     13 // -------------------------------------------------------------------
     14 
     15 // This file contains date support implemented in JavaScript.
     16 
     17 // Helper function to throw error.
     18 function ThrowDateTypeError() {
     19   throw new $TypeError('this is not a Date object.');
     20 }
     21 
     22 
     23 var timezone_cache_time = NAN;
     24 var timezone_cache_timezone;
     25 
     26 function LocalTimezone(t) {
     27   if (NUMBER_IS_NAN(t)) return "";
     28   CheckDateCacheCurrent();
     29   if (t == timezone_cache_time) {
     30     return timezone_cache_timezone;
     31   }
     32   var timezone = %DateLocalTimezone(t);
     33   timezone_cache_time = t;
     34   timezone_cache_timezone = timezone;
     35   return timezone;
     36 }
     37 
     38 
     39 function UTC(time) {
     40   if (NUMBER_IS_NAN(time)) return time;
     41   // local_time_offset is needed before the call to DaylightSavingsOffset,
     42   // so it may be uninitialized.
     43   return %DateToUTC(time);
     44 }
     45 
     46 
     47 // ECMA 262 - 15.9.1.11
     48 function MakeTime(hour, min, sec, ms) {
     49   if (!$isFinite(hour)) return NAN;
     50   if (!$isFinite(min)) return NAN;
     51   if (!$isFinite(sec)) return NAN;
     52   if (!$isFinite(ms)) return NAN;
     53   return TO_INTEGER(hour) * msPerHour
     54       + TO_INTEGER(min) * msPerMinute
     55       + TO_INTEGER(sec) * msPerSecond
     56       + TO_INTEGER(ms);
     57 }
     58 
     59 
     60 // ECMA 262 - 15.9.1.12
     61 function TimeInYear(year) {
     62   return DaysInYear(year) * msPerDay;
     63 }
     64 
     65 
     66 // Compute number of days given a year, month, date.
     67 // Note that month and date can lie outside the normal range.
     68 //   For example:
     69 //     MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
     70 //     MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
     71 //     MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
     72 function MakeDay(year, month, date) {
     73   if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return NAN;
     74 
     75   // Convert to integer and map -0 to 0.
     76   year = TO_INTEGER_MAP_MINUS_ZERO(year);
     77   month = TO_INTEGER_MAP_MINUS_ZERO(month);
     78   date = TO_INTEGER_MAP_MINUS_ZERO(date);
     79 
     80   if (year < kMinYear || year > kMaxYear ||
     81       month < kMinMonth || month > kMaxMonth) {
     82     return NAN;
     83   }
     84 
     85   // Now we rely on year and month being SMIs.
     86   return %DateMakeDay(year | 0, month | 0) + date - 1;
     87 }
     88 
     89 
     90 // ECMA 262 - 15.9.1.13
     91 function MakeDate(day, time) {
     92   var time = day * msPerDay + time;
     93   // Some of our runtime funtions for computing UTC(time) rely on
     94   // times not being significantly larger than MAX_TIME_MS. If there
     95   // is no way that the time can be within range even after UTC
     96   // conversion we return NaN immediately instead of relying on
     97   // TimeClip to do it.
     98   if ($abs(time) > MAX_TIME_BEFORE_UTC) return NAN;
     99   return time;
    100 }
    101 
    102 
    103 // ECMA 262 - 15.9.1.14
    104 function TimeClip(time) {
    105   if (!$isFinite(time)) return NAN;
    106   if ($abs(time) > MAX_TIME_MS) return NAN;
    107   return TO_INTEGER(time);
    108 }
    109 
    110 
    111 // The Date cache is used to limit the cost of parsing the same Date
    112 // strings over and over again.
    113 var Date_cache = {
    114   // Cached time value.
    115   time: 0,
    116   // String input for which the cached time is valid.
    117   string: null
    118 };
    119 
    120 
    121 function DateConstructor(year, month, date, hours, minutes, seconds, ms) {
    122   if (!%_IsConstructCall()) {
    123     // ECMA 262 - 15.9.2
    124     return (new $Date()).toString();
    125   }
    126 
    127   // ECMA 262 - 15.9.3
    128   var argc = %_ArgumentsLength();
    129   var value;
    130   if (argc == 0) {
    131     value = %DateCurrentTime();
    132     SET_UTC_DATE_VALUE(this, value);
    133   } else if (argc == 1) {
    134     if (IS_NUMBER(year)) {
    135       value = year;
    136     } else if (IS_STRING(year)) {
    137       // Probe the Date cache. If we already have a time value for the
    138       // given time, we re-use that instead of parsing the string again.
    139       CheckDateCacheCurrent();
    140       var cache = Date_cache;
    141       if (cache.string === year) {
    142         value = cache.time;
    143       } else {
    144         value = DateParse(year);
    145         if (!NUMBER_IS_NAN(value)) {
    146           cache.time = value;
    147           cache.string = year;
    148         }
    149       }
    150 
    151     } else {
    152       // According to ECMA 262, no hint should be given for this
    153       // conversion. However, ToPrimitive defaults to STRING_HINT for
    154       // Date objects which will lose precision when the Date
    155       // constructor is called with another Date object as its
    156       // argument. We therefore use NUMBER_HINT for the conversion,
    157       // which is the default for everything else than Date objects.
    158       // This makes us behave like KJS and SpiderMonkey.
    159       var time = ToPrimitive(year, NUMBER_HINT);
    160       value = IS_STRING(time) ? DateParse(time) : ToNumber(time);
    161     }
    162     SET_UTC_DATE_VALUE(this, value);
    163   } else {
    164     year = ToNumber(year);
    165     month = ToNumber(month);
    166     date = argc > 2 ? ToNumber(date) : 1;
    167     hours = argc > 3 ? ToNumber(hours) : 0;
    168     minutes = argc > 4 ? ToNumber(minutes) : 0;
    169     seconds = argc > 5 ? ToNumber(seconds) : 0;
    170     ms = argc > 6 ? ToNumber(ms) : 0;
    171     year = (!NUMBER_IS_NAN(year) &&
    172             0 <= TO_INTEGER(year) &&
    173             TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
    174     var day = MakeDay(year, month, date);
    175     var time = MakeTime(hours, minutes, seconds, ms);
    176     value = MakeDate(day, time);
    177     SET_LOCAL_DATE_VALUE(this, value);
    178   }
    179 }
    180 
    181 
    182 var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    183 var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
    184               'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    185 
    186 
    187 function TwoDigitString(value) {
    188   return value < 10 ? "0" + value : "" + value;
    189 }
    190 
    191 
    192 function DateString(date) {
    193   return WeekDays[LOCAL_WEEKDAY(date)] + ' '
    194       + Months[LOCAL_MONTH(date)] + ' '
    195       + TwoDigitString(LOCAL_DAY(date)) + ' '
    196       + LOCAL_YEAR(date);
    197 }
    198 
    199 
    200 var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
    201     'Thursday', 'Friday', 'Saturday'];
    202 var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June',
    203     'July', 'August', 'September', 'October', 'November', 'December'];
    204 
    205 
    206 function LongDateString(date) {
    207   return LongWeekDays[LOCAL_WEEKDAY(date)] + ', '
    208       + LongMonths[LOCAL_MONTH(date)] + ' '
    209       + TwoDigitString(LOCAL_DAY(date)) + ', '
    210       + LOCAL_YEAR(date);
    211 }
    212 
    213 
    214 function TimeString(date) {
    215   return TwoDigitString(LOCAL_HOUR(date)) + ':'
    216       + TwoDigitString(LOCAL_MIN(date)) + ':'
    217       + TwoDigitString(LOCAL_SEC(date));
    218 }
    219 
    220 
    221 function TimeStringUTC(date) {
    222   return TwoDigitString(UTC_HOUR(date)) + ':'
    223       + TwoDigitString(UTC_MIN(date)) + ':'
    224       + TwoDigitString(UTC_SEC(date));
    225 }
    226 
    227 
    228 function LocalTimezoneString(date) {
    229   var timezone = LocalTimezone(UTC_DATE_VALUE(date));
    230 
    231   var timezoneOffset = -TIMEZONE_OFFSET(date);
    232   var sign = (timezoneOffset >= 0) ? 1 : -1;
    233   var hours = FLOOR((sign * timezoneOffset)/60);
    234   var min   = FLOOR((sign * timezoneOffset)%60);
    235   var gmt = ' GMT' + ((sign == 1) ? '+' : '-') +
    236       TwoDigitString(hours) + TwoDigitString(min);
    237   return gmt + ' (' +  timezone + ')';
    238 }
    239 
    240 
    241 function DatePrintString(date) {
    242   return DateString(date) + ' ' + TimeString(date);
    243 }
    244 
    245 // -------------------------------------------------------------------
    246 
    247 // Reused output buffer. Used when parsing date strings.
    248 var parse_buffer = $Array(8);
    249 
    250 // ECMA 262 - 15.9.4.2
    251 function DateParse(string) {
    252   var arr = %DateParseString(ToString(string), parse_buffer);
    253   if (IS_NULL(arr)) return NAN;
    254 
    255   var day = MakeDay(arr[0], arr[1], arr[2]);
    256   var time = MakeTime(arr[3], arr[4], arr[5], arr[6]);
    257   var date = MakeDate(day, time);
    258 
    259   if (IS_NULL(arr[7])) {
    260     return TimeClip(UTC(date));
    261   } else {
    262     return TimeClip(date - arr[7] * 1000);
    263   }
    264 }
    265 
    266 
    267 // ECMA 262 - 15.9.4.3
    268 function DateUTC(year, month, date, hours, minutes, seconds, ms) {
    269   year = ToNumber(year);
    270   month = ToNumber(month);
    271   var argc = %_ArgumentsLength();
    272   date = argc > 2 ? ToNumber(date) : 1;
    273   hours = argc > 3 ? ToNumber(hours) : 0;
    274   minutes = argc > 4 ? ToNumber(minutes) : 0;
    275   seconds = argc > 5 ? ToNumber(seconds) : 0;
    276   ms = argc > 6 ? ToNumber(ms) : 0;
    277   year = (!NUMBER_IS_NAN(year) &&
    278           0 <= TO_INTEGER(year) &&
    279           TO_INTEGER(year) <= 99) ? 1900 + TO_INTEGER(year) : year;
    280   var day = MakeDay(year, month, date);
    281   var time = MakeTime(hours, minutes, seconds, ms);
    282   return TimeClip(MakeDate(day, time));
    283 }
    284 
    285 
    286 // ECMA 262 - 15.9.4.4
    287 function DateNow() {
    288   return %DateCurrentTime();
    289 }
    290 
    291 
    292 // ECMA 262 - 15.9.5.2
    293 function DateToString() {
    294   var t = UTC_DATE_VALUE(this)
    295   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    296   var time_zone_string = LocalTimezoneString(this)
    297   return DatePrintString(this) + time_zone_string;
    298 }
    299 
    300 
    301 // ECMA 262 - 15.9.5.3
    302 function DateToDateString() {
    303   var t = UTC_DATE_VALUE(this);
    304   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    305   return DateString(this);
    306 }
    307 
    308 
    309 // ECMA 262 - 15.9.5.4
    310 function DateToTimeString() {
    311   var t = UTC_DATE_VALUE(this);
    312   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    313   var time_zone_string = LocalTimezoneString(this);
    314   return TimeString(this) + time_zone_string;
    315 }
    316 
    317 
    318 // ECMA 262 - 15.9.5.5
    319 function DateToLocaleString() {
    320   return %_CallFunction(this, DateToString);
    321 }
    322 
    323 
    324 // ECMA 262 - 15.9.5.6
    325 function DateToLocaleDateString() {
    326   var t = UTC_DATE_VALUE(this);
    327   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    328   return LongDateString(this);
    329 }
    330 
    331 
    332 // ECMA 262 - 15.9.5.7
    333 function DateToLocaleTimeString() {
    334   var t = UTC_DATE_VALUE(this);
    335   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    336   return TimeString(this);
    337 }
    338 
    339 
    340 // ECMA 262 - 15.9.5.8
    341 function DateValueOf() {
    342   return UTC_DATE_VALUE(this);
    343 }
    344 
    345 
    346 // ECMA 262 - 15.9.5.9
    347 function DateGetTime() {
    348   return UTC_DATE_VALUE(this);
    349 }
    350 
    351 
    352 // ECMA 262 - 15.9.5.10
    353 function DateGetFullYear() {
    354   return LOCAL_YEAR(this);
    355 }
    356 
    357 
    358 // ECMA 262 - 15.9.5.11
    359 function DateGetUTCFullYear() {
    360   return UTC_YEAR(this);
    361 }
    362 
    363 
    364 // ECMA 262 - 15.9.5.12
    365 function DateGetMonth() {
    366   return LOCAL_MONTH(this);
    367 }
    368 
    369 
    370 // ECMA 262 - 15.9.5.13
    371 function DateGetUTCMonth() {
    372   return UTC_MONTH(this);
    373 }
    374 
    375 
    376 // ECMA 262 - 15.9.5.14
    377 function DateGetDate() {
    378   return LOCAL_DAY(this);
    379 }
    380 
    381 
    382 // ECMA 262 - 15.9.5.15
    383 function DateGetUTCDate() {
    384   return UTC_DAY(this);
    385 }
    386 
    387 
    388 // ECMA 262 - 15.9.5.16
    389 function DateGetDay() {
    390   return LOCAL_WEEKDAY(this);
    391 }
    392 
    393 
    394 // ECMA 262 - 15.9.5.17
    395 function DateGetUTCDay() {
    396   return UTC_WEEKDAY(this);
    397 }
    398 
    399 
    400 // ECMA 262 - 15.9.5.18
    401 function DateGetHours() {
    402   return LOCAL_HOUR(this);
    403 }
    404 
    405 
    406 // ECMA 262 - 15.9.5.19
    407 function DateGetUTCHours() {
    408   return UTC_HOUR(this);
    409 }
    410 
    411 
    412 // ECMA 262 - 15.9.5.20
    413 function DateGetMinutes() {
    414   return LOCAL_MIN(this);
    415 }
    416 
    417 
    418 // ECMA 262 - 15.9.5.21
    419 function DateGetUTCMinutes() {
    420   return UTC_MIN(this);
    421 }
    422 
    423 
    424 // ECMA 262 - 15.9.5.22
    425 function DateGetSeconds() {
    426   return LOCAL_SEC(this);
    427 }
    428 
    429 
    430 // ECMA 262 - 15.9.5.23
    431 function DateGetUTCSeconds() {
    432   return UTC_SEC(this)
    433 }
    434 
    435 
    436 // ECMA 262 - 15.9.5.24
    437 function DateGetMilliseconds() {
    438   return LOCAL_MS(this);
    439 }
    440 
    441 
    442 // ECMA 262 - 15.9.5.25
    443 function DateGetUTCMilliseconds() {
    444   return UTC_MS(this);
    445 }
    446 
    447 
    448 // ECMA 262 - 15.9.5.26
    449 function DateGetTimezoneOffset() {
    450   return TIMEZONE_OFFSET(this);
    451 }
    452 
    453 
    454 // ECMA 262 - 15.9.5.27
    455 function DateSetTime(ms) {
    456   CHECK_DATE(this);
    457   SET_UTC_DATE_VALUE(this, ToNumber(ms));
    458   return UTC_DATE_VALUE(this);
    459 }
    460 
    461 
    462 // ECMA 262 - 15.9.5.28
    463 function DateSetMilliseconds(ms) {
    464   var t = LOCAL_DATE_VALUE(this);
    465   ms = ToNumber(ms);
    466   var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms);
    467   return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
    468 }
    469 
    470 
    471 // ECMA 262 - 15.9.5.29
    472 function DateSetUTCMilliseconds(ms) {
    473   var t = UTC_DATE_VALUE(this);
    474   ms = ToNumber(ms);
    475   var time = MakeTime(UTC_HOUR(this),
    476                       UTC_MIN(this),
    477                       UTC_SEC(this),
    478                       ms);
    479   return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
    480 }
    481 
    482 
    483 // ECMA 262 - 15.9.5.30
    484 function DateSetSeconds(sec, ms) {
    485   var t = LOCAL_DATE_VALUE(this);
    486   sec = ToNumber(sec);
    487   ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : ToNumber(ms);
    488   var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), sec, ms);
    489   return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
    490 }
    491 
    492 
    493 // ECMA 262 - 15.9.5.31
    494 function DateSetUTCSeconds(sec, ms) {
    495   var t = UTC_DATE_VALUE(this);
    496   sec = ToNumber(sec);
    497   ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : ToNumber(ms);
    498   var time = MakeTime(UTC_HOUR(this), UTC_MIN(this), sec, ms);
    499   return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
    500 }
    501 
    502 
    503 // ECMA 262 - 15.9.5.33
    504 function DateSetMinutes(min, sec, ms) {
    505   var t = LOCAL_DATE_VALUE(this);
    506   min = ToNumber(min);
    507   var argc = %_ArgumentsLength();
    508   sec = argc < 2 ? LOCAL_SEC(this) : ToNumber(sec);
    509   ms = argc < 3 ? LOCAL_MS(this) : ToNumber(ms);
    510   var time = MakeTime(LOCAL_HOUR(this), min, sec, ms);
    511   return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
    512 }
    513 
    514 
    515 // ECMA 262 - 15.9.5.34
    516 function DateSetUTCMinutes(min, sec, ms) {
    517   var t = UTC_DATE_VALUE(this);
    518   min = ToNumber(min);
    519   var argc = %_ArgumentsLength();
    520   sec = argc < 2 ? UTC_SEC(this) : ToNumber(sec);
    521   ms = argc < 3 ? UTC_MS(this) : ToNumber(ms);
    522   var time = MakeTime(UTC_HOUR(this), min, sec, ms);
    523   return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
    524 }
    525 
    526 
    527 // ECMA 262 - 15.9.5.35
    528 function DateSetHours(hour, min, sec, ms) {
    529   var t = LOCAL_DATE_VALUE(this);
    530   hour = ToNumber(hour);
    531   var argc = %_ArgumentsLength();
    532   min = argc < 2 ? LOCAL_MIN(this) : ToNumber(min);
    533   sec = argc < 3 ? LOCAL_SEC(this) : ToNumber(sec);
    534   ms = argc < 4 ? LOCAL_MS(this) : ToNumber(ms);
    535   var time = MakeTime(hour, min, sec, ms);
    536   return SET_LOCAL_DATE_VALUE(this, MakeDate(LOCAL_DAYS(this), time));
    537 }
    538 
    539 
    540 // ECMA 262 - 15.9.5.34
    541 function DateSetUTCHours(hour, min, sec, ms) {
    542   var t = UTC_DATE_VALUE(this);
    543   hour = ToNumber(hour);
    544   var argc = %_ArgumentsLength();
    545   min = argc < 2 ? UTC_MIN(this) : ToNumber(min);
    546   sec = argc < 3 ? UTC_SEC(this) : ToNumber(sec);
    547   ms = argc < 4 ? UTC_MS(this) : ToNumber(ms);
    548   var time = MakeTime(hour, min, sec, ms);
    549   return SET_UTC_DATE_VALUE(this, MakeDate(UTC_DAYS(this), time));
    550 }
    551 
    552 
    553 // ECMA 262 - 15.9.5.36
    554 function DateSetDate(date) {
    555   var t = LOCAL_DATE_VALUE(this);
    556   date = ToNumber(date);
    557   var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
    558   return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
    559 }
    560 
    561 
    562 // ECMA 262 - 15.9.5.37
    563 function DateSetUTCDate(date) {
    564   var t = UTC_DATE_VALUE(this);
    565   date = ToNumber(date);
    566   var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
    567   return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
    568 }
    569 
    570 
    571 // ECMA 262 - 15.9.5.38
    572 function DateSetMonth(month, date) {
    573   var t = LOCAL_DATE_VALUE(this);
    574   month = ToNumber(month);
    575   date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : ToNumber(date);
    576   var day = MakeDay(LOCAL_YEAR(this), month, date);
    577   return SET_LOCAL_DATE_VALUE(this, MakeDate(day, LOCAL_TIME_IN_DAY(this)));
    578 }
    579 
    580 
    581 // ECMA 262 - 15.9.5.39
    582 function DateSetUTCMonth(month, date) {
    583   var t = UTC_DATE_VALUE(this);
    584   month = ToNumber(month);
    585   date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : ToNumber(date);
    586   var day = MakeDay(UTC_YEAR(this), month, date);
    587   return SET_UTC_DATE_VALUE(this, MakeDate(day, UTC_TIME_IN_DAY(this)));
    588 }
    589 
    590 
    591 // ECMA 262 - 15.9.5.40
    592 function DateSetFullYear(year, month, date) {
    593   var t = LOCAL_DATE_VALUE(this);
    594   year = ToNumber(year);
    595   var argc = %_ArgumentsLength();
    596   var time ;
    597   if (NUMBER_IS_NAN(t)) {
    598     month = argc < 2 ? 0 : ToNumber(month);
    599     date = argc < 3 ? 1 : ToNumber(date);
    600     time = 0;
    601   } else {
    602     month = argc < 2 ? LOCAL_MONTH(this) : ToNumber(month);
    603     date = argc < 3 ? LOCAL_DAY(this) : ToNumber(date);
    604     time = LOCAL_TIME_IN_DAY(this);
    605   }
    606   var day = MakeDay(year, month, date);
    607   return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
    608 }
    609 
    610 
    611 // ECMA 262 - 15.9.5.41
    612 function DateSetUTCFullYear(year, month, date) {
    613   var t = UTC_DATE_VALUE(this);
    614   year = ToNumber(year);
    615   var argc = %_ArgumentsLength();
    616   var time ;
    617   if (NUMBER_IS_NAN(t)) {
    618     month = argc < 2 ? 0 : ToNumber(month);
    619     date = argc < 3 ? 1 : ToNumber(date);
    620     time = 0;
    621   } else {
    622     month = argc < 2 ? UTC_MONTH(this) : ToNumber(month);
    623     date = argc < 3 ? UTC_DAY(this) : ToNumber(date);
    624     time = UTC_TIME_IN_DAY(this);
    625   }
    626   var day = MakeDay(year, month, date);
    627   return SET_UTC_DATE_VALUE(this, MakeDate(day, time));
    628 }
    629 
    630 
    631 // ECMA 262 - 15.9.5.42
    632 function DateToUTCString() {
    633   var t = UTC_DATE_VALUE(this);
    634   if (NUMBER_IS_NAN(t)) return kInvalidDate;
    635   // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
    636   return WeekDays[UTC_WEEKDAY(this)] + ', '
    637       + TwoDigitString(UTC_DAY(this)) + ' '
    638       + Months[UTC_MONTH(this)] + ' '
    639       + UTC_YEAR(this) + ' '
    640       + TimeStringUTC(this) + ' GMT';
    641 }
    642 
    643 
    644 // ECMA 262 - B.2.4
    645 function DateGetYear() {
    646   return LOCAL_YEAR(this) - 1900;
    647 }
    648 
    649 
    650 // ECMA 262 - B.2.5
    651 function DateSetYear(year) {
    652   CHECK_DATE(this);
    653   year = ToNumber(year);
    654   if (NUMBER_IS_NAN(year)) return SET_UTC_DATE_VALUE(this, NAN);
    655   year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
    656       ? 1900 + TO_INTEGER(year) : year;
    657   var t = LOCAL_DATE_VALUE(this);
    658   var month, date, time;
    659   if (NUMBER_IS_NAN(t))  {
    660     month = 0;
    661     date = 1;
    662     time = 0;
    663   } else {
    664     month = LOCAL_MONTH(this);
    665     date = LOCAL_DAY(this);
    666     time = LOCAL_TIME_IN_DAY(this);
    667   }
    668   var day = MakeDay(year, month, date);
    669   return SET_LOCAL_DATE_VALUE(this, MakeDate(day, time));
    670 }
    671 
    672 
    673 // ECMA 262 - B.2.6
    674 //
    675 // Notice that this does not follow ECMA 262 completely.  ECMA 262
    676 // says that toGMTString should be the same Function object as
    677 // toUTCString.  JSC does not do this, so for compatibility we do not
    678 // do that either.  Instead, we create a new function whose name
    679 // property will return toGMTString.
    680 function DateToGMTString() {
    681   return %_CallFunction(this, DateToUTCString);
    682 }
    683 
    684 
    685 function PadInt(n, digits) {
    686   if (digits == 1) return n;
    687   return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
    688 }
    689 
    690 
    691 // ECMA 262 - 15.9.5.43
    692 function DateToISOString() {
    693   var t = UTC_DATE_VALUE(this);
    694   if (NUMBER_IS_NAN(t)) throw MakeRangeError("invalid_time_value", []);
    695   var year = this.getUTCFullYear();
    696   var year_string;
    697   if (year >= 0 && year <= 9999) {
    698     year_string = PadInt(year, 4);
    699   } else {
    700     if (year < 0) {
    701       year_string = "-" + PadInt(-year, 6);
    702     } else {
    703       year_string = "+" + PadInt(year, 6);
    704     }
    705   }
    706   return year_string +
    707       '-' + PadInt(this.getUTCMonth() + 1, 2) +
    708       '-' + PadInt(this.getUTCDate(), 2) +
    709       'T' + PadInt(this.getUTCHours(), 2) +
    710       ':' + PadInt(this.getUTCMinutes(), 2) +
    711       ':' + PadInt(this.getUTCSeconds(), 2) +
    712       '.' + PadInt(this.getUTCMilliseconds(), 3) +
    713       'Z';
    714 }
    715 
    716 
    717 function DateToJSON(key) {
    718   var o = ToObject(this);
    719   var tv = DefaultNumber(o);
    720   if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
    721     return null;
    722   }
    723   return o.toISOString();
    724 }
    725 
    726 
    727 var date_cache_version_holder;
    728 var date_cache_version = NAN;
    729 
    730 
    731 function CheckDateCacheCurrent() {
    732   if (!date_cache_version_holder) {
    733     date_cache_version_holder = %DateCacheVersion();
    734   }
    735   if (date_cache_version_holder[0] == date_cache_version) {
    736     return;
    737   }
    738   date_cache_version = date_cache_version_holder[0];
    739 
    740   // Reset the timezone cache:
    741   timezone_cache_time = NAN;
    742   timezone_cache_timezone = UNDEFINED;
    743 
    744   // Reset the date cache:
    745   Date_cache.time = NAN;
    746   Date_cache.string = null;
    747 }
    748 
    749 
    750 // -------------------------------------------------------------------
    751 
    752 function SetUpDate() {
    753   %CheckIsBootstrapping();
    754 
    755   %SetCode($Date, DateConstructor);
    756   %FunctionSetPrototype($Date, new $Date(NAN));
    757 
    758   // Set up non-enumerable properties of the Date object itself.
    759   InstallFunctions($Date, DONT_ENUM, $Array(
    760     "UTC", DateUTC,
    761     "parse", DateParse,
    762     "now", DateNow
    763   ));
    764 
    765   // Set up non-enumerable constructor property of the Date prototype object.
    766   %AddNamedProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
    767 
    768   // Set up non-enumerable functions of the Date prototype object and
    769   // set their names.
    770   InstallFunctions($Date.prototype, DONT_ENUM, $Array(
    771     "toString", DateToString,
    772     "toDateString", DateToDateString,
    773     "toTimeString", DateToTimeString,
    774     "toLocaleString", DateToLocaleString,
    775     "toLocaleDateString", DateToLocaleDateString,
    776     "toLocaleTimeString", DateToLocaleTimeString,
    777     "valueOf", DateValueOf,
    778     "getTime", DateGetTime,
    779     "getFullYear", DateGetFullYear,
    780     "getUTCFullYear", DateGetUTCFullYear,
    781     "getMonth", DateGetMonth,
    782     "getUTCMonth", DateGetUTCMonth,
    783     "getDate", DateGetDate,
    784     "getUTCDate", DateGetUTCDate,
    785     "getDay", DateGetDay,
    786     "getUTCDay", DateGetUTCDay,
    787     "getHours", DateGetHours,
    788     "getUTCHours", DateGetUTCHours,
    789     "getMinutes", DateGetMinutes,
    790     "getUTCMinutes", DateGetUTCMinutes,
    791     "getSeconds", DateGetSeconds,
    792     "getUTCSeconds", DateGetUTCSeconds,
    793     "getMilliseconds", DateGetMilliseconds,
    794     "getUTCMilliseconds", DateGetUTCMilliseconds,
    795     "getTimezoneOffset", DateGetTimezoneOffset,
    796     "setTime", DateSetTime,
    797     "setMilliseconds", DateSetMilliseconds,
    798     "setUTCMilliseconds", DateSetUTCMilliseconds,
    799     "setSeconds", DateSetSeconds,
    800     "setUTCSeconds", DateSetUTCSeconds,
    801     "setMinutes", DateSetMinutes,
    802     "setUTCMinutes", DateSetUTCMinutes,
    803     "setHours", DateSetHours,
    804     "setUTCHours", DateSetUTCHours,
    805     "setDate", DateSetDate,
    806     "setUTCDate", DateSetUTCDate,
    807     "setMonth", DateSetMonth,
    808     "setUTCMonth", DateSetUTCMonth,
    809     "setFullYear", DateSetFullYear,
    810     "setUTCFullYear", DateSetUTCFullYear,
    811     "toGMTString", DateToGMTString,
    812     "toUTCString", DateToUTCString,
    813     "getYear", DateGetYear,
    814     "setYear", DateSetYear,
    815     "toISOString", DateToISOString,
    816     "toJSON", DateToJSON
    817   ));
    818 }
    819 
    820 SetUpDate();
    821