blob: 79b846d4a7060efc938990330cf8396b07224073 [file] [log] [blame]
Andrei Popescu31002712010-02-23 13:46:05 +00001// 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// const $isFinite = GlobalIsFinite;
32
33// -------------------------------------------------------------------
34
35// This file contains date support implemented in JavaScript.
36
37
38// Keep reference to original values of some global properties. This
39// has the added benefit that the code in this file is isolated from
40// changes to these properties.
41const $Date = global.Date;
42
43// Helper function to throw error.
44function ThrowDateTypeError() {
45 throw new $TypeError('this is not a Date object.');
46}
47
48// ECMA 262 - 5.2
49function Modulo(value, remainder) {
50 var mod = value % remainder;
51 // Guard against returning -0.
52 if (mod == 0) return 0;
53 return mod >= 0 ? mod : mod + remainder;
54}
55
56
57function TimeWithinDay(time) {
58 return Modulo(time, msPerDay);
59}
60
61
62// ECMA 262 - 15.9.1.3
63function DaysInYear(year) {
64 if (year % 4 != 0) return 365;
65 if ((year % 100 == 0) && (year % 400 != 0)) return 365;
66 return 366;
67}
68
69
70function DayFromYear(year) {
71 return 365 * (year-1970)
72 + FLOOR((year-1969)/4)
73 - FLOOR((year-1901)/100)
74 + FLOOR((year-1601)/400);
75}
76
77
78function TimeFromYear(year) {
79 return msPerDay * DayFromYear(year);
80}
81
82
83function InLeapYear(time) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010084 return DaysInYear(YearFromTime(time)) - 365; // Returns 1 or 0.
Andrei Popescu31002712010-02-23 13:46:05 +000085}
86
87
88// ECMA 262 - 15.9.1.9
89function EquivalentYear(year) {
90 // Returns an equivalent year in the range [2008-2035] matching
91 // - leap year.
92 // - week day of first day.
93 var time = TimeFromYear(year);
94 var recent_year = (InLeapYear(time) == 0 ? 1967 : 1956) +
95 (WeekDay(time) * 12) % 28;
96 // Find the year in the range 2008..2037 that is equivalent mod 28.
97 // Add 3*28 to give a positive argument to the modulus operator.
98 return 2008 + (recent_year + 3*28 - 2008) % 28;
99}
100
101
102function EquivalentTime(t) {
103 // The issue here is that some library calls don't work right for dates
104 // that cannot be represented using a non-negative signed 32 bit integer
105 // (measured in whole seconds based on the 1970 epoch).
106 // We solve this by mapping the time to a year with same leap-year-ness
107 // and same starting day for the year. The ECMAscript specification says
108 // we must do this, but for compatibility with other browsers, we use
109 // the actual year if it is in the range 1970..2037
110 if (t >= 0 && t <= 2.1e12) return t;
Steve Block6ded16b2010-05-10 14:33:55 +0100111
Ben Murdochb0fe1622011-05-05 13:52:32 +0100112 var day = MakeDay(EquivalentYear(YearFromTime(t)),
113 MonthFromTime(t),
114 DateFromTime(t));
Steve Block6ded16b2010-05-10 14:33:55 +0100115 return MakeDate(day, TimeWithinDay(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000116}
117
118
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100119// local_time_offset is initialized when the DST_offset_cache is missed.
120// It must not be used until after a call to DaylightSavingsOffset().
121// In this way, only one check, for a DST cache miss, is needed.
122var local_time_offset;
123
124
125// Because computing the DST offset is an expensive operation,
126// we keep a cache of the last computed DST offset along with a time interval
Andrei Popescu31002712010-02-23 13:46:05 +0000127// where we know the cache is valid.
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100128// When the cache is valid, local_time_offset is also valid.
Andrei Popescu31002712010-02-23 13:46:05 +0000129var DST_offset_cache = {
130 // Cached DST offset.
131 offset: 0,
132 // Time interval where the cached offset is valid.
133 start: 0, end: -1,
134 // Size of next interval expansion.
Iain Merrick75681382010-08-19 15:07:18 +0100135 increment: 0,
136 initial_increment: 19 * msPerDay
Andrei Popescu31002712010-02-23 13:46:05 +0000137};
138
139
140// NOTE: The implementation relies on the fact that no time zones have
Iain Merrick75681382010-08-19 15:07:18 +0100141// more than one daylight savings offset change per 19 days.
142//
143// In Egypt in 2010 they decided to suspend DST during Ramadan. This
144// led to a short interval where DST is in effect from September 10 to
145// September 30.
146//
Andrei Popescu31002712010-02-23 13:46:05 +0000147// If this function is called with NaN it returns NaN.
148function DaylightSavingsOffset(t) {
149 // Load the cache object from the builtins object.
150 var cache = DST_offset_cache;
151
152 // Cache the start and the end in local variables for fast access.
153 var start = cache.start;
154 var end = cache.end;
155
156 if (start <= t) {
157 // If the time fits in the cached interval, return the cached offset.
158 if (t <= end) return cache.offset;
159
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100160 // If the cache misses, the local_time_offset may not be initialized.
161 if (IS_UNDEFINED(local_time_offset)) {
162 local_time_offset = %DateLocalTimeOffset();
163 }
164
Andrei Popescu31002712010-02-23 13:46:05 +0000165 // Compute a possible new interval end.
166 var new_end = end + cache.increment;
167
168 if (t <= new_end) {
169 var end_offset = %DateDaylightSavingsOffset(EquivalentTime(new_end));
170 if (cache.offset == end_offset) {
171 // If the offset at the end of the new interval still matches
172 // the offset in the cache, we grow the cached time interval
173 // and return the offset.
174 cache.end = new_end;
Iain Merrick75681382010-08-19 15:07:18 +0100175 cache.increment = cache.initial_increment;
Andrei Popescu31002712010-02-23 13:46:05 +0000176 return end_offset;
177 } else {
178 var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
179 if (offset == end_offset) {
180 // The offset at the given time is equal to the offset at the
181 // new end of the interval, so that means that we've just skipped
182 // the point in time where the DST offset change occurred. Updated
183 // the interval to reflect this and reset the increment.
184 cache.start = t;
185 cache.end = new_end;
Iain Merrick75681382010-08-19 15:07:18 +0100186 cache.increment = cache.initial_increment;
Andrei Popescu31002712010-02-23 13:46:05 +0000187 } else {
188 // The interval contains a DST offset change and the given time is
189 // before it. Adjust the increment to avoid a linear search for
190 // the offset change point and change the end of the interval.
191 cache.increment /= 3;
192 cache.end = t;
193 }
194 // Update the offset in the cache and return it.
195 cache.offset = offset;
196 return offset;
197 }
198 }
199 }
200
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100201 // If the cache misses, the local_time_offset may not be initialized.
202 if (IS_UNDEFINED(local_time_offset)) {
203 local_time_offset = %DateLocalTimeOffset();
204 }
Andrei Popescu31002712010-02-23 13:46:05 +0000205 // Compute the DST offset for the time and shrink the cache interval
206 // to only contain the time. This allows fast repeated DST offset
207 // computations for the same time.
208 var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
209 cache.offset = offset;
210 cache.start = cache.end = t;
Iain Merrick75681382010-08-19 15:07:18 +0100211 cache.increment = cache.initial_increment;
Andrei Popescu31002712010-02-23 13:46:05 +0000212 return offset;
213}
214
215
216var timezone_cache_time = $NaN;
217var timezone_cache_timezone;
218
219function LocalTimezone(t) {
220 if (NUMBER_IS_NAN(t)) return "";
221 if (t == timezone_cache_time) {
222 return timezone_cache_timezone;
223 }
224 var timezone = %DateLocalTimezone(EquivalentTime(t));
225 timezone_cache_time = t;
226 timezone_cache_timezone = timezone;
227 return timezone;
228}
229
230
231function WeekDay(time) {
232 return Modulo(DAY(time) + 4, 7);
233}
234
Andrei Popescu31002712010-02-23 13:46:05 +0000235
236function LocalTime(time) {
237 if (NUMBER_IS_NAN(time)) return time;
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100238 // DaylightSavingsOffset called before local_time_offset used.
239 return time + DaylightSavingsOffset(time) + local_time_offset;
Andrei Popescu31002712010-02-23 13:46:05 +0000240}
241
Kristian Monsen25f61362010-05-21 11:50:48 +0100242
243var ltcache = {
Ben Murdochf87a2032010-10-22 12:50:53 +0100244 key: null,
Kristian Monsen25f61362010-05-21 11:50:48 +0100245 val: null
246};
247
Andrei Popescu31002712010-02-23 13:46:05 +0000248function LocalTimeNoCheck(time) {
Kristian Monsen25f61362010-05-21 11:50:48 +0100249 var ltc = ltcache;
250 if (%_ObjectEquals(time, ltc.key)) return ltc.val;
Steve Block6ded16b2010-05-10 14:33:55 +0100251
Andrei Popescu31002712010-02-23 13:46:05 +0000252 // Inline the DST offset cache checks for speed.
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100253 // The cache is hit, or DaylightSavingsOffset is called,
254 // before local_time_offset is used.
Andrei Popescu31002712010-02-23 13:46:05 +0000255 var cache = DST_offset_cache;
256 if (cache.start <= time && time <= cache.end) {
257 var dst_offset = cache.offset;
258 } else {
259 var dst_offset = DaylightSavingsOffset(time);
260 }
Kristian Monsen25f61362010-05-21 11:50:48 +0100261 ltc.key = time;
262 return (ltc.val = time + local_time_offset + dst_offset);
Andrei Popescu31002712010-02-23 13:46:05 +0000263}
264
265
266function UTC(time) {
267 if (NUMBER_IS_NAN(time)) return time;
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100268 // local_time_offset is needed before the call to DaylightSavingsOffset,
269 // so it may be uninitialized.
270 if (IS_UNDEFINED(local_time_offset)) {
271 local_time_offset = %DateLocalTimeOffset();
272 }
Andrei Popescu31002712010-02-23 13:46:05 +0000273 var tmp = time - local_time_offset;
274 return tmp - DaylightSavingsOffset(tmp);
275}
276
277
278// ECMA 262 - 15.9.1.11
279function MakeTime(hour, min, sec, ms) {
280 if (!$isFinite(hour)) return $NaN;
281 if (!$isFinite(min)) return $NaN;
282 if (!$isFinite(sec)) return $NaN;
283 if (!$isFinite(ms)) return $NaN;
284 return TO_INTEGER(hour) * msPerHour
285 + TO_INTEGER(min) * msPerMinute
286 + TO_INTEGER(sec) * msPerSecond
287 + TO_INTEGER(ms);
288}
289
290
291// ECMA 262 - 15.9.1.12
292function TimeInYear(year) {
293 return DaysInYear(year) * msPerDay;
294}
295
296
Steve Block6ded16b2010-05-10 14:33:55 +0100297var ymd_from_time_cache = [$NaN, $NaN, $NaN];
298var ymd_from_time_cached_time = $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000299
Steve Block6ded16b2010-05-10 14:33:55 +0100300function YearFromTime(t) {
301 if (t !== ymd_from_time_cached_time) {
302 if (!$isFinite(t)) {
303 return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000304 }
Steve Block6ded16b2010-05-10 14:33:55 +0100305
306 %DateYMDFromTime(t, ymd_from_time_cache);
307 ymd_from_time_cached_time = t
308 }
309
310 return ymd_from_time_cache[0];
311}
312
313function MonthFromTime(t) {
314 if (t !== ymd_from_time_cached_time) {
315 if (!$isFinite(t)) {
316 return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000317 }
Steve Block6ded16b2010-05-10 14:33:55 +0100318 %DateYMDFromTime(t, ymd_from_time_cache);
319 ymd_from_time_cached_time = t
Andrei Popescu31002712010-02-23 13:46:05 +0000320 }
Steve Block6ded16b2010-05-10 14:33:55 +0100321
322 return ymd_from_time_cache[1];
Andrei Popescu31002712010-02-23 13:46:05 +0000323}
324
Steve Block6ded16b2010-05-10 14:33:55 +0100325function DateFromTime(t) {
326 if (t !== ymd_from_time_cached_time) {
327 if (!$isFinite(t)) {
328 return $NaN;
329 }
Andrei Popescu31002712010-02-23 13:46:05 +0000330
Steve Block6ded16b2010-05-10 14:33:55 +0100331 %DateYMDFromTime(t, ymd_from_time_cache);
332 ymd_from_time_cached_time = t
Andrei Popescu31002712010-02-23 13:46:05 +0000333 }
Steve Block6ded16b2010-05-10 14:33:55 +0100334
335 return ymd_from_time_cache[2];
Andrei Popescu31002712010-02-23 13:46:05 +0000336}
337
338
339// Compute number of days given a year, month, date.
340// Note that month and date can lie outside the normal range.
341// For example:
342// MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
343// MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
344// MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)
345function MakeDay(year, month, date) {
346 if (!$isFinite(year) || !$isFinite(month) || !$isFinite(date)) return $NaN;
347
Steve Block8defd9f2010-07-08 12:39:36 +0100348 // Convert to integer and map -0 to 0.
349 year = TO_INTEGER_MAP_MINUS_ZERO(year);
350 month = TO_INTEGER_MAP_MINUS_ZERO(month);
351 date = TO_INTEGER_MAP_MINUS_ZERO(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000352
Steve Block6ded16b2010-05-10 14:33:55 +0100353 if (year < kMinYear || year > kMaxYear ||
354 month < kMinMonth || month > kMaxMonth ||
355 date < kMinDate || date > kMaxDate) {
356 return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000357 }
358
Steve Block6ded16b2010-05-10 14:33:55 +0100359 // Now we rely on year, month and date being SMIs.
360 return %DateMakeDay(year, month, date);
Andrei Popescu31002712010-02-23 13:46:05 +0000361}
362
363
364// ECMA 262 - 15.9.1.13
365function MakeDate(day, time) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100366 var time = day * msPerDay + time;
367 // Some of our runtime funtions for computing UTC(time) rely on
368 // times not being significantly larger than MAX_TIME_MS. If there
369 // is no way that the time can be within range even after UTC
370 // conversion we return NaN immediately instead of relying on
371 // TimeClip to do it.
372 if ($abs(time) > MAX_TIME_BEFORE_UTC) return $NaN;
373 return time;
Andrei Popescu31002712010-02-23 13:46:05 +0000374}
375
376
377// ECMA 262 - 15.9.1.14
378function TimeClip(time) {
379 if (!$isFinite(time)) return $NaN;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100380 if ($abs(time) > MAX_TIME_MS) return $NaN;
Andrei Popescu31002712010-02-23 13:46:05 +0000381 return TO_INTEGER(time);
382}
383
384
385// The Date cache is used to limit the cost of parsing the same Date
386// strings over and over again.
387var Date_cache = {
388 // Cached time value.
389 time: $NaN,
390 // Cached year when interpreting the time as a local time. Only
391 // valid when the time matches cached time.
392 year: $NaN,
393 // String input for which the cached time is valid.
394 string: null
395};
396
397
398%SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
399 if (!%_IsConstructCall()) {
400 // ECMA 262 - 15.9.2
401 return (new $Date()).toString();
402 }
403
404 // ECMA 262 - 15.9.3
405 var argc = %_ArgumentsLength();
406 var value;
407 if (argc == 0) {
408 value = %DateCurrentTime();
409
410 } else if (argc == 1) {
411 if (IS_NUMBER(year)) {
412 value = TimeClip(year);
413
414 } else if (IS_STRING(year)) {
415 // Probe the Date cache. If we already have a time value for the
416 // given time, we re-use that instead of parsing the string again.
417 var cache = Date_cache;
418 if (cache.string === year) {
419 value = cache.time;
420 } else {
421 value = DateParse(year);
422 if (!NUMBER_IS_NAN(value)) {
423 cache.time = value;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100424 cache.year = YearFromTime(LocalTimeNoCheck(value));
Andrei Popescu31002712010-02-23 13:46:05 +0000425 cache.string = year;
426 }
427 }
428
429 } else {
430 // According to ECMA 262, no hint should be given for this
431 // conversion. However, ToPrimitive defaults to STRING_HINT for
432 // Date objects which will lose precision when the Date
433 // constructor is called with another Date object as its
434 // argument. We therefore use NUMBER_HINT for the conversion,
435 // which is the default for everything else than Date objects.
436 // This makes us behave like KJS and SpiderMonkey.
437 var time = ToPrimitive(year, NUMBER_HINT);
438 value = IS_STRING(time) ? DateParse(time) : TimeClip(ToNumber(time));
439 }
440
441 } else {
442 year = ToNumber(year);
443 month = ToNumber(month);
444 date = argc > 2 ? ToNumber(date) : 1;
445 hours = argc > 3 ? ToNumber(hours) : 0;
446 minutes = argc > 4 ? ToNumber(minutes) : 0;
447 seconds = argc > 5 ? ToNumber(seconds) : 0;
448 ms = argc > 6 ? ToNumber(ms) : 0;
449 year = (!NUMBER_IS_NAN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
450 ? 1900 + TO_INTEGER(year) : year;
451 var day = MakeDay(year, month, date);
452 var time = MakeTime(hours, minutes, seconds, ms);
453 value = TimeClip(UTC(MakeDate(day, time)));
454 }
455 %_SetValueOf(this, value);
456});
457
458
Andrei Popescu31002712010-02-23 13:46:05 +0000459%FunctionSetPrototype($Date, new $Date($NaN));
460
461
462var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
463var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
464
465
466function TwoDigitString(value) {
467 return value < 10 ? "0" + value : "" + value;
468}
469
470
471function DateString(time) {
Andrei Popescu31002712010-02-23 13:46:05 +0000472 return WeekDays[WeekDay(time)] + ' '
Steve Block6ded16b2010-05-10 14:33:55 +0100473 + Months[MonthFromTime(time)] + ' '
474 + TwoDigitString(DateFromTime(time)) + ' '
475 + YearFromTime(time);
Andrei Popescu31002712010-02-23 13:46:05 +0000476}
477
478
479var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
480var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
481
482
483function LongDateString(time) {
Andrei Popescu31002712010-02-23 13:46:05 +0000484 return LongWeekDays[WeekDay(time)] + ', '
Steve Block6ded16b2010-05-10 14:33:55 +0100485 + LongMonths[MonthFromTime(time)] + ' '
486 + TwoDigitString(DateFromTime(time)) + ', '
487 + YearFromTime(time);
Andrei Popescu31002712010-02-23 13:46:05 +0000488}
489
490
491function TimeString(time) {
492 return TwoDigitString(HOUR_FROM_TIME(time)) + ':'
493 + TwoDigitString(MIN_FROM_TIME(time)) + ':'
494 + TwoDigitString(SEC_FROM_TIME(time));
495}
496
497
498function LocalTimezoneString(time) {
Ben Murdochd69d2e32010-03-30 12:55:27 +0100499 var old_timezone = timezone_cache_timezone;
500 var timezone = LocalTimezone(time);
501 if (old_timezone && timezone != old_timezone) {
502 // If the timezone string has changed from the one that we cached,
503 // the local time offset may now be wrong. So we need to update it
504 // and try again.
505 local_time_offset = %DateLocalTimeOffset();
506 // We also need to invalidate the DST cache as the new timezone may have
507 // different DST times.
508 var dst_cache = DST_offset_cache;
509 dst_cache.start = 0;
510 dst_cache.end = -1;
511 }
512
Andrei Popescu31002712010-02-23 13:46:05 +0000513 var timezoneOffset =
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100514 (DaylightSavingsOffset(time) + local_time_offset) / msPerMinute;
Andrei Popescu31002712010-02-23 13:46:05 +0000515 var sign = (timezoneOffset >= 0) ? 1 : -1;
516 var hours = FLOOR((sign * timezoneOffset)/60);
517 var min = FLOOR((sign * timezoneOffset)%60);
518 var gmt = ' GMT' + ((sign == 1) ? '+' : '-') +
519 TwoDigitString(hours) + TwoDigitString(min);
Ben Murdochd69d2e32010-03-30 12:55:27 +0100520 return gmt + ' (' + timezone + ')';
Andrei Popescu31002712010-02-23 13:46:05 +0000521}
522
523
524function DatePrintString(time) {
525 return DateString(time) + ' ' + TimeString(time);
526}
527
528// -------------------------------------------------------------------
529
530// Reused output buffer. Used when parsing date strings.
Steve Block6ded16b2010-05-10 14:33:55 +0100531var parse_buffer = $Array(8);
Andrei Popescu31002712010-02-23 13:46:05 +0000532
533// ECMA 262 - 15.9.4.2
534function DateParse(string) {
535 var arr = %DateParseString(ToString(string), parse_buffer);
536 if (IS_NULL(arr)) return $NaN;
537
538 var day = MakeDay(arr[0], arr[1], arr[2]);
Steve Block6ded16b2010-05-10 14:33:55 +0100539 var time = MakeTime(arr[3], arr[4], arr[5], arr[6]);
Andrei Popescu31002712010-02-23 13:46:05 +0000540 var date = MakeDate(day, time);
541
Steve Block6ded16b2010-05-10 14:33:55 +0100542 if (IS_NULL(arr[7])) {
Andrei Popescu31002712010-02-23 13:46:05 +0000543 return TimeClip(UTC(date));
544 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100545 return TimeClip(date - arr[7] * 1000);
Andrei Popescu31002712010-02-23 13:46:05 +0000546 }
547}
548
549
550// ECMA 262 - 15.9.4.3
551function DateUTC(year, month, date, hours, minutes, seconds, ms) {
552 year = ToNumber(year);
553 month = ToNumber(month);
554 var argc = %_ArgumentsLength();
555 date = argc > 2 ? ToNumber(date) : 1;
556 hours = argc > 3 ? ToNumber(hours) : 0;
557 minutes = argc > 4 ? ToNumber(minutes) : 0;
558 seconds = argc > 5 ? ToNumber(seconds) : 0;
559 ms = argc > 6 ? ToNumber(ms) : 0;
560 year = (!NUMBER_IS_NAN(year) && 0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
561 ? 1900 + TO_INTEGER(year) : year;
562 var day = MakeDay(year, month, date);
563 var time = MakeTime(hours, minutes, seconds, ms);
564 return %_SetValueOf(this, TimeClip(MakeDate(day, time)));
565}
566
567
568// Mozilla-specific extension. Returns the number of milliseconds
569// elapsed since 1 January 1970 00:00:00 UTC.
570function DateNow() {
571 return %DateCurrentTime();
572}
573
574
575// ECMA 262 - 15.9.5.2
576function DateToString() {
577 var t = DATE_VALUE(this);
578 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100579 var time_zone_string = LocalTimezoneString(t); // May update local offset.
580 return DatePrintString(LocalTimeNoCheck(t)) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000581}
582
583
584// ECMA 262 - 15.9.5.3
585function DateToDateString() {
586 var t = DATE_VALUE(this);
587 if (NUMBER_IS_NAN(t)) return kInvalidDate;
588 return DateString(LocalTimeNoCheck(t));
589}
590
591
592// ECMA 262 - 15.9.5.4
593function DateToTimeString() {
594 var t = DATE_VALUE(this);
595 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Andrei Popescu6599b9d2010-04-28 13:01:47 +0100596 var time_zone_string = LocalTimezoneString(t); // May update local offset.
597 return TimeString(LocalTimeNoCheck(t)) + time_zone_string;
Andrei Popescu31002712010-02-23 13:46:05 +0000598}
599
600
601// ECMA 262 - 15.9.5.5
602function DateToLocaleString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100603 return %_CallFunction(this, DateToString);
Andrei Popescu31002712010-02-23 13:46:05 +0000604}
605
606
607// ECMA 262 - 15.9.5.6
608function DateToLocaleDateString() {
609 var t = DATE_VALUE(this);
610 if (NUMBER_IS_NAN(t)) return kInvalidDate;
611 return LongDateString(LocalTimeNoCheck(t));
612}
613
614
615// ECMA 262 - 15.9.5.7
616function DateToLocaleTimeString() {
617 var t = DATE_VALUE(this);
618 if (NUMBER_IS_NAN(t)) return kInvalidDate;
619 var lt = LocalTimeNoCheck(t);
620 return TimeString(lt);
621}
622
623
624// ECMA 262 - 15.9.5.8
625function DateValueOf() {
626 return DATE_VALUE(this);
627}
628
629
630// ECMA 262 - 15.9.5.9
Andrei Popescu402d9372010-02-26 13:31:12 +0000631function DateGetTime() {
Andrei Popescu31002712010-02-23 13:46:05 +0000632 return DATE_VALUE(this);
633}
634
635
636// ECMA 262 - 15.9.5.10
637function DateGetFullYear() {
Leon Clarkeac952652010-07-15 11:15:24 +0100638 var t = DATE_VALUE(this);
639 if (NUMBER_IS_NAN(t)) return t;
640 var cache = Date_cache;
641 if (cache.time === t) return cache.year;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100642 return YearFromTime(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000643}
644
645
646// ECMA 262 - 15.9.5.11
647function DateGetUTCFullYear() {
Leon Clarkeac952652010-07-15 11:15:24 +0100648 var t = DATE_VALUE(this);
649 if (NUMBER_IS_NAN(t)) return t;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100650 return YearFromTime(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000651}
652
653
654// ECMA 262 - 15.9.5.12
655function DateGetMonth() {
Leon Clarkeac952652010-07-15 11:15:24 +0100656 var t = DATE_VALUE(this);
657 if (NUMBER_IS_NAN(t)) return t;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100658 return MonthFromTime(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000659}
660
661
662// ECMA 262 - 15.9.5.13
663function DateGetUTCMonth() {
Leon Clarkeac952652010-07-15 11:15:24 +0100664 var t = DATE_VALUE(this);
665 if (NUMBER_IS_NAN(t)) return t;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100666 return MonthFromTime(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000667}
668
669
670// ECMA 262 - 15.9.5.14
671function DateGetDate() {
Leon Clarkeac952652010-07-15 11:15:24 +0100672 var t = DATE_VALUE(this);
673 if (NUMBER_IS_NAN(t)) return t;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 return DateFromTime(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000675}
676
677
678// ECMA 262 - 15.9.5.15
679function DateGetUTCDate() {
Leon Clarkeac952652010-07-15 11:15:24 +0100680 var t = DATE_VALUE(this);
681 return NAN_OR_DATE_FROM_TIME(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000682}
683
684
685// ECMA 262 - 15.9.5.16
686function DateGetDay() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000687 var t = DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000688 if (NUMBER_IS_NAN(t)) return t;
689 return WeekDay(LocalTimeNoCheck(t));
690}
691
692
693// ECMA 262 - 15.9.5.17
694function DateGetUTCDay() {
Ben Murdoch257744e2011-11-30 15:57:28 +0000695 var t = DATE_VALUE(this);
Andrei Popescu31002712010-02-23 13:46:05 +0000696 if (NUMBER_IS_NAN(t)) return t;
697 return WeekDay(t);
698}
699
700
701// ECMA 262 - 15.9.5.18
702function DateGetHours() {
Leon Clarkeac952652010-07-15 11:15:24 +0100703 var t = DATE_VALUE(this);
704 if (NUMBER_IS_NAN(t)) return t;
705 return HOUR_FROM_TIME(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000706}
707
708
709// ECMA 262 - 15.9.5.19
710function DateGetUTCHours() {
Leon Clarkeac952652010-07-15 11:15:24 +0100711 var t = DATE_VALUE(this);
712 if (NUMBER_IS_NAN(t)) return t;
713 return HOUR_FROM_TIME(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000714}
715
716
717// ECMA 262 - 15.9.5.20
718function DateGetMinutes() {
Leon Clarkeac952652010-07-15 11:15:24 +0100719 var t = DATE_VALUE(this);
720 if (NUMBER_IS_NAN(t)) return t;
721 return MIN_FROM_TIME(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000722}
723
724
725// ECMA 262 - 15.9.5.21
726function DateGetUTCMinutes() {
Leon Clarkeac952652010-07-15 11:15:24 +0100727 var t = DATE_VALUE(this);
728 return NAN_OR_MIN_FROM_TIME(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000729}
730
731
732// ECMA 262 - 15.9.5.22
733function DateGetSeconds() {
Leon Clarkeac952652010-07-15 11:15:24 +0100734 var t = DATE_VALUE(this);
735 if (NUMBER_IS_NAN(t)) return t;
736 return SEC_FROM_TIME(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000737}
738
739
740// ECMA 262 - 15.9.5.23
741function DateGetUTCSeconds() {
Leon Clarkeac952652010-07-15 11:15:24 +0100742 var t = DATE_VALUE(this);
743 return NAN_OR_SEC_FROM_TIME(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000744}
745
746
747// ECMA 262 - 15.9.5.24
748function DateGetMilliseconds() {
Leon Clarkeac952652010-07-15 11:15:24 +0100749 var t = DATE_VALUE(this);
750 if (NUMBER_IS_NAN(t)) return t;
751 return MS_FROM_TIME(LocalTimeNoCheck(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000752}
753
754
755// ECMA 262 - 15.9.5.25
756function DateGetUTCMilliseconds() {
Leon Clarkeac952652010-07-15 11:15:24 +0100757 var t = DATE_VALUE(this);
758 return NAN_OR_MS_FROM_TIME(t);
Andrei Popescu31002712010-02-23 13:46:05 +0000759}
760
761
762// ECMA 262 - 15.9.5.26
763function DateGetTimezoneOffset() {
764 var t = DATE_VALUE(this);
765 if (NUMBER_IS_NAN(t)) return t;
766 return (t - LocalTimeNoCheck(t)) / msPerMinute;
767}
768
769
770// ECMA 262 - 15.9.5.27
771function DateSetTime(ms) {
772 if (!IS_DATE(this)) ThrowDateTypeError();
773 return %_SetValueOf(this, TimeClip(ToNumber(ms)));
774}
775
776
777// ECMA 262 - 15.9.5.28
778function DateSetMilliseconds(ms) {
779 var t = LocalTime(DATE_VALUE(this));
780 ms = ToNumber(ms);
781 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), SEC_FROM_TIME(t), ms);
782 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time))));
783}
784
785
786// ECMA 262 - 15.9.5.29
787function DateSetUTCMilliseconds(ms) {
788 var t = DATE_VALUE(this);
789 ms = ToNumber(ms);
790 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), SEC_FROM_TIME(t), ms);
791 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time)));
792}
793
794
795// ECMA 262 - 15.9.5.30
796function DateSetSeconds(sec, ms) {
797 var t = LocalTime(DATE_VALUE(this));
798 sec = ToNumber(sec);
Leon Clarkeac952652010-07-15 11:15:24 +0100799 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000800 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms);
801 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time))));
802}
803
804
805// ECMA 262 - 15.9.5.31
806function DateSetUTCSeconds(sec, ms) {
807 var t = DATE_VALUE(this);
808 sec = ToNumber(sec);
Leon Clarkeac952652010-07-15 11:15:24 +0100809 ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000810 var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms);
811 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time)));
812}
813
814
815// ECMA 262 - 15.9.5.33
816function DateSetMinutes(min, sec, ms) {
817 var t = LocalTime(DATE_VALUE(this));
818 min = ToNumber(min);
819 var argc = %_ArgumentsLength();
Leon Clarkeac952652010-07-15 11:15:24 +0100820 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
821 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000822 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms);
823 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time))));
824}
825
826
827// ECMA 262 - 15.9.5.34
828function DateSetUTCMinutes(min, sec, ms) {
829 var t = DATE_VALUE(this);
830 min = ToNumber(min);
831 var argc = %_ArgumentsLength();
Leon Clarkeac952652010-07-15 11:15:24 +0100832 sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
833 ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000834 var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms);
835 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time)));
836}
837
838
839// ECMA 262 - 15.9.5.35
840function DateSetHours(hour, min, sec, ms) {
841 var t = LocalTime(DATE_VALUE(this));
842 hour = ToNumber(hour);
843 var argc = %_ArgumentsLength();
Leon Clarkeac952652010-07-15 11:15:24 +0100844 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min);
845 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
846 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000847 var time = MakeTime(hour, min, sec, ms);
848 return %_SetValueOf(this, TimeClip(UTC(MakeDate(DAY(t), time))));
849}
850
851
852// ECMA 262 - 15.9.5.34
853function DateSetUTCHours(hour, min, sec, ms) {
854 var t = DATE_VALUE(this);
855 hour = ToNumber(hour);
856 var argc = %_ArgumentsLength();
Leon Clarkeac952652010-07-15 11:15:24 +0100857 min = argc < 2 ? NAN_OR_MIN_FROM_TIME(t) : ToNumber(min);
858 sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
859 ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
Andrei Popescu31002712010-02-23 13:46:05 +0000860 var time = MakeTime(hour, min, sec, ms);
861 return %_SetValueOf(this, TimeClip(MakeDate(DAY(t), time)));
862}
863
864
865// ECMA 262 - 15.9.5.36
866function DateSetDate(date) {
867 var t = LocalTime(DATE_VALUE(this));
868 date = ToNumber(date);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100869 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
Andrei Popescu31002712010-02-23 13:46:05 +0000870 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
871}
872
873
874// ECMA 262 - 15.9.5.37
875function DateSetUTCDate(date) {
876 var t = DATE_VALUE(this);
877 date = ToNumber(date);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100878 var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
Andrei Popescu31002712010-02-23 13:46:05 +0000879 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
880}
881
882
883// ECMA 262 - 15.9.5.38
884function DateSetMonth(month, date) {
885 var t = LocalTime(DATE_VALUE(this));
886 month = ToNumber(month);
Leon Clarkeac952652010-07-15 11:15:24 +0100887 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100888 var day = MakeDay(YearFromTime(t), month, date);
Andrei Popescu31002712010-02-23 13:46:05 +0000889 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
890}
891
892
893// ECMA 262 - 15.9.5.39
894function DateSetUTCMonth(month, date) {
895 var t = DATE_VALUE(this);
896 month = ToNumber(month);
Leon Clarkeac952652010-07-15 11:15:24 +0100897 date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100898 var day = MakeDay(YearFromTime(t), month, date);
Andrei Popescu31002712010-02-23 13:46:05 +0000899 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
900}
901
902
903// ECMA 262 - 15.9.5.40
904function DateSetFullYear(year, month, date) {
905 var t = DATE_VALUE(this);
906 t = NUMBER_IS_NAN(t) ? 0 : LocalTimeNoCheck(t);
907 year = ToNumber(year);
908 var argc = %_ArgumentsLength();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100909 month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
910 date = argc < 3 ? DateFromTime(t) : ToNumber(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000911 var day = MakeDay(year, month, date);
912 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
913}
914
915
916// ECMA 262 - 15.9.5.41
917function DateSetUTCFullYear(year, month, date) {
918 var t = DATE_VALUE(this);
919 if (NUMBER_IS_NAN(t)) t = 0;
920 var argc = %_ArgumentsLength();
921 year = ToNumber(year);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100922 month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
923 date = argc < 3 ? DateFromTime(t) : ToNumber(date);
Andrei Popescu31002712010-02-23 13:46:05 +0000924 var day = MakeDay(year, month, date);
925 return %_SetValueOf(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
926}
927
928
929// ECMA 262 - 15.9.5.42
930function DateToUTCString() {
931 var t = DATE_VALUE(this);
932 if (NUMBER_IS_NAN(t)) return kInvalidDate;
933 // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
934 return WeekDays[WeekDay(t)] + ', '
Ben Murdochb0fe1622011-05-05 13:52:32 +0100935 + TwoDigitString(DateFromTime(t)) + ' '
936 + Months[MonthFromTime(t)] + ' '
937 + YearFromTime(t) + ' '
Andrei Popescu31002712010-02-23 13:46:05 +0000938 + TimeString(t) + ' GMT';
939}
940
941
942// ECMA 262 - B.2.4
943function DateGetYear() {
944 var t = DATE_VALUE(this);
945 if (NUMBER_IS_NAN(t)) return $NaN;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100946 return YearFromTime(LocalTimeNoCheck(t)) - 1900;
Andrei Popescu31002712010-02-23 13:46:05 +0000947}
948
949
950// ECMA 262 - B.2.5
951function DateSetYear(year) {
952 var t = LocalTime(DATE_VALUE(this));
953 if (NUMBER_IS_NAN(t)) t = 0;
954 year = ToNumber(year);
955 if (NUMBER_IS_NAN(year)) return %_SetValueOf(this, $NaN);
956 year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
957 ? 1900 + TO_INTEGER(year) : year;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100958 var day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
Andrei Popescu31002712010-02-23 13:46:05 +0000959 return %_SetValueOf(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
960}
961
962
963// ECMA 262 - B.2.6
964//
965// Notice that this does not follow ECMA 262 completely. ECMA 262
966// says that toGMTString should be the same Function object as
967// toUTCString. JSC does not do this, so for compatibility we do not
968// do that either. Instead, we create a new function whose name
969// property will return toGMTString.
970function DateToGMTString() {
Steve Block1e0659c2011-05-24 12:43:12 +0100971 return %_CallFunction(this, DateToUTCString);
Andrei Popescu31002712010-02-23 13:46:05 +0000972}
973
974
975function PadInt(n, digits) {
976 if (digits == 1) return n;
977 return n < MathPow(10, digits - 1) ? '0' + PadInt(n, digits - 1) : n;
978}
979
980
981function DateToISOString() {
982 var t = DATE_VALUE(this);
983 if (NUMBER_IS_NAN(t)) return kInvalidDate;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000984 var year = this.getUTCFullYear();
985 var year_string;
986 if (year >= 0 && year <= 9999) {
987 year_string = PadInt(year, 4);
988 } else {
989 if (year < 0) {
990 year_string = "-" + PadInt(-year, 6);
991 } else {
992 year_string = "+" + PadInt(year, 6);
993 }
994 }
995 return year_string +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100996 '-' + PadInt(this.getUTCMonth() + 1, 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000997 '-' + PadInt(this.getUTCDate(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +0100998 'T' + PadInt(this.getUTCHours(), 2) +
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000999 ':' + PadInt(this.getUTCMinutes(), 2) +
Ben Murdochb0fe1622011-05-05 13:52:32 +01001000 ':' + PadInt(this.getUTCSeconds(), 2) +
Andrei Popescu31002712010-02-23 13:46:05 +00001001 '.' + PadInt(this.getUTCMilliseconds(), 3) +
1002 'Z';
1003}
1004
1005
1006function DateToJSON(key) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001007 var o = ToObject(this);
1008 var tv = DefaultNumber(o);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001009 if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
1010 return null;
Ben Murdochb0fe1622011-05-05 13:52:32 +01001011 }
1012 return o.toISOString();
1013}
1014
1015
1016function ResetDateCache() {
1017
1018 // Reset the local_time_offset:
1019 local_time_offset = %DateLocalTimeOffset();
1020
1021 // Reset the DST offset cache:
1022 var cache = DST_offset_cache;
1023 cache.offset = 0;
1024 cache.start = 0;
1025 cache.end = -1;
1026 cache.increment = 0;
1027 cache.initial_increment = 19 * msPerDay;
1028
1029 // Reset the timezone cache:
1030 timezone_cache_time = $NaN;
1031 timezone_cache_timezone = undefined;
1032
1033 // Reset the ltcache:
1034 ltcache.key = null;
1035 ltcache.val = null;
1036
1037 // Reset the ymd_from_time_cache:
1038 ymd_from_time_cache = [$NaN, $NaN, $NaN];
1039 ymd_from_time_cached_time = $NaN;
1040
1041 // Reset the date cache:
1042 cache = Date_cache;
1043 cache.time = $NaN;
1044 cache.year = $NaN;
1045 cache.string = null;
Andrei Popescu31002712010-02-23 13:46:05 +00001046}
1047
1048
1049// -------------------------------------------------------------------
1050
1051function SetupDate() {
1052 // Setup non-enumerable properties of the Date object itself.
1053 InstallFunctions($Date, DONT_ENUM, $Array(
1054 "UTC", DateUTC,
1055 "parse", DateParse,
1056 "now", DateNow
1057 ));
1058
1059 // Setup non-enumerable constructor property of the Date prototype object.
1060 %SetProperty($Date.prototype, "constructor", $Date, DONT_ENUM);
1061
1062 // Setup non-enumerable functions of the Date prototype object and
1063 // set their names.
1064 InstallFunctionsOnHiddenPrototype($Date.prototype, DONT_ENUM, $Array(
1065 "toString", DateToString,
1066 "toDateString", DateToDateString,
1067 "toTimeString", DateToTimeString,
1068 "toLocaleString", DateToLocaleString,
1069 "toLocaleDateString", DateToLocaleDateString,
1070 "toLocaleTimeString", DateToLocaleTimeString,
1071 "valueOf", DateValueOf,
1072 "getTime", DateGetTime,
1073 "getFullYear", DateGetFullYear,
1074 "getUTCFullYear", DateGetUTCFullYear,
1075 "getMonth", DateGetMonth,
1076 "getUTCMonth", DateGetUTCMonth,
1077 "getDate", DateGetDate,
1078 "getUTCDate", DateGetUTCDate,
1079 "getDay", DateGetDay,
1080 "getUTCDay", DateGetUTCDay,
1081 "getHours", DateGetHours,
1082 "getUTCHours", DateGetUTCHours,
1083 "getMinutes", DateGetMinutes,
1084 "getUTCMinutes", DateGetUTCMinutes,
1085 "getSeconds", DateGetSeconds,
1086 "getUTCSeconds", DateGetUTCSeconds,
1087 "getMilliseconds", DateGetMilliseconds,
1088 "getUTCMilliseconds", DateGetUTCMilliseconds,
1089 "getTimezoneOffset", DateGetTimezoneOffset,
1090 "setTime", DateSetTime,
1091 "setMilliseconds", DateSetMilliseconds,
1092 "setUTCMilliseconds", DateSetUTCMilliseconds,
1093 "setSeconds", DateSetSeconds,
1094 "setUTCSeconds", DateSetUTCSeconds,
1095 "setMinutes", DateSetMinutes,
1096 "setUTCMinutes", DateSetUTCMinutes,
1097 "setHours", DateSetHours,
1098 "setUTCHours", DateSetUTCHours,
1099 "setDate", DateSetDate,
1100 "setUTCDate", DateSetUTCDate,
1101 "setMonth", DateSetMonth,
1102 "setUTCMonth", DateSetUTCMonth,
1103 "setFullYear", DateSetFullYear,
1104 "setUTCFullYear", DateSetUTCFullYear,
1105 "toGMTString", DateToGMTString,
1106 "toUTCString", DateToUTCString,
1107 "getYear", DateGetYear,
1108 "setYear", DateSetYear,
1109 "toISOString", DateToISOString,
1110 "toJSON", DateToJSON
1111 ));
1112}
1113
1114SetupDate();