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