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. 40var $Date = global.Date; 41 42// Helper function to throw error. 43function ThrowDateTypeError() { 44 throw new $TypeError('this is not a Date object.'); 45} 46 47 48var timezone_cache_time = $NaN; 49var timezone_cache_timezone; 50 51function 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 63function 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 72function 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 85function 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) 96function 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 115function 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 128function 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. 137var 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 208var WeekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; 209var Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 210 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 211 212 213function TwoDigitString(value) { 214 return value < 10 ? "0" + value : "" + value; 215} 216 217 218function 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 226var LongWeekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 227 'Thursday', 'Friday', 'Saturday']; 228var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June', 229 'July', 'August', 'September', 'October', 'November', 'December']; 230 231 232function 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 240function TimeString(date) { 241 return TwoDigitString(LOCAL_HOUR(date)) + ':' 242 + TwoDigitString(LOCAL_MIN(date)) + ':' 243 + TwoDigitString(LOCAL_SEC(date)); 244} 245 246 247function TimeStringUTC(date) { 248 return TwoDigitString(UTC_HOUR(date)) + ':' 249 + TwoDigitString(UTC_MIN(date)) + ':' 250 + TwoDigitString(UTC_SEC(date)); 251} 252 253 254function 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 267function DatePrintString(date) { 268 return DateString(date) + ' ' + TimeString(date); 269} 270 271// ------------------------------------------------------------------- 272 273// Reused output buffer. Used when parsing date strings. 274var parse_buffer = $Array(8); 275 276// ECMA 262 - 15.9.4.2 277function 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 294function 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. 314function DateNow() { 315 return %DateCurrentTime(); 316} 317 318 319// ECMA 262 - 15.9.5.2 320function 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 330function 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 339function 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 349function DateToLocaleString() { 350 return %_CallFunction(this, DateToString); 351} 352 353 354// ECMA 262 - 15.9.5.6 355function 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 364function 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 373function DateValueOf() { 374 CHECK_DATE(this); 375 return UTC_DATE_VALUE(this); 376} 377 378 379// ECMA 262 - 15.9.5.9 380function DateGetTime() { 381 CHECK_DATE(this); 382 return UTC_DATE_VALUE(this); 383} 384 385 386// ECMA 262 - 15.9.5.10 387function DateGetFullYear() { 388 CHECK_DATE(this); 389 return LOCAL_YEAR(this); 390} 391 392 393// ECMA 262 - 15.9.5.11 394function DateGetUTCFullYear() { 395 CHECK_DATE(this); 396 return UTC_YEAR(this); 397} 398 399 400// ECMA 262 - 15.9.5.12 401function DateGetMonth() { 402 CHECK_DATE(this); 403 return LOCAL_MONTH(this); 404} 405 406 407// ECMA 262 - 15.9.5.13 408function DateGetUTCMonth() { 409 CHECK_DATE(this); 410 return UTC_MONTH(this); 411} 412 413 414// ECMA 262 - 15.9.5.14 415function DateGetDate() { 416 CHECK_DATE(this); 417 return LOCAL_DAY(this); 418} 419 420 421// ECMA 262 - 15.9.5.15 422function DateGetUTCDate() { 423 CHECK_DATE(this); 424 return UTC_DAY(this); 425} 426 427 428// ECMA 262 - 15.9.5.16 429function DateGetDay() { 430 CHECK_DATE(this); 431 return LOCAL_WEEKDAY(this); 432} 433 434 435// ECMA 262 - 15.9.5.17 436function DateGetUTCDay() { 437 CHECK_DATE(this); 438 return UTC_WEEKDAY(this); 439} 440 441 442// ECMA 262 - 15.9.5.18 443function DateGetHours() { 444 CHECK_DATE(this); 445 return LOCAL_HOUR(this); 446} 447 448 449// ECMA 262 - 15.9.5.19 450function DateGetUTCHours() { 451 CHECK_DATE(this); 452 return UTC_HOUR(this); 453} 454 455 456// ECMA 262 - 15.9.5.20 457function DateGetMinutes() { 458 CHECK_DATE(this); 459 return LOCAL_MIN(this); 460} 461 462 463// ECMA 262 - 15.9.5.21 464function DateGetUTCMinutes() { 465 CHECK_DATE(this); 466 return UTC_MIN(this); 467} 468 469 470// ECMA 262 - 15.9.5.22 471function DateGetSeconds() { 472 CHECK_DATE(this); 473 return LOCAL_SEC(this); 474} 475 476 477// ECMA 262 - 15.9.5.23 478function DateGetUTCSeconds() { 479 CHECK_DATE(this); 480 return UTC_SEC(this) 481} 482 483 484// ECMA 262 - 15.9.5.24 485function DateGetMilliseconds() { 486 CHECK_DATE(this); 487 return LOCAL_MS(this); 488} 489 490 491// ECMA 262 - 15.9.5.25 492function DateGetUTCMilliseconds() { 493 CHECK_DATE(this); 494 return UTC_MS(this); 495} 496 497 498// ECMA 262 - 15.9.5.26 499function DateGetTimezoneOffset() { 500 CHECK_DATE(this); 501 return TIMEZONE_OFFSET(this); 502} 503 504 505// ECMA 262 - 15.9.5.27 506function 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 514function 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 524function 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 537function 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 548function 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 559function 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 572function 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 585function 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 599function 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 613function 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 623function 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 633function 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 644function 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 655function 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 676function 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 697function 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 711function DateGetYear() { 712 CHECK_DATE(this); 713 return LOCAL_YEAR(this) - 1900; 714} 715 716 717// ECMA 262 - B.2.5 718function 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. 747function DateToGMTString() { 748 return %_CallFunction(this, DateToUTCString); 749} 750 751 752function 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 759function 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 785function 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 795function 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 809function 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 873SetUpDate(); 874