c58903cc29c23f653f99e0baf4e61ab129ccee3f
[platform/framework/web/crosswalk.git] / src / v8 / src / date.js
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   %SetProperty($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();