1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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/
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.
13 * The Original Code is Rhino code, released
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
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.
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;
46 * This class implements the Date native object.
50 public class JSDate extends JSCallable {
53 if (thisTimeZone == null) {
54 // j.u.TimeZone is synchronized, so setting class statics from it
56 thisTimeZone = java.util.TimeZone.getDefault();
57 LocalTZA = thisTimeZone.getRawOffset();
61 public String coerceToString() { return date_format(date, FORMATSPEC_FULL); }
63 public Object call(Object name, JSArray args_) {
64 Object[] args = new Object[args_.length()];
65 for(int i=0; i<args.length; i++) args[i] = args_.elementAt(i);
67 if (name.equals(getIdName(ConstructorId_UTC))) {
68 return new Double(jsStaticJSFunction_UTC(args));
70 } else if (name.equals(getIdName(ConstructorId_parse))) {
71 return new Double(jsStaticJSFunction_parse(args[0].toString()));
73 } else if (name.equals(getIdName(Id_constructor))) {
74 return new JSDate(args_);
76 } else if (name.equals(getIdName(Id_toString))) {
78 return date_format(t, FORMATSPEC_FULL);
80 } else if (name.equals(getIdName(Id_toTimeString))) {
82 return date_format(t, FORMATSPEC_TIME);
84 } else if (name.equals(getIdName(Id_toDateString))) {
86 return date_format(t, FORMATSPEC_DATE);
88 } else if (name.equals(getIdName(Id_toLocaleString))) {
90 return jsJSFunction_toLocaleString(t);
92 } else if (name.equals(getIdName(Id_toLocaleTimeString))) {
94 return jsJSFunction_toLocaleTimeString(t);
96 } else if (name.equals(getIdName(Id_toLocaleDateString))) {
98 return jsJSFunction_toLocaleDateString(t);
100 } else if (name.equals(getIdName(Id_toUTCString))) {
102 return jsJSFunction_toUTCString(t);
104 } else if (name.equals(getIdName(Id_valueOf))) {
105 return new Double(this.date);
107 } else if (name.equals(getIdName(Id_getTime))) {
108 return new Double(this.date);
110 } else if (name.equals(getIdName(Id_getYear))) {
112 t = jsJSFunction_getYear(t);
113 return new Double(t);
115 } else if (name.equals(getIdName(Id_getFullYear))) {
117 t = YearFromTime(LocalTime(t));
118 return new Double(t);
120 } else if (name.equals(getIdName(Id_getUTCFullYear))) {
123 return new Double(t);
125 } else if (name.equals(getIdName(Id_getMonth))) {
127 t = MonthFromTime(LocalTime(t));
128 return new Double(t);
130 } else if (name.equals(getIdName(Id_getUTCMonth))) {
132 t = MonthFromTime(t);
133 return new Double(t);
135 } else if (name.equals(getIdName(Id_getDate))) {
137 t = DateFromTime(LocalTime(t));
138 return new Double(t);
140 } else if (name.equals(getIdName(Id_getUTCDate))) {
143 return new Double(t);
145 } else if (name.equals(getIdName(Id_getDay))) {
147 t = WeekDay(LocalTime(t));
148 return new Double(t);
150 } else if (name.equals(getIdName(Id_getUTCDay))) {
153 return new Double(t);
155 } else if (name.equals(getIdName(Id_getHours))) {
157 t = HourFromTime(LocalTime(t));
158 return new Double(t);
160 } else if (name.equals(getIdName(Id_getUTCHours))) {
163 return new Double(t);
165 } else if (name.equals(getIdName(Id_getMinutes))) {
167 t = MinFromTime(LocalTime(t));
168 return new Double(t);
170 } else if (name.equals(getIdName(Id_getUTCMinutes))) {
173 return new Double(t);
175 } else if (name.equals(getIdName(Id_getSeconds))) {
177 t = SecFromTime(LocalTime(t));
178 return new Double(t);
180 } else if (name.equals(getIdName(Id_getUTCSeconds))) {
183 return new Double(t);
185 } else if (name.equals(getIdName(Id_getMilliseconds))) {
187 t = msFromTime(LocalTime(t));
188 return new Double(t);
190 } else if (name.equals(getIdName(Id_getUTCMilliseconds))) {
193 return new Double(t);
195 } else if (name.equals(getIdName(Id_getTimezoneOffset))) {
197 t = jsJSFunction_getTimezoneOffset(t);
198 return new Double(t);
200 } else if (name.equals(getIdName(Id_setTime))) {
201 return new Double(this.jsJSFunction_setTime(_toNumber(args, 0)));
203 } else if (name.equals(getIdName(Id_setMilliseconds))) {
204 return new Double(this.
205 makeTime(args, 1, true));
207 } else if (name.equals(getIdName(Id_setUTCMilliseconds))) {
208 return new Double(this.
209 makeTime(args, 1, false));
211 } else if (name.equals(getIdName(Id_setSeconds))) {
212 return new Double(this.
213 makeTime(args, 2, true));
215 } else if (name.equals(getIdName(Id_setUTCSeconds))) {
216 return new Double(this.
217 makeTime(args, 2, false));
219 } else if (name.equals(getIdName(Id_setMinutes))) {
220 return new Double(this.
221 makeTime(args, 3, true));
223 } else if (name.equals(getIdName(Id_setUTCMinutes))) {
224 return new Double(this.
225 makeTime(args, 3, false));
227 } else if (name.equals(getIdName(Id_setHours))) {
228 return new Double(this.
229 makeTime(args, 4, true));
231 } else if (name.equals(getIdName(Id_setUTCHours))) {
232 return new Double(this.
233 makeTime(args, 4, false));
235 } else if (name.equals(getIdName(Id_setDate))) {
236 return new Double(this.
237 makeDate(args, 1, true));
239 } else if (name.equals(getIdName(Id_setUTCDate))) {
240 return new Double(this.
241 makeDate(args, 1, false));
243 } else if (name.equals(getIdName(Id_setMonth))) {
244 return new Double(this.
245 makeDate(args, 2, true));
247 } else if (name.equals(getIdName(Id_setUTCMonth))) {
248 return new Double(this.
249 makeDate(args, 2, false));
251 } else if (name.equals(getIdName(Id_setFullYear))) {
252 return new Double(this.
253 makeDate(args, 3, true));
255 } else if (name.equals(getIdName(Id_setUTCFullYear))) {
256 return new Double(this.
257 makeDate(args, 3, false));
259 } else if (name.equals(getIdName(Id_setYear))) {
260 return new Double(this.
261 jsJSFunction_setYear(_toNumber(args, 0)));
266 /* ECMA helper functions */
268 private static final double HalfTimeDomain = 8.64e15;
269 private static final double HoursPerDay = 24.0;
270 private static final double MinutesPerHour = 60.0;
271 private static final double SecondsPerMinute = 60.0;
272 private static final double msPerSecond = 1000.0;
273 private static final double MinutesPerDay = (HoursPerDay * MinutesPerHour);
274 private static final double SecondsPerDay = (MinutesPerDay * SecondsPerMinute);
275 private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute);
276 private static final double msPerDay = (SecondsPerDay * msPerSecond);
277 private static final double msPerHour = (SecondsPerHour * msPerSecond);
278 private static final double msPerMinute = (SecondsPerMinute * msPerSecond);
280 private static double Day(double t) {
281 return java.lang.Math.floor(t / msPerDay);
284 private static double TimeWithinDay(double t) {
286 result = t % msPerDay;
292 private static int DaysInYear(int y) {
293 if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
300 /* math here has to be f.p, because we need
301 * floor((1968 - 1969) / 4) == -1
303 private static double DayFromYear(double y) {
304 return ((365 * ((y)-1970) + java.lang.Math.floor(((y)-1969)/4.0)
305 - java.lang.Math.floor(((y)-1901)/100.0) + java.lang.Math.floor(((y)-1601)/400.0)));
308 private static double TimeFromYear(double y) {
309 return DayFromYear(y) * msPerDay;
312 private static int YearFromTime(double t) {
313 int lo = (int) java.lang.Math.floor((t / msPerDay) / 366) + 1970;
314 int hi = (int) java.lang.Math.floor((t / msPerDay) / 365) + 1970;
317 /* above doesn't work for negative dates... */
324 /* Use a simple binary search algorithm to find the right
325 year. This seems like brute force... but the computation
326 of hi and lo years above lands within one year of the
327 correct answer for years within a thousand years of
328 1970; the loop below only requires six iterations
332 if (TimeFromYear(mid) > t) {
335 if (TimeFromYear(mid) <= t) {
337 if (TimeFromYear(temp) > t) {
347 private static boolean InLeapYear(double t) {
348 return DaysInYear(YearFromTime(t)) == 366;
351 private static int DayWithinYear(double t) {
352 int year = YearFromTime(t);
353 return (int) (Day(t) - DayFromYear(year));
356 * The following array contains the day of year for the first day of
357 * each month, where index 0 is January, and day 0 is January 1.
360 private static double DayFromMonth(int m, boolean leap) {
363 if (m >= 7) { day += m / 2 - 1; }
364 else if (m >= 2) { day += (m - 1) / 2 - 1; }
367 if (leap && m >= 2) { ++day; }
372 private static int MonthFromTime(double t) {
375 d = DayWithinYear(t);
380 // Originally coded as step += (InLeapYear(t) ? 29 : 28);
381 // but some jits always returned 28!
389 if (d < (step += 31))
391 if (d < (step += 30))
393 if (d < (step += 31))
395 if (d < (step += 30))
397 if (d < (step += 31))
399 if (d < (step += 31))
401 if (d < (step += 30))
403 if (d < (step += 31))
405 if (d < (step += 30))
410 private static int DateFromTime(double t) {
413 d = DayWithinYear(t);
414 if (d <= (next = 30))
418 // Originally coded as next += (InLeapYear(t) ? 29 : 28);
419 // but some jits always returned 28!
428 if (d <= (next += 31))
431 if (d <= (next += 30))
434 if (d <= (next += 31))
437 if (d <= (next += 30))
440 if (d <= (next += 31))
443 if (d <= (next += 31))
446 if (d <= (next += 30))
449 if (d <= (next += 31))
452 if (d <= (next += 30))
459 private static int WeekDay(double t) {
468 private static double Now() {
469 return (double) System.currentTimeMillis();
472 /* Should be possible to determine the need for this dynamically
473 * if we go with the workaround... I'm not using it now, because I
474 * can't think of any clean way to make toLocaleString() and the
475 * time zone (comment) in toString match the generated string
476 * values. Currently it's wrong-but-consistent in all but the
477 * most recent betas of the JRE - seems to work in 1.1.7.
479 private final static boolean TZO_WORKAROUND = false;
480 private static double DaylightSavingTA(double t) {
481 if (!TZO_WORKAROUND) {
482 java.util.Date date = new java.util.Date((long) t);
483 if (thisTimeZone.inDaylightTime(date))
488 /* Use getOffset if inDaylightTime() is broken, because it
489 * seems to work acceptably. We don't switch over to it
490 * entirely, because it requires (expensive) exploded date arguments,
491 * and the api makes it impossible to handle dst
492 * changeovers cleanly.
495 // Hardcode the assumption that the changeover always
496 // happens at 2:00 AM:
497 t += LocalTZA + (HourFromTime(t) <= 2 ? msPerHour : 0);
499 int year = YearFromTime(t);
500 double offset = thisTimeZone.getOffset(year > 0 ? 1 : 0,
505 (int)TimeWithinDay(t));
507 if ((offset - LocalTZA) != 0)
511 // return offset - LocalTZA;
515 private static double LocalTime(double t) {
516 return t + LocalTZA + DaylightSavingTA(t);
519 public static double internalUTC(double t) {
520 return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
523 private static int HourFromTime(double t) {
525 result = java.lang.Math.floor(t / msPerHour) % HoursPerDay;
527 result += HoursPerDay;
531 private static int MinFromTime(double t) {
533 result = java.lang.Math.floor(t / msPerMinute) % MinutesPerHour;
535 result += MinutesPerHour;
539 private static int SecFromTime(double t) {
541 result = java.lang.Math.floor(t / msPerSecond) % SecondsPerMinute;
543 result += SecondsPerMinute;
547 private static int msFromTime(double t) {
549 result = t % msPerSecond;
551 result += msPerSecond;
555 private static double MakeTime(double hour, double min,
556 double sec, double ms)
558 return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec)
562 private static double MakeDay(double year, double month, double date) {
568 year += java.lang.Math.floor(month / 12);
574 leap = (DaysInYear((int) year) == 366);
576 yearday = java.lang.Math.floor(TimeFromYear(year) / msPerDay);
577 monthday = DayFromMonth((int) month, leap);
585 private static double MakeDate(double day, double time) {
586 return day * msPerDay + time;
589 private static double TimeClip(double d) {
591 d == Double.POSITIVE_INFINITY ||
592 d == Double.NEGATIVE_INFINITY ||
593 java.lang.Math.abs(d) > HalfTimeDomain)
598 return java.lang.Math.floor(d + 0.);
600 return java.lang.Math.ceil(d + 0.);
603 /* end of ECMA helper functions */
605 /* find UTC time from given date... no 1900 correction! */
606 public static double date_msecFromDate(double year, double mon,
607 double mday, double hour,
608 double min, double sec,
615 day = MakeDay(year, mon, mday);
616 time = MakeTime(hour, min, sec, msec);
617 result = MakeDate(day, time);
622 private static final int MAXARGS = 7;
623 private static double jsStaticJSFunction_UTC(Object[] args) {
624 double array[] = new double[MAXARGS];
628 for (loop = 0; loop < MAXARGS; loop++) {
629 if (loop < args.length) {
630 d = _toNumber(args[loop]);
631 if (d != d || Double.isInfinite(d)) {
634 array[loop] = toDouble(args[loop]);
640 /* adjust 2-digit years into the 20th century */
641 if (array[0] >= 0 && array[0] <= 99)
644 /* if we got a 0 for 'date' (which is out of range)
645 * pretend it's a 1. (So Date.UTC(1972, 5) works) */
649 d = date_msecFromDate(array[0], array[1], array[2],
650 array[3], array[4], array[5], array[6]);
653 // return new Double(d);
657 * Use ported code from jsdate.c rather than the locale-specific
658 * date-parsing code from Java, to keep js and rhino consistent.
659 * Is this the right strategy?
662 /* for use by date_parse */
664 /* replace this with byte arrays? Cheaper? */
665 private static String wtb[] = {
667 "monday", "tuesday", "wednesday", "thursday", "friday",
668 "saturday", "sunday",
669 "january", "february", "march", "april", "may", "june",
670 "july", "august", "september", "october", "november", "december",
671 "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
672 "mst", "mdt", "pst", "pdt"
673 /* time zone table needs to be expanded */
676 private static int ttb[] = {
677 -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */
678 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
679 10000 + 0, 10000 + 0, 10000 + 0, /* UT/UTC */
680 10000 + 5 * 60, 10000 + 4 * 60, /* EDT */
681 10000 + 6 * 60, 10000 + 5 * 60,
682 10000 + 7 * 60, 10000 + 6 * 60,
683 10000 + 8 * 60, 10000 + 7 * 60
686 /* helper for date_parse */
687 private static boolean date_regionMatches(String s1, int s1off,
688 String s2, int s2off,
691 boolean result = false;
692 /* return true if matches, otherwise, false */
693 int s1len = s1.length();
694 int s2len = s2.length();
696 while (count > 0 && s1off < s1len && s2off < s2len) {
697 if (Character.toLowerCase(s1.charAt(s1off)) !=
698 Character.toLowerCase(s2.charAt(s2off)))
711 private static double date_parseString(String s) {
724 double tzoffset = -1;
727 boolean seenplusminus = false;
729 if (s == null) // ??? Will s be null?
735 if (c <= ' ' || c == ',' || c == '-') {
738 if (c == '-' && '0' <= si && si <= '9') {
744 if (c == '(') { /* comments) */
757 if ('0' <= c && c <= '9') {
759 while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {
760 n = n * 10 + c - '0';
764 /* allow TZA before the year, so
765 * 'Wed Nov 05 21:49:11 GMT-0800 1997'
768 /* uses of seenplusminus allow : in TZA, so Java
769 * no-timezone style of GMT+4:30 works
771 if ((prevc == '+' || prevc == '-')/* && year>=0 */) {
772 /* make ':' case below change tzoffset */
773 seenplusminus = true;
777 n = n * 60; /* EG. "GMT-3" */
779 n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
780 if (prevc == '+') /* plus means east of GMT */
782 if (tzoffset != 0 && tzoffset != -1)
785 } else if (n >= 70 ||
786 (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {
789 else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
790 year = n < 100 ? n + 1900 : n;
793 } else if (c == ':') {
800 } else if (c == '/') {
807 } else if (i < limit && c != ',' && c > ' ' && c != '-') {
809 } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */
814 } else if (hour >= 0 && min < 0) {
816 } else if (min >= 0 && sec < 0) {
818 } else if (mday < 0) {
824 } else if (c == '/' || c == ':' || c == '+' || c == '-') {
831 if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
837 for (k = wtb.length; --k >= 0;)
838 if (date_regionMatches(wtb[k], 0, s, st, i-st)) {
843 * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
844 * 12:30, instead of blindly adding 12 if PM.
846 if (hour > 12 || hour < 0) {
849 if (action == -1 && hour == 12) { // am
851 } else if (action == -2 && hour != 12) {// pm
855 } else if (action <= 13) { /* month! */
857 mon = /*byte*/ (action - 2);
862 tzoffset = action - 10000;
872 if (year < 0 || mon < 0 || mday < 0)
880 if (tzoffset == -1) { /* no time zone specified, have to use local */
882 time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
883 return internalUTC(time);
886 msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
887 msec += tzoffset * msPerMinute;
891 private static double jsStaticJSFunction_parse(String s) {
892 return date_parseString(s);
895 private static final int FORMATSPEC_FULL = 0;
896 private static final int FORMATSPEC_DATE = 1;
897 private static final int FORMATSPEC_TIME = 2;
899 private static String date_format(double t, int format) {
901 return jsJSFunction_NaN_date_str;
903 StringBuffer result = new StringBuffer(60);
904 double local = LocalTime(t);
906 /* offset from GMT in minutes. The offset includes daylight savings,
908 int minutes = (int) java.lang.Math.floor((LocalTZA + DaylightSavingTA(t))
910 /* map 510 minutes to 0830 hours */
911 int offset = (minutes / 60) * 100 + minutes % 60;
913 String dateStr = Integer.toString(DateFromTime(local));
914 String hourStr = Integer.toString(HourFromTime(local));
915 String minStr = Integer.toString(MinFromTime(local));
916 String secStr = Integer.toString(SecFromTime(local));
917 String offsetStr = Integer.toString(offset > 0 ? offset : -offset);
918 int year = YearFromTime(local);
919 String yearStr = Integer.toString(year > 0 ? year : -year);
921 /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */
922 /* Tue Oct 31 2000 */
923 /* 09:41:40 GMT-0800 (PST) */
925 if (format != FORMATSPEC_TIME) {
926 result.append(days[WeekDay(local)]);
928 result.append(months[MonthFromTime(local)]);
929 if (dateStr.length() == 1)
933 result.append(dateStr);
937 if (format != FORMATSPEC_DATE) {
938 if (hourStr.length() == 1)
940 result.append(hourStr);
941 if (minStr.length() == 1)
945 result.append(minStr);
946 if (secStr.length() == 1)
950 result.append(secStr);
952 result.append(" GMT+");
954 result.append(" GMT-");
955 for (int i = offsetStr.length(); i < 4; i++)
957 result.append(offsetStr);
959 if (timeZoneFormatter == null)
960 timeZoneFormatter = new java.text.SimpleDateFormat("zzz");
962 if (timeZoneFormatter != null) {
964 java.util.Date date = new java.util.Date((long) t);
965 result.append(timeZoneFormatter.format(date));
968 if (format != FORMATSPEC_TIME)
972 if (format != FORMATSPEC_TIME) {
975 for (int i = yearStr.length(); i < 4; i++)
977 result.append(yearStr);
980 return result.toString();
983 private static double _toNumber(Object o) { return JS.toDouble(o); }
984 private static double _toNumber(Object[] o, int index) { return JS.toDouble(o[index]); }
985 private static double toDouble(double d) { return d; }
987 public JSDate(JSArray args_) {
988 Object[] args = new Object[args_.length()];
989 for(int i=0; i<args.length; i++) args[i] = args_.elementAt(i);
992 // if called as a constructor with no args,
993 // return a new Date with the current time.
994 if (args.length == 0) {
999 // if called with just one arg -
1000 if (args.length == 1) {
1002 if (args[0] instanceof JS)
1003 args[0] = ((JS) args[0]).toString();
1004 if (!(args[0] instanceof String)) {
1005 // if it's not a string, use it as a millisecond date
1006 date = _toNumber(args[0]);
1008 // it's a string; parse it.
1009 String str = (String) args[0];
1010 date = date_parseString(str);
1012 obj.date = TimeClip(date);
1016 // multiple arguments; year, month, day etc.
1017 double array[] = new double[MAXARGS];
1021 for (loop = 0; loop < MAXARGS; loop++) {
1022 if (loop < args.length) {
1023 d = _toNumber(args[loop]);
1025 if (d != d || Double.isInfinite(d)) {
1026 obj.date = Double.NaN;
1029 array[loop] = toDouble(args[loop]);
1035 /* adjust 2-digit years into the 20th century */
1036 if (array[0] >= 0 && array[0] <= 99)
1039 /* if we got a 0 for 'date' (which is out of range)
1040 * pretend it's a 1 */
1044 double day = MakeDay(array[0], array[1], array[2]);
1045 double time = MakeTime(array[3], array[4], array[5], array[6]);
1046 time = MakeDate(day, time);
1047 time = internalUTC(time);
1048 obj.date = TimeClip(time);
1053 /* constants for toString, toUTCString */
1054 private static String jsJSFunction_NaN_date_str = "Invalid Date";
1056 private static String[] days = {
1057 "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
1060 private static String[] months = {
1061 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1062 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1065 private static String toLocale_helper(double t,
1066 java.text.DateFormat formatter)
1069 return jsJSFunction_NaN_date_str;
1071 java.util.Date tempdate = new java.util.Date((long) t);
1072 return formatter.format(tempdate);
1075 private static String jsJSFunction_toLocaleString(double date) {
1076 if (localeDateTimeFormatter == null)
1077 localeDateTimeFormatter =
1078 DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
1080 return toLocale_helper(date, localeDateTimeFormatter);
1083 private static String jsJSFunction_toLocaleTimeString(double date) {
1084 if (localeTimeFormatter == null)
1085 localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG);
1087 return toLocale_helper(date, localeTimeFormatter);
1090 private static String jsJSFunction_toLocaleDateString(double date) {
1091 if (localeDateFormatter == null)
1092 localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG);
1094 return toLocale_helper(date, localeDateFormatter);
1097 private static String jsJSFunction_toUTCString(double date) {
1098 StringBuffer result = new StringBuffer(60);
1100 String dateStr = Integer.toString(DateFromTime(date));
1101 String hourStr = Integer.toString(HourFromTime(date));
1102 String minStr = Integer.toString(MinFromTime(date));
1103 String secStr = Integer.toString(SecFromTime(date));
1104 int year = YearFromTime(date);
1105 String yearStr = Integer.toString(year > 0 ? year : -year);
1107 result.append(days[WeekDay(date)]);
1108 result.append(", ");
1109 if (dateStr.length() == 1)
1111 result.append(dateStr);
1113 result.append(months[MonthFromTime(date)]);
1115 result.append(" -");
1119 for (i = yearStr.length(); i < 4; i++)
1121 result.append(yearStr);
1123 if (hourStr.length() == 1)
1124 result.append(" 0");
1127 result.append(hourStr);
1128 if (minStr.length() == 1)
1129 result.append(":0");
1132 result.append(minStr);
1133 if (secStr.length() == 1)
1134 result.append(":0");
1137 result.append(secStr);
1139 result.append(" GMT");
1140 return result.toString();
1143 private static double jsJSFunction_getYear(double date) {
1144 int result = YearFromTime(LocalTime(date));
1149 private static double jsJSFunction_getTimezoneOffset(double date) {
1150 return (date - LocalTime(date)) / msPerMinute;
1153 public double jsJSFunction_setTime(double time) {
1154 this.date = TimeClip(time);
1158 private double makeTime(Object[] args, int maxargs, boolean local) {
1160 double conv[] = new double[4];
1161 double hour, min, sec, msec;
1162 double lorutime; /* Local or UTC version of date */
1167 double date = this.date;
1169 /* just return NaN if the date is already NaN */
1173 /* Satisfy the ECMA rule that if a function is called with
1174 * fewer arguments than the specified formal arguments, the
1175 * remaining arguments are set to undefined. Seems like all
1176 * the Date.setWhatever functions in ECMA are only varargs
1177 * beyond the first argument; this should be set to undefined
1178 * if it's not given. This means that "d = new Date();
1179 * d.setMilliseconds()" returns NaN. Blech.
1181 if (args.length == 0)
1182 args = new Object[] { null };
1184 for (i = 0; i < args.length && i < maxargs; i++) {
1185 conv[i] = _toNumber(args[i]);
1187 // limit checks that happen in MakeTime in ECMA.
1188 if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {
1189 this.date = Double.NaN;
1192 conv[i] = toDouble(conv[i]);
1196 lorutime = LocalTime(date);
1201 int stop = args.length;
1203 if (maxargs >= 4 && i < stop)
1206 hour = HourFromTime(lorutime);
1208 if (maxargs >= 3 && i < stop)
1211 min = MinFromTime(lorutime);
1213 if (maxargs >= 2 && i < stop)
1216 sec = SecFromTime(lorutime);
1218 if (maxargs >= 1 && i < stop)
1221 msec = msFromTime(lorutime);
1223 time = MakeTime(hour, min, sec, msec);
1224 result = MakeDate(Day(lorutime), time);
1227 result = internalUTC(result);
1228 date = TimeClip(result);
1234 private double jsJSFunction_setHours(Object[] args) {
1235 return makeTime(args, 4, true);
1238 private double jsJSFunction_setUTCHours(Object[] args) {
1239 return makeTime(args, 4, false);
1242 private double makeDate(Object[] args, int maxargs, boolean local) {
1244 double conv[] = new double[3];
1245 double year, month, day;
1246 double lorutime; /* local or UTC version of date */
1249 double date = this.date;
1251 /* See arg padding comment in makeTime.*/
1252 if (args.length == 0)
1253 args = new Object[] { null };
1255 for (i = 0; i < args.length && i < maxargs; i++) {
1256 conv[i] = _toNumber(args[i]);
1258 // limit checks that happen in MakeDate in ECMA.
1259 if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {
1260 this.date = Double.NaN;
1263 conv[i] = toDouble(conv[i]);
1266 /* return NaN if date is NaN and we're not setting the year,
1267 * If we are, use 0 as the time. */
1269 if (args.length < 3) {
1276 lorutime = LocalTime(date);
1282 int stop = args.length;
1284 if (maxargs >= 3 && i < stop)
1287 year = YearFromTime(lorutime);
1289 if (maxargs >= 2 && i < stop)
1292 month = MonthFromTime(lorutime);
1294 if (maxargs >= 1 && i < stop)
1297 day = DateFromTime(lorutime);
1299 day = MakeDay(year, month, day); /* day within year */
1300 result = MakeDate(day, TimeWithinDay(lorutime));
1303 result = internalUTC(result);
1305 date = TimeClip(result);
1311 private double jsJSFunction_setYear(double year) {
1313 if (year != year || Double.isInfinite(year)) {
1314 this.date = Double.NaN;
1318 if (this.date != this.date) {
1321 this.date = LocalTime(this.date);
1324 if (year >= 0 && year <= 99)
1327 day = MakeDay(year, MonthFromTime(this.date), DateFromTime(this.date));
1328 result = MakeDate(day, TimeWithinDay(this.date));
1329 result = internalUTC(result);
1331 this.date = TimeClip(result);
1335 protected String getIdName(int id) {
1337 case ConstructorId_UTC: return "UTC";
1338 case ConstructorId_parse: return "parse";
1339 case Id_constructor: return "constructor";
1340 case Id_toString: return "toString";
1341 case Id_toTimeString: return "toTimeString";
1342 case Id_toDateString: return "toDateString";
1343 case Id_toLocaleString: return "toLocaleString";
1344 case Id_toLocaleTimeString: return "toLocaleTimeString";
1345 case Id_toLocaleDateString: return "toLocaleDateString";
1346 case Id_toUTCString: return "toUTCString";
1347 case Id_valueOf: return "valueOf";
1348 case Id_getTime: return "getTime";
1349 case Id_getYear: return "getYear";
1350 case Id_getFullYear: return "getFullYear";
1351 case Id_getUTCFullYear: return "getUTCFullYear";
1352 case Id_getMonth: return "getMonth";
1353 case Id_getUTCMonth: return "getUTCMonth";
1354 case Id_getDate: return "getDate";
1355 case Id_getUTCDate: return "getUTCDate";
1356 case Id_getDay: return "getDay";
1357 case Id_getUTCDay: return "getUTCDay";
1358 case Id_getHours: return "getHours";
1359 case Id_getUTCHours: return "getUTCHours";
1360 case Id_getMinutes: return "getMinutes";
1361 case Id_getUTCMinutes: return "getUTCMinutes";
1362 case Id_getSeconds: return "getSeconds";
1363 case Id_getUTCSeconds: return "getUTCSeconds";
1364 case Id_getMilliseconds: return "getMilliseconds";
1365 case Id_getUTCMilliseconds: return "getUTCMilliseconds";
1366 case Id_getTimezoneOffset: return "getTimezoneOffset";
1367 case Id_setTime: return "setTime";
1368 case Id_setMilliseconds: return "setMilliseconds";
1369 case Id_setUTCMilliseconds: return "setUTCMilliseconds";
1370 case Id_setSeconds: return "setSeconds";
1371 case Id_setUTCSeconds: return "setUTCSeconds";
1372 case Id_setMinutes: return "setMinutes";
1373 case Id_setUTCMinutes: return "setUTCMinutes";
1374 case Id_setHours: return "setHours";
1375 case Id_setUTCHours: return "setUTCHours";
1376 case Id_setDate: return "setDate";
1377 case Id_setUTCDate: return "setUTCDate";
1378 case Id_setMonth: return "setMonth";
1379 case Id_setUTCMonth: return "setUTCMonth";
1380 case Id_setFullYear: return "setFullYear";
1381 case Id_setUTCFullYear: return "setUTCFullYear";
1382 case Id_setYear: return "setYear";
1389 protected int mapNameToId(String s) {
1391 // #generated# Last update: 2001-04-22 23:46:59 CEST
1392 L0: { id = 0; String X = null; int c;
1393 L: switch (s.length()) {
1394 case 6: X="getDay";id=Id_getDay; break L;
1395 case 7: switch (s.charAt(3)) {
1396 case 'D': c=s.charAt(0);
1397 if (c=='g') { X="getDate";id=Id_getDate; }
1398 else if (c=='s') { X="setDate";id=Id_setDate; }
1400 case 'T': c=s.charAt(0);
1401 if (c=='g') { X="getTime";id=Id_getTime; }
1402 else if (c=='s') { X="setTime";id=Id_setTime; }
1404 case 'Y': c=s.charAt(0);
1405 if (c=='g') { X="getYear";id=Id_getYear; }
1406 else if (c=='s') { X="setYear";id=Id_setYear; }
1408 case 'u': X="valueOf";id=Id_valueOf; break L;
1410 case 8: c=s.charAt(0);
1413 if (c=='h') { X="getMonth";id=Id_getMonth; }
1414 else if (c=='s') { X="getHours";id=Id_getHours; }
1418 if (c=='h') { X="setMonth";id=Id_setMonth; }
1419 else if (c=='s') { X="setHours";id=Id_setHours; }
1421 else if (c=='t') { X="toString";id=Id_toString; }
1423 case 9: X="getUTCDay";id=Id_getUTCDay; break L;
1424 case 10: c=s.charAt(3);
1427 if (c=='g') { X="getMinutes";id=Id_getMinutes; }
1428 else if (c=='s') { X="setMinutes";id=Id_setMinutes; }
1432 if (c=='g') { X="getSeconds";id=Id_getSeconds; }
1433 else if (c=='s') { X="setSeconds";id=Id_setSeconds; }
1437 if (c=='g') { X="getUTCDate";id=Id_getUTCDate; }
1438 else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; }
1441 case 11: switch (s.charAt(3)) {
1442 case 'F': c=s.charAt(0);
1443 if (c=='g') { X="getFullYear";id=Id_getFullYear; }
1444 else if (c=='s') { X="setFullYear";id=Id_setFullYear; }
1446 case 'M': X="toGMTString";id=Id_toGMTString; break L;
1447 case 'T': X="toUTCString";id=Id_toUTCString; break L;
1448 case 'U': c=s.charAt(0);
1451 if (c=='r') { X="getUTCHours";id=Id_getUTCHours; }
1452 else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; }
1456 if (c=='r') { X="setUTCHours";id=Id_setUTCHours; }
1457 else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; }
1460 case 's': X="constructor";id=Id_constructor; break L;
1462 case 12: c=s.charAt(2);
1463 if (c=='D') { X="toDateString";id=Id_toDateString; }
1464 else if (c=='T') { X="toTimeString";id=Id_toTimeString; }
1466 case 13: c=s.charAt(0);
1469 if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; }
1470 else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; }
1474 if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; }
1475 else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; }
1478 case 14: c=s.charAt(0);
1479 if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; }
1480 else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; }
1481 else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; }
1483 case 15: c=s.charAt(0);
1484 if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; }
1485 else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; }
1487 case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L;
1488 case 18: c=s.charAt(0);
1489 if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; }
1490 else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; }
1493 if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; }
1494 else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; }
1498 if (X!=null && X!=s && !X.equals(s)) id = 0;
1504 private static final int
1505 ConstructorId_UTC = -2,
1506 ConstructorId_parse = -1,
1510 Id_toTimeString = 3,
1511 Id_toDateString = 4,
1512 Id_toLocaleString = 5,
1513 Id_toLocaleTimeString = 6,
1514 Id_toLocaleDateString = 7,
1519 Id_getFullYear = 12,
1520 Id_getUTCFullYear = 13,
1522 Id_getUTCMonth = 15,
1528 Id_getUTCHours = 21,
1530 Id_getUTCMinutes = 23,
1532 Id_getUTCSeconds = 25,
1533 Id_getMilliseconds = 26,
1534 Id_getUTCMilliseconds = 27,
1535 Id_getTimezoneOffset = 28,
1537 Id_setMilliseconds = 30,
1538 Id_setUTCMilliseconds = 31,
1540 Id_setUTCSeconds = 33,
1542 Id_setUTCMinutes = 35,
1544 Id_setUTCHours = 37,
1548 Id_setUTCMonth = 41,
1549 Id_setFullYear = 42,
1550 Id_setUTCFullYear = 43,
1553 MAX_PROTOTYPE_ID = 44;
1555 private static final int
1556 Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6
1560 private static java.util.TimeZone thisTimeZone;
1561 private static double LocalTZA;
1562 private static java.text.DateFormat timeZoneFormatter;
1563 private static java.text.DateFormat localeDateTimeFormatter;
1564 private static java.text.DateFormat localeDateFormatter;
1565 private static java.text.DateFormat localeTimeFormatter;
1567 private double date;
1569 public long getRawTime() { return (long)this.date; }