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