1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 package org.mozilla.javascript; 8 9 import java.util.Date; 10 import java.text.DateFormat; 11 import java.text.SimpleDateFormat; 12 13 import java.util.TimeZone; 14 import java.util.SimpleTimeZone; 15 16 /** 17 * This class implements the Date native object. 18 * See ECMA 15.9. 19 * @author Mike McCabe 20 */ 21 final class NativeDate extends IdScriptableObject 22 { 23 static final long serialVersionUID = -8307438915861678966L; 24 25 private static final Object DATE_TAG = "Date"; 26 27 private static final String js_NaN_date_str = "Invalid Date"; 28 29 private static final DateFormat isoFormat; 30 static { 31 isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); isoFormat.setTimeZone(new SimpleTimeZone(0, R))32 isoFormat.setTimeZone(new SimpleTimeZone(0, "UTC")); 33 isoFormat.setLenient(false); 34 } 35 init(Scriptable scope, boolean sealed)36 static void init(Scriptable scope, boolean sealed) 37 { 38 NativeDate obj = new NativeDate(); 39 // Set the value of the prototype Date to NaN ('invalid date'); 40 obj.date = ScriptRuntime.NaN; 41 obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); 42 } 43 NativeDate()44 private NativeDate() 45 { 46 if (thisTimeZone == null) { 47 // j.u.TimeZone is synchronized, so setting class statics from it 48 // should be OK. 49 thisTimeZone = TimeZone.getDefault(); 50 LocalTZA = thisTimeZone.getRawOffset(); 51 } 52 } 53 54 @Override getClassName()55 public String getClassName() 56 { 57 return "Date"; 58 } 59 60 @Override getDefaultValue(Class<?> typeHint)61 public Object getDefaultValue(Class<?> typeHint) 62 { 63 if (typeHint == null) 64 typeHint = ScriptRuntime.StringClass; 65 return super.getDefaultValue(typeHint); 66 } 67 getJSTimeValue()68 double getJSTimeValue() 69 { 70 return date; 71 } 72 73 @Override fillConstructorProperties(IdFunctionObject ctor)74 protected void fillConstructorProperties(IdFunctionObject ctor) 75 { 76 addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_now, 77 "now", 0); 78 addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_parse, 79 "parse", 1); 80 addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_UTC, 81 "UTC", 1); 82 super.fillConstructorProperties(ctor); 83 } 84 85 @Override initPrototypeId(int id)86 protected void initPrototypeId(int id) 87 { 88 String s; 89 int arity; 90 switch (id) { 91 case Id_constructor: arity=1; s="constructor"; break; 92 case Id_toString: arity=0; s="toString"; break; 93 case Id_toTimeString: arity=0; s="toTimeString"; break; 94 case Id_toDateString: arity=0; s="toDateString"; break; 95 case Id_toLocaleString: arity=0; s="toLocaleString"; break; 96 case Id_toLocaleTimeString: arity=0; s="toLocaleTimeString"; break; 97 case Id_toLocaleDateString: arity=0; s="toLocaleDateString"; break; 98 case Id_toUTCString: arity=0; s="toUTCString"; break; 99 case Id_toSource: arity=0; s="toSource"; break; 100 case Id_valueOf: arity=0; s="valueOf"; break; 101 case Id_getTime: arity=0; s="getTime"; break; 102 case Id_getYear: arity=0; s="getYear"; break; 103 case Id_getFullYear: arity=0; s="getFullYear"; break; 104 case Id_getUTCFullYear: arity=0; s="getUTCFullYear"; break; 105 case Id_getMonth: arity=0; s="getMonth"; break; 106 case Id_getUTCMonth: arity=0; s="getUTCMonth"; break; 107 case Id_getDate: arity=0; s="getDate"; break; 108 case Id_getUTCDate: arity=0; s="getUTCDate"; break; 109 case Id_getDay: arity=0; s="getDay"; break; 110 case Id_getUTCDay: arity=0; s="getUTCDay"; break; 111 case Id_getHours: arity=0; s="getHours"; break; 112 case Id_getUTCHours: arity=0; s="getUTCHours"; break; 113 case Id_getMinutes: arity=0; s="getMinutes"; break; 114 case Id_getUTCMinutes: arity=0; s="getUTCMinutes"; break; 115 case Id_getSeconds: arity=0; s="getSeconds"; break; 116 case Id_getUTCSeconds: arity=0; s="getUTCSeconds"; break; 117 case Id_getMilliseconds: arity=0; s="getMilliseconds"; break; 118 case Id_getUTCMilliseconds: arity=0; s="getUTCMilliseconds"; break; 119 case Id_getTimezoneOffset: arity=0; s="getTimezoneOffset"; break; 120 case Id_setTime: arity=1; s="setTime"; break; 121 case Id_setMilliseconds: arity=1; s="setMilliseconds"; break; 122 case Id_setUTCMilliseconds: arity=1; s="setUTCMilliseconds"; break; 123 case Id_setSeconds: arity=2; s="setSeconds"; break; 124 case Id_setUTCSeconds: arity=2; s="setUTCSeconds"; break; 125 case Id_setMinutes: arity=3; s="setMinutes"; break; 126 case Id_setUTCMinutes: arity=3; s="setUTCMinutes"; break; 127 case Id_setHours: arity=4; s="setHours"; break; 128 case Id_setUTCHours: arity=4; s="setUTCHours"; break; 129 case Id_setDate: arity=1; s="setDate"; break; 130 case Id_setUTCDate: arity=1; s="setUTCDate"; break; 131 case Id_setMonth: arity=2; s="setMonth"; break; 132 case Id_setUTCMonth: arity=2; s="setUTCMonth"; break; 133 case Id_setFullYear: arity=3; s="setFullYear"; break; 134 case Id_setUTCFullYear: arity=3; s="setUTCFullYear"; break; 135 case Id_setYear: arity=1; s="setYear"; break; 136 case Id_toISOString: arity=0; s="toISOString"; break; 137 case Id_toJSON: arity=1; s="toJSON"; break; 138 default: throw new IllegalArgumentException(String.valueOf(id)); 139 } 140 initPrototypeMethod(DATE_TAG, id, s, arity); 141 } 142 143 @Override execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args)144 public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, 145 Scriptable thisObj, Object[] args) 146 { 147 if (!f.hasTag(DATE_TAG)) { 148 return super.execIdCall(f, cx, scope, thisObj, args); 149 } 150 int id = f.methodId(); 151 switch (id) { 152 case ConstructorId_now: 153 return ScriptRuntime.wrapNumber(now()); 154 155 case ConstructorId_parse: 156 { 157 String dataStr = ScriptRuntime.toString(args, 0); 158 return ScriptRuntime.wrapNumber(date_parseString(dataStr)); 159 } 160 161 case ConstructorId_UTC: 162 return ScriptRuntime.wrapNumber(jsStaticFunction_UTC(args)); 163 164 case Id_constructor: 165 { 166 // if called as a function, just return a string 167 // representing the current time. 168 if (thisObj != null) 169 return date_format(now(), Id_toString); 170 return jsConstructor(args); 171 } 172 173 case Id_toJSON: 174 { 175 if (thisObj instanceof NativeDate) { 176 return ((NativeDate) thisObj).toISOString(); 177 } 178 179 final String toISOString = "toISOString"; 180 181 Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); 182 Object tv = ScriptRuntime.toPrimitive(o, ScriptRuntime.NumberClass); 183 if (tv instanceof Number) { 184 double d = ((Number) tv).doubleValue(); 185 if (d != d || Double.isInfinite(d)) { 186 return null; 187 } 188 } 189 Object toISO = o.get(toISOString, o); 190 if (toISO == NOT_FOUND) { 191 throw ScriptRuntime.typeError2("msg.function.not.found.in", 192 toISOString, 193 ScriptRuntime.toString(o)); 194 } 195 if ( !(toISO instanceof Callable) ) { 196 throw ScriptRuntime.typeError3("msg.isnt.function.in", 197 toISOString, 198 ScriptRuntime.toString(o), 199 ScriptRuntime.toString(toISO)); 200 } 201 Object result = ((Callable) toISO).call(cx, scope, o, 202 ScriptRuntime.emptyArgs); 203 if ( !ScriptRuntime.isPrimitive(result) ) { 204 throw ScriptRuntime.typeError1("msg.toisostring.must.return.primitive", 205 ScriptRuntime.toString(result)); 206 } 207 return result; 208 } 209 210 } 211 212 // The rest of Date.prototype methods require thisObj to be Date 213 214 if (!(thisObj instanceof NativeDate)) 215 throw incompatibleCallError(f); 216 NativeDate realThis = (NativeDate)thisObj; 217 double t = realThis.date; 218 219 switch (id) { 220 221 case Id_toString: 222 case Id_toTimeString: 223 case Id_toDateString: 224 if (t == t) { 225 return date_format(t, id); 226 } 227 return js_NaN_date_str; 228 229 case Id_toLocaleString: 230 case Id_toLocaleTimeString: 231 case Id_toLocaleDateString: 232 if (t == t) { 233 return toLocale_helper(t, id); 234 } 235 return js_NaN_date_str; 236 237 case Id_toUTCString: 238 if (t == t) { 239 return js_toUTCString(t); 240 } 241 return js_NaN_date_str; 242 243 case Id_toSource: 244 return "(new Date("+ScriptRuntime.toString(t)+"))"; 245 246 case Id_valueOf: 247 case Id_getTime: 248 return ScriptRuntime.wrapNumber(t); 249 250 case Id_getYear: 251 case Id_getFullYear: 252 case Id_getUTCFullYear: 253 if (t == t) { 254 if (id != Id_getUTCFullYear) t = LocalTime(t); 255 t = YearFromTime(t); 256 if (id == Id_getYear) { 257 if (cx.hasFeature(Context.FEATURE_NON_ECMA_GET_YEAR)) { 258 if (1900 <= t && t < 2000) { 259 t -= 1900; 260 } 261 } else { 262 t -= 1900; 263 } 264 } 265 } 266 return ScriptRuntime.wrapNumber(t); 267 268 case Id_getMonth: 269 case Id_getUTCMonth: 270 if (t == t) { 271 if (id == Id_getMonth) t = LocalTime(t); 272 t = MonthFromTime(t); 273 } 274 return ScriptRuntime.wrapNumber(t); 275 276 case Id_getDate: 277 case Id_getUTCDate: 278 if (t == t) { 279 if (id == Id_getDate) t = LocalTime(t); 280 t = DateFromTime(t); 281 } 282 return ScriptRuntime.wrapNumber(t); 283 284 case Id_getDay: 285 case Id_getUTCDay: 286 if (t == t) { 287 if (id == Id_getDay) t = LocalTime(t); 288 t = WeekDay(t); 289 } 290 return ScriptRuntime.wrapNumber(t); 291 292 case Id_getHours: 293 case Id_getUTCHours: 294 if (t == t) { 295 if (id == Id_getHours) t = LocalTime(t); 296 t = HourFromTime(t); 297 } 298 return ScriptRuntime.wrapNumber(t); 299 300 case Id_getMinutes: 301 case Id_getUTCMinutes: 302 if (t == t) { 303 if (id == Id_getMinutes) t = LocalTime(t); 304 t = MinFromTime(t); 305 } 306 return ScriptRuntime.wrapNumber(t); 307 308 case Id_getSeconds: 309 case Id_getUTCSeconds: 310 if (t == t) { 311 if (id == Id_getSeconds) t = LocalTime(t); 312 t = SecFromTime(t); 313 } 314 return ScriptRuntime.wrapNumber(t); 315 316 case Id_getMilliseconds: 317 case Id_getUTCMilliseconds: 318 if (t == t) { 319 if (id == Id_getMilliseconds) t = LocalTime(t); 320 t = msFromTime(t); 321 } 322 return ScriptRuntime.wrapNumber(t); 323 324 case Id_getTimezoneOffset: 325 if (t == t) { 326 t = (t - LocalTime(t)) / msPerMinute; 327 } 328 return ScriptRuntime.wrapNumber(t); 329 330 case Id_setTime: 331 t = TimeClip(ScriptRuntime.toNumber(args, 0)); 332 realThis.date = t; 333 return ScriptRuntime.wrapNumber(t); 334 335 case Id_setMilliseconds: 336 case Id_setUTCMilliseconds: 337 case Id_setSeconds: 338 case Id_setUTCSeconds: 339 case Id_setMinutes: 340 case Id_setUTCMinutes: 341 case Id_setHours: 342 case Id_setUTCHours: 343 t = makeTime(t, args, id); 344 realThis.date = t; 345 return ScriptRuntime.wrapNumber(t); 346 347 case Id_setDate: 348 case Id_setUTCDate: 349 case Id_setMonth: 350 case Id_setUTCMonth: 351 case Id_setFullYear: 352 case Id_setUTCFullYear: 353 t = makeDate(t, args, id); 354 realThis.date = t; 355 return ScriptRuntime.wrapNumber(t); 356 357 case Id_setYear: 358 { 359 double year = ScriptRuntime.toNumber(args, 0); 360 361 if (year != year || Double.isInfinite(year)) { 362 t = ScriptRuntime.NaN; 363 } else { 364 if (t != t) { 365 t = 0; 366 } else { 367 t = LocalTime(t); 368 } 369 370 if (year >= 0 && year <= 99) 371 year += 1900; 372 373 double day = MakeDay(year, MonthFromTime(t), 374 DateFromTime(t)); 375 t = MakeDate(day, TimeWithinDay(t)); 376 t = internalUTC(t); 377 t = TimeClip(t); 378 } 379 } 380 realThis.date = t; 381 return ScriptRuntime.wrapNumber(t); 382 383 case Id_toISOString: 384 return realThis.toISOString(); 385 386 default: throw new IllegalArgumentException(String.valueOf(id)); 387 } 388 389 } 390 toISOString()391 private String toISOString() { 392 if (date == date) { 393 synchronized (isoFormat) { 394 return isoFormat.format(new Date((long) date)); 395 } 396 } 397 String msg = ScriptRuntime.getMessage0("msg.invalid.date"); 398 throw ScriptRuntime.constructError("RangeError", msg); 399 } 400 401 /* ECMA helper functions */ 402 403 private static final double HalfTimeDomain = 8.64e15; 404 private static final double HoursPerDay = 24.0; 405 private static final double MinutesPerHour = 60.0; 406 private static final double SecondsPerMinute = 60.0; 407 private static final double msPerSecond = 1000.0; 408 private static final double MinutesPerDay = (HoursPerDay * MinutesPerHour); 409 private static final double SecondsPerDay = (MinutesPerDay * SecondsPerMinute); 410 private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute); 411 private static final double msPerDay = (SecondsPerDay * msPerSecond); 412 private static final double msPerHour = (SecondsPerHour * msPerSecond); 413 private static final double msPerMinute = (SecondsPerMinute * msPerSecond); 414 Day(double t)415 private static double Day(double t) 416 { 417 return Math.floor(t / msPerDay); 418 } 419 TimeWithinDay(double t)420 private static double TimeWithinDay(double t) 421 { 422 double result; 423 result = t % msPerDay; 424 if (result < 0) 425 result += msPerDay; 426 return result; 427 } 428 IsLeapYear(int year)429 private static boolean IsLeapYear(int year) 430 { 431 return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); 432 } 433 434 /* math here has to be f.p, because we need 435 * floor((1968 - 1969) / 4) == -1 436 */ DayFromYear(double y)437 private static double DayFromYear(double y) 438 { 439 return ((365 * ((y)-1970) + Math.floor(((y)-1969)/4.0) 440 - Math.floor(((y)-1901)/100.0) + Math.floor(((y)-1601)/400.0))); 441 } 442 TimeFromYear(double y)443 private static double TimeFromYear(double y) 444 { 445 return DayFromYear(y) * msPerDay; 446 } 447 YearFromTime(double t)448 private static int YearFromTime(double t) 449 { 450 int lo = (int) Math.floor((t / msPerDay) / 366) + 1970; 451 int hi = (int) Math.floor((t / msPerDay) / 365) + 1970; 452 int mid; 453 454 /* above doesn't work for negative dates... */ 455 if (hi < lo) { 456 int temp = lo; 457 lo = hi; 458 hi = temp; 459 } 460 461 /* Use a simple binary search algorithm to find the right 462 year. This seems like brute force... but the computation 463 of hi and lo years above lands within one year of the 464 correct answer for years within a thousand years of 465 1970; the loop below only requires six iterations 466 for year 270000. */ 467 while (hi > lo) { 468 mid = (hi + lo) / 2; 469 if (TimeFromYear(mid) > t) { 470 hi = mid - 1; 471 } else { 472 lo = mid + 1; 473 if (TimeFromYear(lo) > t) { 474 return mid; 475 } 476 } 477 } 478 return lo; 479 } 480 DayFromMonth(int m, int year)481 private static double DayFromMonth(int m, int year) 482 { 483 int day = m * 30; 484 485 if (m >= 7) { day += m / 2 - 1; } 486 else if (m >= 2) { day += (m - 1) / 2 - 1; } 487 else { day += m; } 488 489 if (m >= 2 && IsLeapYear(year)) { ++day; } 490 491 return day; 492 } 493 MonthFromTime(double t)494 private static int MonthFromTime(double t) 495 { 496 int year = YearFromTime(t); 497 int d = (int)(Day(t) - DayFromYear(year)); 498 499 d -= 31 + 28; 500 if (d < 0) { 501 return (d < -28) ? 0 : 1; 502 } 503 504 if (IsLeapYear(year)) { 505 if (d == 0) 506 return 1; // 29 February 507 --d; 508 } 509 510 // d: date count from 1 March 511 int estimate = d / 30; // approx number of month since March 512 int mstart; 513 switch (estimate) { 514 case 0: return 2; 515 case 1: mstart = 31; break; 516 case 2: mstart = 31+30; break; 517 case 3: mstart = 31+30+31; break; 518 case 4: mstart = 31+30+31+30; break; 519 case 5: mstart = 31+30+31+30+31; break; 520 case 6: mstart = 31+30+31+30+31+31; break; 521 case 7: mstart = 31+30+31+30+31+31+30; break; 522 case 8: mstart = 31+30+31+30+31+31+30+31; break; 523 case 9: mstart = 31+30+31+30+31+31+30+31+30; break; 524 case 10: return 11; //Late december 525 default: throw Kit.codeBug(); 526 } 527 // if d < mstart then real month since March == estimate - 1 528 return (d >= mstart) ? estimate + 2 : estimate + 1; 529 } 530 DateFromTime(double t)531 private static int DateFromTime(double t) 532 { 533 int year = YearFromTime(t); 534 int d = (int)(Day(t) - DayFromYear(year)); 535 536 d -= 31 + 28; 537 if (d < 0) { 538 return (d < -28) ? d + 31 + 28 + 1 : d + 28 + 1; 539 } 540 541 if (IsLeapYear(year)) { 542 if (d == 0) 543 return 29; // 29 February 544 --d; 545 } 546 547 // d: date count from 1 March 548 int mdays, mstart; 549 switch (d / 30) { // approx number of month since March 550 case 0: return d + 1; 551 case 1: mdays = 31; mstart = 31; break; 552 case 2: mdays = 30; mstart = 31+30; break; 553 case 3: mdays = 31; mstart = 31+30+31; break; 554 case 4: mdays = 30; mstart = 31+30+31+30; break; 555 case 5: mdays = 31; mstart = 31+30+31+30+31; break; 556 case 6: mdays = 31; mstart = 31+30+31+30+31+31; break; 557 case 7: mdays = 30; mstart = 31+30+31+30+31+31+30; break; 558 case 8: mdays = 31; mstart = 31+30+31+30+31+31+30+31; break; 559 case 9: mdays = 30; mstart = 31+30+31+30+31+31+30+31+30; break; 560 case 10: 561 return d - (31+30+31+30+31+31+30+31+30) + 1; //Late december 562 default: throw Kit.codeBug(); 563 } 564 d -= mstart; 565 if (d < 0) { 566 // wrong estimate: sfhift to previous month 567 d += mdays; 568 } 569 return d + 1; 570 } 571 WeekDay(double t)572 private static int WeekDay(double t) 573 { 574 double result; 575 result = Day(t) + 4; 576 result = result % 7; 577 if (result < 0) 578 result += 7; 579 return (int) result; 580 } 581 now()582 private static double now() 583 { 584 return System.currentTimeMillis(); 585 } 586 DaylightSavingTA(double t)587 private static double DaylightSavingTA(double t) 588 { 589 // Another workaround! The JRE doesn't seem to know about DST 590 // before year 1 AD, so we map to equivalent dates for the 591 // purposes of finding DST. To be safe, we do this for years 592 // before 1970. 593 if (t < 0.0) { 594 int year = EquivalentYear(YearFromTime(t)); 595 double day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); 596 t = MakeDate(day, TimeWithinDay(t)); 597 } 598 Date date = new Date((long) t); 599 if (thisTimeZone.inDaylightTime(date)) 600 return msPerHour; 601 else 602 return 0; 603 } 604 605 /* 606 * Find a year for which any given date will fall on the same weekday. 607 * 608 * This function should be used with caution when used other than 609 * for determining DST; it hasn't been proven not to produce an 610 * incorrect year for times near year boundaries. 611 */ EquivalentYear(int year)612 private static int EquivalentYear(int year) 613 { 614 int day = (int) DayFromYear(year) + 4; 615 day = day % 7; 616 if (day < 0) 617 day += 7; 618 // Years and leap years on which Jan 1 is a Sunday, Monday, etc. 619 if (IsLeapYear(year)) { 620 switch (day) { 621 case 0: return 1984; 622 case 1: return 1996; 623 case 2: return 1980; 624 case 3: return 1992; 625 case 4: return 1976; 626 case 5: return 1988; 627 case 6: return 1972; 628 } 629 } else { 630 switch (day) { 631 case 0: return 1978; 632 case 1: return 1973; 633 case 2: return 1985; 634 case 3: return 1986; 635 case 4: return 1981; 636 case 5: return 1971; 637 case 6: return 1977; 638 } 639 } 640 // Unreachable 641 throw Kit.codeBug(); 642 } 643 LocalTime(double t)644 private static double LocalTime(double t) 645 { 646 return t + LocalTZA + DaylightSavingTA(t); 647 } 648 internalUTC(double t)649 private static double internalUTC(double t) 650 { 651 return t - LocalTZA - DaylightSavingTA(t - LocalTZA); 652 } 653 HourFromTime(double t)654 private static int HourFromTime(double t) 655 { 656 double result; 657 result = Math.floor(t / msPerHour) % HoursPerDay; 658 if (result < 0) 659 result += HoursPerDay; 660 return (int) result; 661 } 662 MinFromTime(double t)663 private static int MinFromTime(double t) 664 { 665 double result; 666 result = Math.floor(t / msPerMinute) % MinutesPerHour; 667 if (result < 0) 668 result += MinutesPerHour; 669 return (int) result; 670 } 671 SecFromTime(double t)672 private static int SecFromTime(double t) 673 { 674 double result; 675 result = Math.floor(t / msPerSecond) % SecondsPerMinute; 676 if (result < 0) 677 result += SecondsPerMinute; 678 return (int) result; 679 } 680 msFromTime(double t)681 private static int msFromTime(double t) 682 { 683 double result; 684 result = t % msPerSecond; 685 if (result < 0) 686 result += msPerSecond; 687 return (int) result; 688 } 689 MakeTime(double hour, double min, double sec, double ms)690 private static double MakeTime(double hour, double min, 691 double sec, double ms) 692 { 693 return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) 694 * msPerSecond + ms; 695 } 696 MakeDay(double year, double month, double date)697 private static double MakeDay(double year, double month, double date) 698 { 699 year += Math.floor(month / 12); 700 701 month = month % 12; 702 if (month < 0) 703 month += 12; 704 705 double yearday = Math.floor(TimeFromYear(year) / msPerDay); 706 double monthday = DayFromMonth((int)month, (int)year); 707 708 return yearday + monthday + date - 1; 709 } 710 MakeDate(double day, double time)711 private static double MakeDate(double day, double time) 712 { 713 return day * msPerDay + time; 714 } 715 TimeClip(double d)716 private static double TimeClip(double d) 717 { 718 if (d != d || 719 d == Double.POSITIVE_INFINITY || 720 d == Double.NEGATIVE_INFINITY || 721 Math.abs(d) > HalfTimeDomain) 722 { 723 return ScriptRuntime.NaN; 724 } 725 if (d > 0.0) 726 return Math.floor(d + 0.); 727 else 728 return Math.ceil(d + 0.); 729 } 730 731 /* end of ECMA helper functions */ 732 733 /* find UTC time from given date... no 1900 correction! */ date_msecFromDate(double year, double mon, double mday, double hour, double min, double sec, double msec)734 private static double date_msecFromDate(double year, double mon, 735 double mday, double hour, 736 double min, double sec, 737 double msec) 738 { 739 double day; 740 double time; 741 double result; 742 743 day = MakeDay(year, mon, mday); 744 time = MakeTime(hour, min, sec, msec); 745 result = MakeDate(day, time); 746 return result; 747 } 748 749 /* compute the time in msec (unclipped) from the given args */ 750 private static final int MAXARGS = 7; date_msecFromArgs(Object[] args)751 private static double date_msecFromArgs(Object[] args) 752 { 753 double array[] = new double[MAXARGS]; 754 int loop; 755 double d; 756 757 for (loop = 0; loop < MAXARGS; loop++) { 758 if (loop < args.length) { 759 d = ScriptRuntime.toNumber(args[loop]); 760 if (d != d || Double.isInfinite(d)) { 761 return ScriptRuntime.NaN; 762 } 763 array[loop] = ScriptRuntime.toInteger(args[loop]); 764 } else { 765 if (loop == 2) { 766 array[loop] = 1; /* Default the date argument to 1. */ 767 } else { 768 array[loop] = 0; 769 } 770 } 771 } 772 773 /* adjust 2-digit years into the 20th century */ 774 if (array[0] >= 0 && array[0] <= 99) 775 array[0] += 1900; 776 777 return date_msecFromDate(array[0], array[1], array[2], 778 array[3], array[4], array[5], array[6]); 779 } 780 jsStaticFunction_UTC(Object[] args)781 private static double jsStaticFunction_UTC(Object[] args) 782 { 783 return TimeClip(date_msecFromArgs(args)); 784 } 785 date_parseString(String s)786 private static double date_parseString(String s) 787 { 788 try { 789 if (s.length() == 24) { 790 final Date d; 791 synchronized(isoFormat) { 792 d = isoFormat.parse(s); 793 } 794 return d.getTime(); 795 } 796 } catch (java.text.ParseException ex) {} 797 798 int year = -1; 799 int mon = -1; 800 int mday = -1; 801 int hour = -1; 802 int min = -1; 803 int sec = -1; 804 char c = 0; 805 char si = 0; 806 int i = 0; 807 int n = -1; 808 double tzoffset = -1; 809 char prevc = 0; 810 int limit = 0; 811 boolean seenplusminus = false; 812 813 limit = s.length(); 814 while (i < limit) { 815 c = s.charAt(i); 816 i++; 817 if (c <= ' ' || c == ',' || c == '-') { 818 if (i < limit) { 819 si = s.charAt(i); 820 if (c == '-' && '0' <= si && si <= '9') { 821 prevc = c; 822 } 823 } 824 continue; 825 } 826 if (c == '(') { /* comments) */ 827 int depth = 1; 828 while (i < limit) { 829 c = s.charAt(i); 830 i++; 831 if (c == '(') 832 depth++; 833 else if (c == ')') 834 if (--depth <= 0) 835 break; 836 } 837 continue; 838 } 839 if ('0' <= c && c <= '9') { 840 n = c - '0'; 841 while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') { 842 n = n * 10 + c - '0'; 843 i++; 844 } 845 846 /* allow TZA before the year, so 847 * 'Wed Nov 05 21:49:11 GMT-0800 1997' 848 * works */ 849 850 /* uses of seenplusminus allow : in TZA, so Java 851 * no-timezone style of GMT+4:30 works 852 */ 853 if ((prevc == '+' || prevc == '-')/* && year>=0 */) { 854 /* make ':' case below change tzoffset */ 855 seenplusminus = true; 856 857 /* offset */ 858 if (n < 24) 859 n = n * 60; /* EG. "GMT-3" */ 860 else 861 n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */ 862 if (prevc == '+') /* plus means east of GMT */ 863 n = -n; 864 if (tzoffset != 0 && tzoffset != -1) 865 return ScriptRuntime.NaN; 866 tzoffset = n; 867 } else if (n >= 70 || 868 (prevc == '/' && mon >= 0 && mday >= 0 869 && year < 0)) 870 { 871 if (year >= 0) 872 return ScriptRuntime.NaN; 873 else if (c <= ' ' || c == ',' || c == '/' || i >= limit) 874 year = n < 100 ? n + 1900 : n; 875 else 876 return ScriptRuntime.NaN; 877 } else if (c == ':') { 878 if (hour < 0) 879 hour = /*byte*/ n; 880 else if (min < 0) 881 min = /*byte*/ n; 882 else 883 return ScriptRuntime.NaN; 884 } else if (c == '/') { 885 if (mon < 0) 886 mon = /*byte*/ n-1; 887 else if (mday < 0) 888 mday = /*byte*/ n; 889 else 890 return ScriptRuntime.NaN; 891 } else if (i < limit && c != ',' && c > ' ' && c != '-') { 892 return ScriptRuntime.NaN; 893 } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */ 894 if (tzoffset < 0) 895 tzoffset -= n; 896 else 897 tzoffset += n; 898 } else if (hour >= 0 && min < 0) { 899 min = /*byte*/ n; 900 } else if (min >= 0 && sec < 0) { 901 sec = /*byte*/ n; 902 } else if (mday < 0) { 903 mday = /*byte*/ n; 904 } else { 905 return ScriptRuntime.NaN; 906 } 907 prevc = 0; 908 } else if (c == '/' || c == ':' || c == '+' || c == '-') { 909 prevc = c; 910 } else { 911 int st = i - 1; 912 while (i < limit) { 913 c = s.charAt(i); 914 if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))) 915 break; 916 i++; 917 } 918 int letterCount = i - st; 919 if (letterCount < 2) 920 return ScriptRuntime.NaN; 921 /* 922 * Use ported code from jsdate.c rather than the locale-specific 923 * date-parsing code from Java, to keep js and rhino consistent. 924 * Is this the right strategy? 925 */ 926 String wtb = "am;pm;" 927 +"monday;tuesday;wednesday;thursday;friday;" 928 +"saturday;sunday;" 929 +"january;february;march;april;may;june;" 930 +"july;august;september;october;november;december;" 931 +"gmt;ut;utc;est;edt;cst;cdt;mst;mdt;pst;pdt;"; 932 int index = 0; 933 for (int wtbOffset = 0; ;) { 934 int wtbNext = wtb.indexOf(';', wtbOffset); 935 if (wtbNext < 0) 936 return ScriptRuntime.NaN; 937 if (wtb.regionMatches(true, wtbOffset, s, st, letterCount)) 938 break; 939 wtbOffset = wtbNext + 1; 940 ++index; 941 } 942 if (index < 2) { 943 /* 944 * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as 945 * 12:30, instead of blindly adding 12 if PM. 946 */ 947 if (hour > 12 || hour < 0) { 948 return ScriptRuntime.NaN; 949 } else if (index == 0) { 950 // AM 951 if (hour == 12) 952 hour = 0; 953 } else { 954 // PM 955 if (hour != 12) 956 hour += 12; 957 } 958 } else if ((index -= 2) < 7) { 959 // ignore week days 960 } else if ((index -= 7) < 12) { 961 // month 962 if (mon < 0) { 963 mon = index; 964 } else { 965 return ScriptRuntime.NaN; 966 } 967 } else { 968 index -= 12; 969 // timezones 970 switch (index) { 971 case 0 /* gmt */: tzoffset = 0; break; 972 case 1 /* ut */: tzoffset = 0; break; 973 case 2 /* utc */: tzoffset = 0; break; 974 case 3 /* est */: tzoffset = 5 * 60; break; 975 case 4 /* edt */: tzoffset = 4 * 60; break; 976 case 5 /* cst */: tzoffset = 6 * 60; break; 977 case 6 /* cdt */: tzoffset = 5 * 60; break; 978 case 7 /* mst */: tzoffset = 7 * 60; break; 979 case 8 /* mdt */: tzoffset = 6 * 60; break; 980 case 9 /* pst */: tzoffset = 8 * 60; break; 981 case 10 /* pdt */:tzoffset = 7 * 60; break; 982 default: Kit.codeBug(); 983 } 984 } 985 } 986 } 987 if (year < 0 || mon < 0 || mday < 0) 988 return ScriptRuntime.NaN; 989 if (sec < 0) 990 sec = 0; 991 if (min < 0) 992 min = 0; 993 if (hour < 0) 994 hour = 0; 995 996 double msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0); 997 if (tzoffset == -1) { /* no time zone specified, have to use local */ 998 return internalUTC(msec); 999 } else { 1000 return msec + tzoffset * msPerMinute; 1001 } 1002 } 1003 1004 private static String date_format(double t, int methodId) 1005 { 1006 StringBuffer result = new StringBuffer(60); 1007 double local = LocalTime(t); 1008 1009 /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */ 1010 /* Tue Oct 31 2000 */ 1011 /* 09:41:40 GMT-0800 (PST) */ 1012 1013 if (methodId != Id_toTimeString) { 1014 appendWeekDayName(result, WeekDay(local)); 1015 result.append(' '); 1016 appendMonthName(result, MonthFromTime(local)); 1017 result.append(' '); 1018 append0PaddedUint(result, DateFromTime(local), 2); 1019 result.append(' '); 1020 int year = YearFromTime(local); 1021 if (year < 0) { 1022 result.append('-'); 1023 year = -year; 1024 } 1025 append0PaddedUint(result, year, 4); 1026 if (methodId != Id_toDateString) 1027 result.append(' '); 1028 } 1029 1030 if (methodId != Id_toDateString) { 1031 append0PaddedUint(result, HourFromTime(local), 2); 1032 result.append(':'); 1033 append0PaddedUint(result, MinFromTime(local), 2); 1034 result.append(':'); 1035 append0PaddedUint(result, SecFromTime(local), 2); 1036 1037 // offset from GMT in minutes. The offset includes daylight 1038 // savings, if it applies. 1039 int minutes = (int) Math.floor((LocalTZA + DaylightSavingTA(t)) 1040 / msPerMinute); 1041 // map 510 minutes to 0830 hours 1042 int offset = (minutes / 60) * 100 + minutes % 60; 1043 if (offset > 0) { 1044 result.append(" GMT+"); 1045 } else { 1046 result.append(" GMT-"); 1047 offset = -offset; 1048 } 1049 append0PaddedUint(result, offset, 4); 1050 1051 if (timeZoneFormatter == null) 1052 timeZoneFormatter = new SimpleDateFormat("zzz"); 1053 1054 // Find an equivalent year before getting the timezone 1055 // comment. See DaylightSavingTA. 1056 if (t < 0.0) { 1057 int equiv = EquivalentYear(YearFromTime(local)); 1058 double day = MakeDay(equiv, MonthFromTime(t), DateFromTime(t)); 1059 t = MakeDate(day, TimeWithinDay(t)); 1060 } 1061 result.append(" ("); 1062 Date date = new Date((long) t); 1063 synchronized (timeZoneFormatter) { 1064 result.append(timeZoneFormatter.format(date)); 1065 } 1066 result.append(')'); 1067 } 1068 return result.toString(); 1069 } 1070 1071 /* the javascript constructor */ 1072 private static Object jsConstructor(Object[] args) 1073 { 1074 NativeDate obj = new NativeDate(); 1075 1076 // if called as a constructor with no args, 1077 // return a new Date with the current time. 1078 if (args.length == 0) { 1079 obj.date = now(); 1080 return obj; 1081 } 1082 1083 // if called with just one arg - 1084 if (args.length == 1) { 1085 Object arg0 = args[0]; 1086 if (arg0 instanceof Scriptable) 1087 arg0 = ((Scriptable) arg0).getDefaultValue(null); 1088 double date; 1089 if (arg0 instanceof CharSequence) { 1090 // it's a string; parse it. 1091 date = date_parseString(arg0.toString()); 1092 } else { 1093 // if it's not a string, use it as a millisecond date 1094 date = ScriptRuntime.toNumber(arg0); 1095 } 1096 obj.date = TimeClip(date); 1097 return obj; 1098 } 1099 1100 double time = date_msecFromArgs(args); 1101 1102 if (!Double.isNaN(time) && !Double.isInfinite(time)) 1103 time = TimeClip(internalUTC(time)); 1104 1105 obj.date = time; 1106 1107 return obj; 1108 } 1109 1110 private static String toLocale_helper(double t, int methodId) 1111 { 1112 DateFormat formatter; 1113 switch (methodId) { 1114 case Id_toLocaleString: 1115 if (localeDateTimeFormatter == null) { 1116 localeDateTimeFormatter 1117 = DateFormat.getDateTimeInstance(DateFormat.LONG, 1118 DateFormat.LONG); 1119 } 1120 formatter = localeDateTimeFormatter; 1121 break; 1122 case Id_toLocaleTimeString: 1123 if (localeTimeFormatter == null) { 1124 localeTimeFormatter 1125 = DateFormat.getTimeInstance(DateFormat.LONG); 1126 } 1127 formatter = localeTimeFormatter; 1128 break; 1129 case Id_toLocaleDateString: 1130 if (localeDateFormatter == null) { 1131 localeDateFormatter 1132 = DateFormat.getDateInstance(DateFormat.LONG); 1133 } 1134 formatter = localeDateFormatter; 1135 break; 1136 default: throw new AssertionError(); // unreachable 1137 } 1138 1139 synchronized (formatter) { 1140 return formatter.format(new Date((long) t)); 1141 } 1142 } 1143 1144 private static String js_toUTCString(double date) 1145 { 1146 StringBuffer result = new StringBuffer(60); 1147 1148 appendWeekDayName(result, WeekDay(date)); 1149 result.append(", "); 1150 append0PaddedUint(result, DateFromTime(date), 2); 1151 result.append(' '); 1152 appendMonthName(result, MonthFromTime(date)); 1153 result.append(' '); 1154 int year = YearFromTime(date); 1155 if (year < 0) { 1156 result.append('-'); year = -year; 1157 } 1158 append0PaddedUint(result, year, 4); 1159 result.append(' '); 1160 append0PaddedUint(result, HourFromTime(date), 2); 1161 result.append(':'); 1162 append0PaddedUint(result, MinFromTime(date), 2); 1163 result.append(':'); 1164 append0PaddedUint(result, SecFromTime(date), 2); 1165 result.append(" GMT"); 1166 return result.toString(); 1167 } 1168 1169 private static void append0PaddedUint(StringBuffer sb, int i, int minWidth) 1170 { 1171 if (i < 0) Kit.codeBug(); 1172 int scale = 1; 1173 --minWidth; 1174 if (i >= 10) { 1175 if (i < 1000 * 1000 * 1000) { 1176 for (;;) { 1177 int newScale = scale * 10; 1178 if (i < newScale) { break; } 1179 --minWidth; 1180 scale = newScale; 1181 } 1182 } else { 1183 // Separated case not to check against 10 * 10^9 overflow 1184 minWidth -= 9; 1185 scale = 1000 * 1000 * 1000; 1186 } 1187 } 1188 while (minWidth > 0) { 1189 sb.append('0'); 1190 --minWidth; 1191 } 1192 while (scale != 1) { 1193 sb.append((char)('0' + (i / scale))); 1194 i %= scale; 1195 scale /= 10; 1196 } 1197 sb.append((char)('0' + i)); 1198 } 1199 1200 private static void appendMonthName(StringBuffer sb, int index) 1201 { 1202 // Take advantage of the fact that all month abbreviations 1203 // have the same length to minimize amount of strings runtime has 1204 // to keep in memory 1205 String months = "Jan"+"Feb"+"Mar"+"Apr"+"May"+"Jun" 1206 +"Jul"+"Aug"+"Sep"+"Oct"+"Nov"+"Dec"; 1207 index *= 3; 1208 for (int i = 0; i != 3; ++i) { 1209 sb.append(months.charAt(index + i)); 1210 } 1211 } 1212 1213 private static void appendWeekDayName(StringBuffer sb, int index) 1214 { 1215 String days = "Sun"+"Mon"+"Tue"+"Wed"+"Thu"+"Fri"+"Sat"; 1216 index *= 3; 1217 for (int i = 0; i != 3; ++i) { 1218 sb.append(days.charAt(index + i)); 1219 } 1220 } 1221 1222 private static double makeTime(double date, Object[] args, int methodId) 1223 { 1224 int maxargs; 1225 boolean local = true; 1226 switch (methodId) { 1227 case Id_setUTCMilliseconds: 1228 local = false; 1229 // fallthrough 1230 case Id_setMilliseconds: 1231 maxargs = 1; 1232 break; 1233 1234 case Id_setUTCSeconds: 1235 local = false; 1236 // fallthrough 1237 case Id_setSeconds: 1238 maxargs = 2; 1239 break; 1240 1241 case Id_setUTCMinutes: 1242 local = false; 1243 // fallthrough 1244 case Id_setMinutes: 1245 maxargs = 3; 1246 break; 1247 1248 case Id_setUTCHours: 1249 local = false; 1250 // fallthrough 1251 case Id_setHours: 1252 maxargs = 4; 1253 break; 1254 1255 default: 1256 Kit.codeBug(); 1257 maxargs = 0; 1258 } 1259 1260 int i; 1261 double conv[] = new double[4]; 1262 double hour, min, sec, msec; 1263 double lorutime; /* Local or UTC version of date */ 1264 1265 double time; 1266 double result; 1267 1268 /* just return NaN if the date is already NaN */ 1269 if (date != date) 1270 return date; 1271 1272 /* Satisfy the ECMA rule that if a function is called with 1273 * fewer arguments than the specified formal arguments, the 1274 * remaining arguments are set to undefined. Seems like all 1275 * the Date.setWhatever functions in ECMA are only varargs 1276 * beyond the first argument; this should be set to undefined 1277 * if it's not given. This means that "d = new Date(); 1278 * d.setMilliseconds()" returns NaN. Blech. 1279 */ 1280 if (args.length == 0) 1281 args = ScriptRuntime.padArguments(args, 1); 1282 1283 for (i = 0; i < args.length && i < maxargs; i++) { 1284 conv[i] = ScriptRuntime.toNumber(args[i]); 1285 1286 // limit checks that happen in MakeTime in ECMA. 1287 if (conv[i] != conv[i] || Double.isInfinite(conv[i])) { 1288 return ScriptRuntime.NaN; 1289 } 1290 conv[i] = ScriptRuntime.toInteger(conv[i]); 1291 } 1292 1293 if (local) 1294 lorutime = LocalTime(date); 1295 else 1296 lorutime = date; 1297 1298 i = 0; 1299 int stop = args.length; 1300 1301 if (maxargs >= 4 && i < stop) 1302 hour = conv[i++]; 1303 else 1304 hour = HourFromTime(lorutime); 1305 1306 if (maxargs >= 3 && i < stop) 1307 min = conv[i++]; 1308 else 1309 min = MinFromTime(lorutime); 1310 1311 if (maxargs >= 2 && i < stop) 1312 sec = conv[i++]; 1313 else 1314 sec = SecFromTime(lorutime); 1315 1316 if (maxargs >= 1 && i < stop) 1317 msec = conv[i++]; 1318 else 1319 msec = msFromTime(lorutime); 1320 1321 time = MakeTime(hour, min, sec, msec); 1322 result = MakeDate(Day(lorutime), time); 1323 1324 if (local) 1325 result = internalUTC(result); 1326 date = TimeClip(result); 1327 1328 return date; 1329 } 1330 1331 private static double makeDate(double date, Object[] args, int methodId) 1332 { 1333 int maxargs; 1334 boolean local = true; 1335 switch (methodId) { 1336 case Id_setUTCDate: 1337 local = false; 1338 // fallthrough 1339 case Id_setDate: 1340 maxargs = 1; 1341 break; 1342 1343 case Id_setUTCMonth: 1344 local = false; 1345 // fallthrough 1346 case Id_setMonth: 1347 maxargs = 2; 1348 break; 1349 1350 case Id_setUTCFullYear: 1351 local = false; 1352 // fallthrough 1353 case Id_setFullYear: 1354 maxargs = 3; 1355 break; 1356 1357 default: 1358 Kit.codeBug(); 1359 maxargs = 0; 1360 } 1361 1362 int i; 1363 double conv[] = new double[3]; 1364 double year, month, day; 1365 double lorutime; /* local or UTC version of date */ 1366 double result; 1367 1368 /* See arg padding comment in makeTime.*/ 1369 if (args.length == 0) 1370 args = ScriptRuntime.padArguments(args, 1); 1371 1372 for (i = 0; i < args.length && i < maxargs; i++) { 1373 conv[i] = ScriptRuntime.toNumber(args[i]); 1374 1375 // limit checks that happen in MakeDate in ECMA. 1376 if (conv[i] != conv[i] || Double.isInfinite(conv[i])) { 1377 return ScriptRuntime.NaN; 1378 } 1379 conv[i] = ScriptRuntime.toInteger(conv[i]); 1380 } 1381 1382 /* return NaN if date is NaN and we're not setting the year, 1383 * If we are, use 0 as the time. */ 1384 if (date != date) { 1385 if (args.length < 3) { 1386 return ScriptRuntime.NaN; 1387 } else { 1388 lorutime = 0; 1389 } 1390 } else { 1391 if (local) 1392 lorutime = LocalTime(date); 1393 else 1394 lorutime = date; 1395 } 1396 1397 i = 0; 1398 int stop = args.length; 1399 1400 if (maxargs >= 3 && i < stop) 1401 year = conv[i++]; 1402 else 1403 year = YearFromTime(lorutime); 1404 1405 if (maxargs >= 2 && i < stop) 1406 month = conv[i++]; 1407 else 1408 month = MonthFromTime(lorutime); 1409 1410 if (maxargs >= 1 && i < stop) 1411 day = conv[i++]; 1412 else 1413 day = DateFromTime(lorutime); 1414 1415 day = MakeDay(year, month, day); /* day within year */ 1416 result = MakeDate(day, TimeWithinDay(lorutime)); 1417 1418 if (local) 1419 result = internalUTC(result); 1420 1421 date = TimeClip(result); 1422 1423 return date; 1424 } 1425 1426 // #string_id_map# 1427 1428 @Override 1429 protected int findPrototypeId(String s) 1430 { 1431 int id; 1432 // #generated# Last update: 2009-07-22 05:44:02 EST 1433 L0: { id = 0; String X = null; int c; 1434 L: switch (s.length()) { 1435 case 6: c=s.charAt(0); 1436 if (c=='g') { X="getDay";id=Id_getDay; } 1437 else if (c=='t') { X="toJSON";id=Id_toJSON; } 1438 break L; 1439 case 7: switch (s.charAt(3)) { 1440 case 'D': c=s.charAt(0); 1441 if (c=='g') { X="getDate";id=Id_getDate; } 1442 else if (c=='s') { X="setDate";id=Id_setDate; } 1443 break L; 1444 case 'T': c=s.charAt(0); 1445 if (c=='g') { X="getTime";id=Id_getTime; } 1446 else if (c=='s') { X="setTime";id=Id_setTime; } 1447 break L; 1448 case 'Y': c=s.charAt(0); 1449 if (c=='g') { X="getYear";id=Id_getYear; } 1450 else if (c=='s') { X="setYear";id=Id_setYear; } 1451 break L; 1452 case 'u': X="valueOf";id=Id_valueOf; break L; 1453 } break L; 1454 case 8: switch (s.charAt(3)) { 1455 case 'H': c=s.charAt(0); 1456 if (c=='g') { X="getHours";id=Id_getHours; } 1457 else if (c=='s') { X="setHours";id=Id_setHours; } 1458 break L; 1459 case 'M': c=s.charAt(0); 1460 if (c=='g') { X="getMonth";id=Id_getMonth; } 1461 else if (c=='s') { X="setMonth";id=Id_setMonth; } 1462 break L; 1463 case 'o': X="toSource";id=Id_toSource; break L; 1464 case 't': X="toString";id=Id_toString; break L; 1465 } break L; 1466 case 9: X="getUTCDay";id=Id_getUTCDay; break L; 1467 case 10: c=s.charAt(3); 1468 if (c=='M') { 1469 c=s.charAt(0); 1470 if (c=='g') { X="getMinutes";id=Id_getMinutes; } 1471 else if (c=='s') { X="setMinutes";id=Id_setMinutes; } 1472 } 1473 else if (c=='S') { 1474 c=s.charAt(0); 1475 if (c=='g') { X="getSeconds";id=Id_getSeconds; } 1476 else if (c=='s') { X="setSeconds";id=Id_setSeconds; } 1477 } 1478 else if (c=='U') { 1479 c=s.charAt(0); 1480 if (c=='g') { X="getUTCDate";id=Id_getUTCDate; } 1481 else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; } 1482 } 1483 break L; 1484 case 11: switch (s.charAt(3)) { 1485 case 'F': c=s.charAt(0); 1486 if (c=='g') { X="getFullYear";id=Id_getFullYear; } 1487 else if (c=='s') { X="setFullYear";id=Id_setFullYear; } 1488 break L; 1489 case 'M': X="toGMTString";id=Id_toGMTString; break L; 1490 case 'S': X="toISOString";id=Id_toISOString; break L; 1491 case 'T': X="toUTCString";id=Id_toUTCString; break L; 1492 case 'U': c=s.charAt(0); 1493 if (c=='g') { 1494 c=s.charAt(9); 1495 if (c=='r') { X="getUTCHours";id=Id_getUTCHours; } 1496 else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; } 1497 } 1498 else if (c=='s') { 1499 c=s.charAt(9); 1500 if (c=='r') { X="setUTCHours";id=Id_setUTCHours; } 1501 else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; } 1502 } 1503 break L; 1504 case 's': X="constructor";id=Id_constructor; break L; 1505 } break L; 1506 case 12: c=s.charAt(2); 1507 if (c=='D') { X="toDateString";id=Id_toDateString; } 1508 else if (c=='T') { X="toTimeString";id=Id_toTimeString; } 1509 break L; 1510 case 13: c=s.charAt(0); 1511 if (c=='g') { 1512 c=s.charAt(6); 1513 if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; } 1514 else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; } 1515 } 1516 else if (c=='s') { 1517 c=s.charAt(6); 1518 if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; } 1519 else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; } 1520 } 1521 break L; 1522 case 14: c=s.charAt(0); 1523 if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; } 1524 else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; } 1525 else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; } 1526 break L; 1527 case 15: c=s.charAt(0); 1528 if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; } 1529 else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; } 1530 break L; 1531 case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L; 1532 case 18: c=s.charAt(0); 1533 if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; } 1534 else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; } 1535 else if (c=='t') { 1536 c=s.charAt(8); 1537 if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; } 1538 else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; } 1539 } 1540 break L; 1541 } 1542 if (X!=null && X!=s && !X.equals(s)) id = 0; 1543 break L0; 1544 } 1545 // #/generated# 1546 return id; 1547 } 1548 1549 private static final int 1550 ConstructorId_now = -3, 1551 ConstructorId_parse = -2, 1552 ConstructorId_UTC = -1, 1553 1554 Id_constructor = 1, 1555 Id_toString = 2, 1556 Id_toTimeString = 3, 1557 Id_toDateString = 4, 1558 Id_toLocaleString = 5, 1559 Id_toLocaleTimeString = 6, 1560 Id_toLocaleDateString = 7, 1561 Id_toUTCString = 8, 1562 Id_toSource = 9, 1563 Id_valueOf = 10, 1564 Id_getTime = 11, 1565 Id_getYear = 12, 1566 Id_getFullYear = 13, 1567 Id_getUTCFullYear = 14, 1568 Id_getMonth = 15, 1569 Id_getUTCMonth = 16, 1570 Id_getDate = 17, 1571 Id_getUTCDate = 18, 1572 Id_getDay = 19, 1573 Id_getUTCDay = 20, 1574 Id_getHours = 21, 1575 Id_getUTCHours = 22, 1576 Id_getMinutes = 23, 1577 Id_getUTCMinutes = 24, 1578 Id_getSeconds = 25, 1579 Id_getUTCSeconds = 26, 1580 Id_getMilliseconds = 27, 1581 Id_getUTCMilliseconds = 28, 1582 Id_getTimezoneOffset = 29, 1583 Id_setTime = 30, 1584 Id_setMilliseconds = 31, 1585 Id_setUTCMilliseconds = 32, 1586 Id_setSeconds = 33, 1587 Id_setUTCSeconds = 34, 1588 Id_setMinutes = 35, 1589 Id_setUTCMinutes = 36, 1590 Id_setHours = 37, 1591 Id_setUTCHours = 38, 1592 Id_setDate = 39, 1593 Id_setUTCDate = 40, 1594 Id_setMonth = 41, 1595 Id_setUTCMonth = 42, 1596 Id_setFullYear = 43, 1597 Id_setUTCFullYear = 44, 1598 Id_setYear = 45, 1599 Id_toISOString = 46, 1600 Id_toJSON = 47, 1601 1602 MAX_PROTOTYPE_ID = Id_toJSON; 1603 1604 private static final int 1605 Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6 1606 // #/string_id_map# 1607 1608 /* cached values */ 1609 private static TimeZone thisTimeZone; 1610 private static double LocalTZA; 1611 private static DateFormat timeZoneFormatter; 1612 private static DateFormat localeDateTimeFormatter; 1613 private static DateFormat localeDateFormatter; 1614 private static DateFormat localeTimeFormatter; 1615 1616 private double date; 1617 } 1618 1619 1620