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