--- /dev/null
+/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-\r
+ *\r
+ * The contents of this file are subject to the Netscape Public\r
+ * License Version 1.1 (the "License"); you may not use this file\r
+ * except in compliance with the License. You may obtain a copy of\r
+ * the License at http://www.mozilla.org/NPL/\r
+ *\r
+ * Software distributed under the License is distributed on an "AS\r
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr\r
+ * implied. See the License for the specific language governing\r
+ * rights and limitations under the License.\r
+ *\r
+ * The Original Code is Rhino code, released\r
+ * May 6, 1999.\r
+ *\r
+ * The Initial Developer of the Original Code is Netscape\r
+ * Communications Corporation. Portions created by Netscape are\r
+ * Copyright (C) 1997-1999 Netscape Communications Corporation. All\r
+ * Rights Reserved.\r
+ *\r
+ * Contributor(s):\r
+ * Norris Boyd\r
+ * Mike McCabe\r
+ *\r
+ * Alternatively, the contents of this file may be used under the\r
+ * terms of the GNU Public License (the "GPL"), in which case the\r
+ * provisions of the GPL are applicable instead of those above.\r
+ * If you wish to allow use of your version of this file only\r
+ * under the terms of the GPL and not to allow others to use your\r
+ * version of this file under the NPL, indicate your decision by\r
+ * deleting the provisions above and replace them with the notice\r
+ * and other provisions required by the GPL. If you do not delete\r
+ * the provisions above, a recipient may use your version of this\r
+ * file under either the NPL or the GPL.\r
+ */\r
+\r
+package org.mozilla.javascript;\r
+\r
+import java.util.Date;\r
+import java.util.TimeZone;\r
+import java.util.Locale;\r
+import java.text.NumberFormat;\r
+import java.text.DateFormat;\r
+import java.text.SimpleDateFormat;\r
+\r
+/**\r
+ * This class implements the Date native object.\r
+ * See ECMA 15.9.\r
+ * @author Mike McCabe\r
+ */\r
+public class NativeDate extends IdScriptable {\r
+\r
+ public static void init(Context cx, Scriptable scope, boolean sealed) {\r
+ NativeDate obj = new NativeDate();\r
+ obj.prototypeFlag = true;\r
+ \r
+ // Set the value of the prototype Date to NaN ('invalid date');\r
+ obj.date = ScriptRuntime.NaN;\r
+\r
+ obj.addAsPrototype(MAX_PROTOTYPE_ID, cx, scope, sealed);\r
+ }\r
+ \r
+ public NativeDate() {\r
+ if (thisTimeZone == null) {\r
+ // j.u.TimeZone is synchronized, so setting class statics from it\r
+ // should be OK.\r
+ thisTimeZone = java.util.TimeZone.getDefault();\r
+ LocalTZA = thisTimeZone.getRawOffset();\r
+ }\r
+ }\r
+\r
+ public String getClassName() {\r
+ return "Date";\r
+ }\r
+\r
+ public Object getDefaultValue(Class typeHint) {\r
+ if (typeHint == null)\r
+ typeHint = ScriptRuntime.StringClass;\r
+ return super.getDefaultValue(typeHint);\r
+ }\r
+\r
+ protected void fillConstructorProperties\r
+ (Context cx, IdFunction ctor, boolean sealed)\r
+ {\r
+ addIdFunctionProperty(ctor, ConstructorId_UTC, sealed);\r
+ addIdFunctionProperty(ctor, ConstructorId_parse, sealed);\r
+ super.fillConstructorProperties(cx, ctor, sealed);\r
+ }\r
+\r
+ public int methodArity(int methodId) {\r
+ if (prototypeFlag) {\r
+ switch (methodId) {\r
+ case ConstructorId_UTC: return 1;\r
+ case ConstructorId_parse: return 1;\r
+ case Id_constructor: return 1; \r
+ case Id_toString: return 0;\r
+ case Id_toTimeString: return 0;\r
+ case Id_toDateString: return 0;\r
+ case Id_toLocaleString: return 0;\r
+ case Id_toLocaleTimeString: return 0;\r
+ case Id_toLocaleDateString: return 0;\r
+ case Id_toUTCString: return 0;\r
+ case Id_valueOf: return 0;\r
+ case Id_getTime: return 0;\r
+ case Id_getYear: return 0;\r
+ case Id_getFullYear: return 0;\r
+ case Id_getUTCFullYear: return 0;\r
+ case Id_getMonth: return 0;\r
+ case Id_getUTCMonth: return 0;\r
+ case Id_getDate: return 0;\r
+ case Id_getUTCDate: return 0;\r
+ case Id_getDay: return 0;\r
+ case Id_getUTCDay: return 0;\r
+ case Id_getHours: return 0;\r
+ case Id_getUTCHours: return 0;\r
+ case Id_getMinutes: return 0;\r
+ case Id_getUTCMinutes: return 0;\r
+ case Id_getSeconds: return 0;\r
+ case Id_getUTCSeconds: return 0;\r
+ case Id_getMilliseconds: return 0;\r
+ case Id_getUTCMilliseconds: return 0;\r
+ case Id_getTimezoneOffset: return 0;\r
+ case Id_setTime: return 1;\r
+ case Id_setMilliseconds: return 1;\r
+ case Id_setUTCMilliseconds: return 1;\r
+ case Id_setSeconds: return 2;\r
+ case Id_setUTCSeconds: return 2;\r
+ case Id_setMinutes: return 3;\r
+ case Id_setUTCMinutes: return 3;\r
+ case Id_setHours: return 4;\r
+ case Id_setUTCHours: return 4;\r
+ case Id_setDate: return 1;\r
+ case Id_setUTCDate: return 1;\r
+ case Id_setMonth: return 2;\r
+ case Id_setUTCMonth: return 2;\r
+ case Id_setFullYear: return 3;\r
+ case Id_setUTCFullYear: return 3;\r
+ case Id_setYear: return 1;\r
+ }\r
+ }\r
+ return super.methodArity(methodId);\r
+ }\r
+\r
+ public Object execMethod\r
+ (int methodId, IdFunction f,\r
+ Context cx, Scriptable scope, Scriptable thisObj, Object[] args)\r
+ throws JavaScriptException\r
+ {\r
+ if (prototypeFlag) {\r
+ switch (methodId) {\r
+ case ConstructorId_UTC: \r
+ return wrap_double(jsStaticFunction_UTC(args));\r
+\r
+ case ConstructorId_parse: \r
+ return wrap_double(jsStaticFunction_parse\r
+ (ScriptRuntime.toString(args, 0)));\r
+\r
+ case Id_constructor:\r
+ return jsConstructor(args, thisObj == null);\r
+\r
+ case Id_toString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return date_format(t, FORMATSPEC_FULL);\r
+ }\r
+\r
+ case Id_toTimeString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return date_format(t, FORMATSPEC_TIME);\r
+ }\r
+\r
+ case Id_toDateString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return date_format(t, FORMATSPEC_DATE);\r
+ }\r
+\r
+ case Id_toLocaleString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return jsFunction_toLocaleString(t);\r
+ }\r
+\r
+ case Id_toLocaleTimeString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return jsFunction_toLocaleTimeString(t);\r
+ }\r
+\r
+ case Id_toLocaleDateString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ return jsFunction_toLocaleDateString(t);\r
+ }\r
+\r
+ case Id_toUTCString: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { return jsFunction_toUTCString(t); }\r
+ return jsFunction_NaN_date_str;\r
+ }\r
+\r
+ case Id_valueOf: \r
+ return wrap_double(realThis(thisObj, f, true).date);\r
+\r
+ case Id_getTime: \r
+ return wrap_double(realThis(thisObj, f, true).date);\r
+\r
+ case Id_getYear: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = jsFunction_getYear(cx, t); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getFullYear: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = YearFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getUTCFullYear: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = YearFromTime(t); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getMonth: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = MonthFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+ \r
+ case Id_getUTCMonth: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = MonthFromTime(t); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getDate: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = DateFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getUTCDate: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = DateFromTime(t); }\r
+ return wrap_double(t);\r
+ } \r
+\r
+ case Id_getDay: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = WeekDay(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getUTCDay: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = WeekDay(t); }\r
+ return wrap_double(t);\r
+ } \r
+\r
+ case Id_getHours: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = HourFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ } \r
+\r
+ case Id_getUTCHours: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = HourFromTime(t); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getMinutes: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = MinFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ } \r
+\r
+ case Id_getUTCMinutes: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = MinFromTime(t); }\r
+ return wrap_double(t);\r
+ } \r
+\r
+ case Id_getSeconds: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = SecFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getUTCSeconds: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = SecFromTime(t); }\r
+ return wrap_double(t);\r
+ }\r
+ \r
+ case Id_getMilliseconds: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = msFromTime(LocalTime(t)); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_getUTCMilliseconds: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = msFromTime(t); }\r
+ return wrap_double(t);\r
+ }\r
+ \r
+ case Id_getTimezoneOffset: {\r
+ double t = realThis(thisObj, f, true).date;\r
+ if (t == t) { t = jsFunction_getTimezoneOffset(t); }\r
+ return wrap_double(t);\r
+ }\r
+\r
+ case Id_setTime: \r
+ return wrap_double(realThis(thisObj, f, true).\r
+ jsFunction_setTime(ScriptRuntime.toNumber(args, 0)));\r
+\r
+ case Id_setMilliseconds: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 1, true));\r
+\r
+ case Id_setUTCMilliseconds: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 1, false));\r
+\r
+ case Id_setSeconds: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 2, true));\r
+\r
+ case Id_setUTCSeconds: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 2, false));\r
+\r
+ case Id_setMinutes: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 3, true));\r
+\r
+ case Id_setUTCMinutes: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 3, false));\r
+\r
+ case Id_setHours: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 4, true));\r
+\r
+ case Id_setUTCHours: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeTime(args, 4, false));\r
+\r
+ case Id_setDate: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 1, true));\r
+\r
+ case Id_setUTCDate: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 1, false));\r
+\r
+ case Id_setMonth: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 2, true));\r
+\r
+ case Id_setUTCMonth: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 2, false));\r
+\r
+ case Id_setFullYear: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 3, true));\r
+\r
+ case Id_setUTCFullYear: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ makeDate(args, 3, false));\r
+\r
+ case Id_setYear: \r
+ return wrap_double(realThis(thisObj, f, false).\r
+ jsFunction_setYear(ScriptRuntime.toNumber(args, 0)));\r
+ }\r
+ }\r
+\r
+ return super.execMethod(methodId, f, cx, scope, thisObj, args);\r
+ }\r
+\r
+ private NativeDate realThis(Scriptable thisObj, IdFunction f, \r
+ boolean readOnly)\r
+ {\r
+ while (!(thisObj instanceof NativeDate)) {\r
+ thisObj = nextInstanceCheck(thisObj, f, readOnly);\r
+ }\r
+ return (NativeDate)thisObj;\r
+ }\r
+\r
+ /* ECMA helper functions */\r
+\r
+ private static final double HalfTimeDomain = 8.64e15;\r
+ private static final double HoursPerDay = 24.0;\r
+ private static final double MinutesPerHour = 60.0;\r
+ private static final double SecondsPerMinute = 60.0;\r
+ private static final double msPerSecond = 1000.0;\r
+ private static final double MinutesPerDay = (HoursPerDay * MinutesPerHour);\r
+ private static final double SecondsPerDay = (MinutesPerDay * SecondsPerMinute);\r
+ private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute);\r
+ private static final double msPerDay = (SecondsPerDay * msPerSecond);\r
+ private static final double msPerHour = (SecondsPerHour * msPerSecond);\r
+ private static final double msPerMinute = (SecondsPerMinute * msPerSecond);\r
+\r
+ private static double Day(double t) {\r
+ return Math.floor(t / msPerDay);\r
+ }\r
+\r
+ private static double TimeWithinDay(double t) {\r
+ double result;\r
+ result = t % msPerDay;\r
+ if (result < 0)\r
+ result += msPerDay;\r
+ return result;\r
+ }\r
+\r
+ private static int DaysInYear(int y) {\r
+ if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))\r
+ return 366;\r
+ else\r
+ return 365;\r
+ }\r
+\r
+\r
+ /* math here has to be f.p, because we need\r
+ * floor((1968 - 1969) / 4) == -1\r
+ */\r
+ private static double DayFromYear(double y) {\r
+ return ((365 * ((y)-1970) + Math.floor(((y)-1969)/4.0)\r
+ - Math.floor(((y)-1901)/100.0) + Math.floor(((y)-1601)/400.0)));\r
+ }\r
+\r
+ private static double TimeFromYear(double y) {\r
+ return DayFromYear(y) * msPerDay;\r
+ }\r
+\r
+ private static int YearFromTime(double t) {\r
+ int lo = (int) Math.floor((t / msPerDay) / 366) + 1970;\r
+ int hi = (int) Math.floor((t / msPerDay) / 365) + 1970;\r
+ int mid;\r
+\r
+ /* above doesn't work for negative dates... */\r
+ if (hi < lo) {\r
+ int temp = lo;\r
+ lo = hi;\r
+ hi = temp;\r
+ }\r
+\r
+ /* Use a simple binary search algorithm to find the right\r
+ year. This seems like brute force... but the computation\r
+ of hi and lo years above lands within one year of the\r
+ correct answer for years within a thousand years of\r
+ 1970; the loop below only requires six iterations\r
+ for year 270000. */\r
+ while (hi > lo) {\r
+ mid = (hi + lo) / 2;\r
+ if (TimeFromYear(mid) > t) {\r
+ hi = mid - 1;\r
+ } else {\r
+ if (TimeFromYear(mid) <= t) {\r
+ int temp = mid + 1;\r
+ if (TimeFromYear(temp) > t) {\r
+ return mid;\r
+ }\r
+ lo = mid + 1;\r
+ }\r
+ }\r
+ }\r
+ return lo;\r
+ }\r
+\r
+ private static boolean InLeapYear(double t) {\r
+ return DaysInYear(YearFromTime(t)) == 366;\r
+ }\r
+\r
+ private static int DayWithinYear(double t) {\r
+ int year = YearFromTime(t);\r
+ return (int) (Day(t) - DayFromYear(year));\r
+ }\r
+ /*\r
+ * The following array contains the day of year for the first day of\r
+ * each month, where index 0 is January, and day 0 is January 1.\r
+ */\r
+\r
+ private static double DayFromMonth(int m, boolean leap) {\r
+ int day = m * 30;\r
+\r
+ if (m >= 7) { day += m / 2 - 1; }\r
+ else if (m >= 2) { day += (m - 1) / 2 - 1; }\r
+ else { day += m; }\r
+\r
+ if (leap && m >= 2) { ++day; }\r
+\r
+ return day;\r
+ }\r
+\r
+ private static int MonthFromTime(double t) {\r
+ int d, step;\r
+\r
+ d = DayWithinYear(t);\r
+\r
+ if (d < (step = 31))\r
+ return 0;\r
+\r
+ // Originally coded as step += (InLeapYear(t) ? 29 : 28);\r
+ // but some jits always returned 28!\r
+ if (InLeapYear(t))\r
+ step += 29;\r
+ else\r
+ step += 28;\r
+\r
+ if (d < step)\r
+ return 1;\r
+ if (d < (step += 31))\r
+ return 2;\r
+ if (d < (step += 30))\r
+ return 3;\r
+ if (d < (step += 31))\r
+ return 4;\r
+ if (d < (step += 30))\r
+ return 5;\r
+ if (d < (step += 31))\r
+ return 6;\r
+ if (d < (step += 31))\r
+ return 7;\r
+ if (d < (step += 30))\r
+ return 8;\r
+ if (d < (step += 31))\r
+ return 9;\r
+ if (d < (step += 30))\r
+ return 10;\r
+ return 11;\r
+ }\r
+\r
+ private static int DateFromTime(double t) {\r
+ int d, step, next;\r
+\r
+ d = DayWithinYear(t);\r
+ if (d <= (next = 30))\r
+ return d + 1;\r
+ step = next;\r
+\r
+ // Originally coded as next += (InLeapYear(t) ? 29 : 28);\r
+ // but some jits always returned 28!\r
+ if (InLeapYear(t))\r
+ next += 29;\r
+ else\r
+ next += 28;\r
+\r
+ if (d <= next)\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 31))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 30))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 31))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 30))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 31))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 31))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 30))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 31))\r
+ return d - step;\r
+ step = next;\r
+ if (d <= (next += 30))\r
+ return d - step;\r
+ step = next;\r
+\r
+ return d - step;\r
+ }\r
+\r
+ private static int WeekDay(double t) {\r
+ double result;\r
+ result = Day(t) + 4;\r
+ result = result % 7;\r
+ if (result < 0)\r
+ result += 7;\r
+ return (int) result;\r
+ }\r
+\r
+ private static double Now() {\r
+ return (double) System.currentTimeMillis();\r
+ }\r
+\r
+ /* Should be possible to determine the need for this dynamically\r
+ * if we go with the workaround... I'm not using it now, because I\r
+ * can't think of any clean way to make toLocaleString() and the\r
+ * time zone (comment) in toString match the generated string\r
+ * values. Currently it's wrong-but-consistent in all but the\r
+ * most recent betas of the JRE - seems to work in 1.1.7.\r
+ */\r
+ private final static boolean TZO_WORKAROUND = false;\r
+ private static double DaylightSavingTA(double t) {\r
+ if (!TZO_WORKAROUND) {\r
+ Date date = new Date((long) t);\r
+ if (thisTimeZone.inDaylightTime(date))\r
+ return msPerHour;\r
+ else\r
+ return 0;\r
+ } else {\r
+ /* Use getOffset if inDaylightTime() is broken, because it\r
+ * seems to work acceptably. We don't switch over to it\r
+ * entirely, because it requires (expensive) exploded date arguments,\r
+ * and the api makes it impossible to handle dst\r
+ * changeovers cleanly.\r
+ */\r
+\r
+ // Hardcode the assumption that the changeover always\r
+ // happens at 2:00 AM:\r
+ t += LocalTZA + (HourFromTime(t) <= 2 ? msPerHour : 0);\r
+\r
+ int year = YearFromTime(t);\r
+ double offset = thisTimeZone.getOffset(year > 0 ? 1 : 0,\r
+ year,\r
+ MonthFromTime(t),\r
+ DateFromTime(t),\r
+ WeekDay(t),\r
+ (int)TimeWithinDay(t));\r
+\r
+ if ((offset - LocalTZA) != 0)\r
+ return msPerHour;\r
+ else\r
+ return 0;\r
+ // return offset - LocalTZA;\r
+ }\r
+ }\r
+\r
+ private static double LocalTime(double t) {\r
+ return t + LocalTZA + DaylightSavingTA(t);\r
+ }\r
+\r
+ public static double internalUTC(double t) {\r
+ return t - LocalTZA - DaylightSavingTA(t - LocalTZA);\r
+ }\r
+\r
+ private static int HourFromTime(double t) {\r
+ double result;\r
+ result = Math.floor(t / msPerHour) % HoursPerDay;\r
+ if (result < 0)\r
+ result += HoursPerDay;\r
+ return (int) result;\r
+ }\r
+\r
+ private static int MinFromTime(double t) {\r
+ double result;\r
+ result = Math.floor(t / msPerMinute) % MinutesPerHour;\r
+ if (result < 0)\r
+ result += MinutesPerHour;\r
+ return (int) result;\r
+ }\r
+\r
+ private static int SecFromTime(double t) {\r
+ double result;\r
+ result = Math.floor(t / msPerSecond) % SecondsPerMinute;\r
+ if (result < 0)\r
+ result += SecondsPerMinute;\r
+ return (int) result;\r
+ }\r
+\r
+ private static int msFromTime(double t) {\r
+ double result;\r
+ result = t % msPerSecond;\r
+ if (result < 0)\r
+ result += msPerSecond;\r
+ return (int) result;\r
+ }\r
+\r
+ private static double MakeTime(double hour, double min,\r
+ double sec, double ms)\r
+ {\r
+ return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec)\r
+ * msPerSecond + ms;\r
+ }\r
+\r
+ private static double MakeDay(double year, double month, double date) {\r
+ double result;\r
+ boolean leap;\r
+ double yearday;\r
+ double monthday;\r
+\r
+ year += Math.floor(month / 12);\r
+\r
+ month = month % 12;\r
+ if (month < 0)\r
+ month += 12;\r
+\r
+ leap = (DaysInYear((int) year) == 366);\r
+\r
+ yearday = Math.floor(TimeFromYear(year) / msPerDay);\r
+ monthday = DayFromMonth((int) month, leap);\r
+\r
+ result = yearday\r
+ + monthday\r
+ + date - 1;\r
+ return result;\r
+ }\r
+\r
+ private static double MakeDate(double day, double time) {\r
+ return day * msPerDay + time;\r
+ }\r
+\r
+ private static double TimeClip(double d) {\r
+ if (d != d ||\r
+ d == Double.POSITIVE_INFINITY ||\r
+ d == Double.NEGATIVE_INFINITY ||\r
+ Math.abs(d) > HalfTimeDomain)\r
+ {\r
+ return ScriptRuntime.NaN;\r
+ }\r
+ if (d > 0.0)\r
+ return Math.floor(d + 0.);\r
+ else\r
+ return Math.ceil(d + 0.);\r
+ }\r
+\r
+ /* end of ECMA helper functions */\r
+\r
+ /* find UTC time from given date... no 1900 correction! */\r
+ public static double date_msecFromDate(double year, double mon,\r
+ double mday, double hour,\r
+ double min, double sec,\r
+ double msec)\r
+ {\r
+ double day;\r
+ double time;\r
+ double result;\r
+\r
+ day = MakeDay(year, mon, mday);\r
+ time = MakeTime(hour, min, sec, msec);\r
+ result = MakeDate(day, time);\r
+ return result;\r
+ }\r
+\r
+\r
+ private static final int MAXARGS = 7;\r
+ private static double jsStaticFunction_UTC(Object[] args) {\r
+ double array[] = new double[MAXARGS];\r
+ int loop;\r
+ double d;\r
+\r
+ for (loop = 0; loop < MAXARGS; loop++) {\r
+ if (loop < args.length) {\r
+ d = ScriptRuntime.toNumber(args[loop]);\r
+ if (d != d || Double.isInfinite(d)) {\r
+ return ScriptRuntime.NaN;\r
+ }\r
+ array[loop] = ScriptRuntime.toInteger(args[loop]);\r
+ } else {\r
+ array[loop] = 0;\r
+ }\r
+ }\r
+\r
+ /* adjust 2-digit years into the 20th century */\r
+ if (array[0] >= 0 && array[0] <= 99)\r
+ array[0] += 1900;\r
+\r
+ /* if we got a 0 for 'date' (which is out of range)\r
+ * pretend it's a 1. (So Date.UTC(1972, 5) works) */\r
+ if (array[2] < 1)\r
+ array[2] = 1;\r
+\r
+ d = date_msecFromDate(array[0], array[1], array[2],\r
+ array[3], array[4], array[5], array[6]);\r
+ d = TimeClip(d);\r
+ return d;\r
+ // return new Double(d);\r
+ }\r
+\r
+ /*\r
+ * Use ported code from jsdate.c rather than the locale-specific\r
+ * date-parsing code from Java, to keep js and rhino consistent.\r
+ * Is this the right strategy?\r
+ */\r
+\r
+ /* for use by date_parse */\r
+\r
+ /* replace this with byte arrays? Cheaper? */\r
+ private static String wtb[] = {\r
+ "am", "pm",\r
+ "monday", "tuesday", "wednesday", "thursday", "friday",\r
+ "saturday", "sunday",\r
+ "january", "february", "march", "april", "may", "june",\r
+ "july", "august", "september", "october", "november", "december",\r
+ "gmt", "ut", "utc", "est", "edt", "cst", "cdt",\r
+ "mst", "mdt", "pst", "pdt"\r
+ /* time zone table needs to be expanded */\r
+ };\r
+\r
+ private static int ttb[] = {\r
+ -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */\r
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,\r
+ 10000 + 0, 10000 + 0, 10000 + 0, /* UT/UTC */\r
+ 10000 + 5 * 60, 10000 + 4 * 60, /* EDT */\r
+ 10000 + 6 * 60, 10000 + 5 * 60,\r
+ 10000 + 7 * 60, 10000 + 6 * 60,\r
+ 10000 + 8 * 60, 10000 + 7 * 60\r
+ };\r
+\r
+ /* helper for date_parse */\r
+ private static boolean date_regionMatches(String s1, int s1off,\r
+ String s2, int s2off,\r
+ int count)\r
+ {\r
+ boolean result = false;\r
+ /* return true if matches, otherwise, false */\r
+ int s1len = s1.length();\r
+ int s2len = s2.length();\r
+\r
+ while (count > 0 && s1off < s1len && s2off < s2len) {\r
+ if (Character.toLowerCase(s1.charAt(s1off)) !=\r
+ Character.toLowerCase(s2.charAt(s2off)))\r
+ break;\r
+ s1off++;\r
+ s2off++;\r
+ count--;\r
+ }\r
+\r
+ if (count == 0) {\r
+ result = true;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private static double date_parseString(String s) {\r
+ double msec;\r
+\r
+ int year = -1;\r
+ int mon = -1;\r
+ int mday = -1;\r
+ int hour = -1;\r
+ int min = -1;\r
+ int sec = -1;\r
+ char c = 0;\r
+ char si = 0;\r
+ int i = 0;\r
+ int n = -1;\r
+ double tzoffset = -1;\r
+ char prevc = 0;\r
+ int limit = 0;\r
+ boolean seenplusminus = false;\r
+\r
+ if (s == null) // ??? Will s be null?\r
+ return ScriptRuntime.NaN;\r
+ limit = s.length();\r
+ while (i < limit) {\r
+ c = s.charAt(i);\r
+ i++;\r
+ if (c <= ' ' || c == ',' || c == '-') {\r
+ if (i < limit) {\r
+ si = s.charAt(i);\r
+ if (c == '-' && '0' <= si && si <= '9') {\r
+ prevc = c;\r
+ }\r
+ }\r
+ continue;\r
+ }\r
+ if (c == '(') { /* comments) */\r
+ int depth = 1;\r
+ while (i < limit) {\r
+ c = s.charAt(i);\r
+ i++;\r
+ if (c == '(')\r
+ depth++;\r
+ else if (c == ')')\r
+ if (--depth <= 0)\r
+ break;\r
+ }\r
+ continue;\r
+ }\r
+ if ('0' <= c && c <= '9') {\r
+ n = c - '0';\r
+ while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') {\r
+ n = n * 10 + c - '0';\r
+ i++;\r
+ }\r
+\r
+ /* allow TZA before the year, so\r
+ * 'Wed Nov 05 21:49:11 GMT-0800 1997'\r
+ * works */\r
+\r
+ /* uses of seenplusminus allow : in TZA, so Java\r
+ * no-timezone style of GMT+4:30 works\r
+ */\r
+ if ((prevc == '+' || prevc == '-')/* && year>=0 */) {\r
+ /* make ':' case below change tzoffset */\r
+ seenplusminus = true;\r
+\r
+ /* offset */\r
+ if (n < 24)\r
+ n = n * 60; /* EG. "GMT-3" */\r
+ else\r
+ n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */\r
+ if (prevc == '+') /* plus means east of GMT */\r
+ n = -n;\r
+ if (tzoffset != 0 && tzoffset != -1)\r
+ return ScriptRuntime.NaN;\r
+ tzoffset = n;\r
+ } else if (n >= 70 ||\r
+ (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {\r
+ if (year >= 0)\r
+ return ScriptRuntime.NaN;\r
+ else if (c <= ' ' || c == ',' || c == '/' || i >= limit)\r
+ year = n < 100 ? n + 1900 : n;\r
+ else\r
+ return ScriptRuntime.NaN;\r
+ } else if (c == ':') {\r
+ if (hour < 0)\r
+ hour = /*byte*/ n;\r
+ else if (min < 0)\r
+ min = /*byte*/ n;\r
+ else\r
+ return ScriptRuntime.NaN;\r
+ } else if (c == '/') {\r
+ if (mon < 0)\r
+ mon = /*byte*/ n-1;\r
+ else if (mday < 0)\r
+ mday = /*byte*/ n;\r
+ else\r
+ return ScriptRuntime.NaN;\r
+ } else if (i < limit && c != ',' && c > ' ' && c != '-') {\r
+ return ScriptRuntime.NaN;\r
+ } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */\r
+ if (tzoffset < 0)\r
+ tzoffset -= n;\r
+ else\r
+ tzoffset += n;\r
+ } else if (hour >= 0 && min < 0) {\r
+ min = /*byte*/ n;\r
+ } else if (min >= 0 && sec < 0) {\r
+ sec = /*byte*/ n;\r
+ } else if (mday < 0) {\r
+ mday = /*byte*/ n;\r
+ } else {\r
+ return ScriptRuntime.NaN;\r
+ }\r
+ prevc = 0;\r
+ } else if (c == '/' || c == ':' || c == '+' || c == '-') {\r
+ prevc = c;\r
+ } else {\r
+ int st = i - 1;\r
+ int k;\r
+ while (i < limit) {\r
+ c = s.charAt(i);\r
+ if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))\r
+ break;\r
+ i++;\r
+ }\r
+ if (i <= st + 1)\r
+ return ScriptRuntime.NaN;\r
+ for (k = wtb.length; --k >= 0;)\r
+ if (date_regionMatches(wtb[k], 0, s, st, i-st)) {\r
+ int action = ttb[k];\r
+ if (action != 0) {\r
+ if (action < 0) {\r
+ /*\r
+ * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as\r
+ * 12:30, instead of blindly adding 12 if PM.\r
+ */\r
+ if (hour > 12 || hour < 0) {\r
+ return ScriptRuntime.NaN;\r
+ } else {\r
+ if (action == -1 && hour == 12) { // am\r
+ hour = 0;\r
+ } else if (action == -2 && hour != 12) {// pm\r
+ hour += 12;\r
+ }\r
+ }\r
+ } else if (action <= 13) { /* month! */\r
+ if (mon < 0) {\r
+ mon = /*byte*/ (action - 2);\r
+ } else {\r
+ return ScriptRuntime.NaN;\r
+ }\r
+ } else {\r
+ tzoffset = action - 10000;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ if (k < 0)\r
+ return ScriptRuntime.NaN;\r
+ prevc = 0;\r
+ }\r
+ }\r
+ if (year < 0 || mon < 0 || mday < 0)\r
+ return ScriptRuntime.NaN;\r
+ if (sec < 0)\r
+ sec = 0;\r
+ if (min < 0)\r
+ min = 0;\r
+ if (hour < 0)\r
+ hour = 0;\r
+ if (tzoffset == -1) { /* no time zone specified, have to use local */\r
+ double time;\r
+ time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);\r
+ return internalUTC(time);\r
+ }\r
+\r
+ msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);\r
+ msec += tzoffset * msPerMinute;\r
+ return msec;\r
+ }\r
+\r
+ private static double jsStaticFunction_parse(String s) {\r
+ return date_parseString(s);\r
+ }\r
+\r
+ private static final int FORMATSPEC_FULL = 0;\r
+ private static final int FORMATSPEC_DATE = 1;\r
+ private static final int FORMATSPEC_TIME = 2;\r
+\r
+ private static String date_format(double t, int format) {\r
+ if (t != t)\r
+ return jsFunction_NaN_date_str;\r
+\r
+ StringBuffer result = new StringBuffer(60);\r
+ double local = LocalTime(t);\r
+\r
+ /* offset from GMT in minutes. The offset includes daylight savings,\r
+ if it applies. */\r
+ int minutes = (int) Math.floor((LocalTZA + DaylightSavingTA(t))\r
+ / msPerMinute);\r
+ /* map 510 minutes to 0830 hours */\r
+ int offset = (minutes / 60) * 100 + minutes % 60;\r
+\r
+ String dateStr = Integer.toString(DateFromTime(local));\r
+ String hourStr = Integer.toString(HourFromTime(local));\r
+ String minStr = Integer.toString(MinFromTime(local));\r
+ String secStr = Integer.toString(SecFromTime(local));\r
+ String offsetStr = Integer.toString(offset > 0 ? offset : -offset);\r
+ int year = YearFromTime(local);\r
+ String yearStr = Integer.toString(year > 0 ? year : -year);\r
+\r
+ /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */\r
+ /* Tue Oct 31 2000 */\r
+ /* 09:41:40 GMT-0800 (PST) */\r
+\r
+ if (format != FORMATSPEC_TIME) {\r
+ result.append(days[WeekDay(local)]);\r
+ result.append(' ');\r
+ result.append(months[MonthFromTime(local)]);\r
+ if (dateStr.length() == 1)\r
+ result.append(" 0");\r
+ else\r
+ result.append(' ');\r
+ result.append(dateStr);\r
+ result.append(' ');\r
+ }\r
+\r
+ if (format != FORMATSPEC_DATE) {\r
+ if (hourStr.length() == 1)\r
+ result.append('0');\r
+ result.append(hourStr);\r
+ if (minStr.length() == 1)\r
+ result.append(":0");\r
+ else\r
+ result.append(':');\r
+ result.append(minStr);\r
+ if (secStr.length() == 1)\r
+ result.append(":0");\r
+ else\r
+ result.append(':');\r
+ result.append(secStr);\r
+ if (offset > 0)\r
+ result.append(" GMT+");\r
+ else\r
+ result.append(" GMT-");\r
+ for (int i = offsetStr.length(); i < 4; i++)\r
+ result.append('0');\r
+ result.append(offsetStr);\r
+\r
+ if (timeZoneFormatter == null)\r
+ timeZoneFormatter = new java.text.SimpleDateFormat("zzz");\r
+\r
+ if (timeZoneFormatter != null) {\r
+ result.append(" (");\r
+ java.util.Date date = new Date((long) t);\r
+ result.append(timeZoneFormatter.format(date));\r
+ result.append(')');\r
+ }\r
+ if (format != FORMATSPEC_TIME)\r
+ result.append(' ');\r
+ }\r
+\r
+ if (format != FORMATSPEC_TIME) {\r
+ if (year < 0)\r
+ result.append('-');\r
+ for (int i = yearStr.length(); i < 4; i++)\r
+ result.append('0');\r
+ result.append(yearStr);\r
+ }\r
+\r
+ return result.toString();\r
+ }\r
+\r
+ /* the javascript constructor */\r
+ private static Object jsConstructor(Object[] args, boolean inNewExpr) {\r
+ // if called as a function, just return a string\r
+ // representing the current time.\r
+ if (!inNewExpr)\r
+ return date_format(Now(), FORMATSPEC_FULL);\r
+\r
+ NativeDate obj = new NativeDate();\r
+\r
+ // if called as a constructor with no args,\r
+ // return a new Date with the current time.\r
+ if (args.length == 0) {\r
+ obj.date = Now();\r
+ return obj;\r
+ }\r
+\r
+ // if called with just one arg -\r
+ if (args.length == 1) {\r
+ double date;\r
+ if (args[0] instanceof Scriptable)\r
+ args[0] = ((Scriptable) args[0]).getDefaultValue(null);\r
+ if (!(args[0] instanceof String)) {\r
+ // if it's not a string, use it as a millisecond date\r
+ date = ScriptRuntime.toNumber(args[0]);\r
+ } else {\r
+ // it's a string; parse it.\r
+ String str = (String) args[0];\r
+ date = date_parseString(str);\r
+ }\r
+ obj.date = TimeClip(date);\r
+ return obj;\r
+ }\r
+\r
+ // multiple arguments; year, month, day etc.\r
+ double array[] = new double[MAXARGS];\r
+ int loop;\r
+ double d;\r
+\r
+ for (loop = 0; loop < MAXARGS; loop++) {\r
+ if (loop < args.length) {\r
+ d = ScriptRuntime.toNumber(args[loop]);\r
+\r
+ if (d != d || Double.isInfinite(d)) {\r
+ obj.date = ScriptRuntime.NaN;\r
+ return obj;\r
+ }\r
+ array[loop] = ScriptRuntime.toInteger(args[loop]);\r
+ } else {\r
+ array[loop] = 0;\r
+ }\r
+ }\r
+\r
+ /* adjust 2-digit years into the 20th century */\r
+ if (array[0] >= 0 && array[0] <= 99)\r
+ array[0] += 1900;\r
+\r
+ /* if we got a 0 for 'date' (which is out of range)\r
+ * pretend it's a 1 */\r
+ if (array[2] < 1)\r
+ array[2] = 1;\r
+\r
+ double day = MakeDay(array[0], array[1], array[2]);\r
+ double time = MakeTime(array[3], array[4], array[5], array[6]);\r
+ time = MakeDate(day, time);\r
+ time = internalUTC(time);\r
+ obj.date = TimeClip(time);\r
+\r
+ return obj;\r
+ }\r
+\r
+ /* constants for toString, toUTCString */\r
+ private static String jsFunction_NaN_date_str = "Invalid Date";\r
+\r
+ private static String[] days = {\r
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"\r
+ };\r
+\r
+ private static String[] months = {\r
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"\r
+ };\r
+\r
+ private static String toLocale_helper(double t,\r
+ java.text.DateFormat formatter)\r
+ {\r
+ if (t != t)\r
+ return jsFunction_NaN_date_str;\r
+\r
+ java.util.Date tempdate = new Date((long) t);\r
+ return formatter.format(tempdate);\r
+ }\r
+\r
+ private static String jsFunction_toLocaleString(double date) {\r
+ if (localeDateTimeFormatter == null)\r
+ localeDateTimeFormatter =\r
+ DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);\r
+\r
+ return toLocale_helper(date, localeDateTimeFormatter);\r
+ }\r
+\r
+ private static String jsFunction_toLocaleTimeString(double date) {\r
+ if (localeTimeFormatter == null)\r
+ localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG);\r
+\r
+ return toLocale_helper(date, localeTimeFormatter);\r
+ }\r
+\r
+ private static String jsFunction_toLocaleDateString(double date) {\r
+ if (localeDateFormatter == null)\r
+ localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG);\r
+\r
+ return toLocale_helper(date, localeDateFormatter);\r
+ }\r
+\r
+ private static String jsFunction_toUTCString(double date) {\r
+ StringBuffer result = new StringBuffer(60);\r
+\r
+ String dateStr = Integer.toString(DateFromTime(date));\r
+ String hourStr = Integer.toString(HourFromTime(date));\r
+ String minStr = Integer.toString(MinFromTime(date));\r
+ String secStr = Integer.toString(SecFromTime(date));\r
+ int year = YearFromTime(date);\r
+ String yearStr = Integer.toString(year > 0 ? year : -year);\r
+\r
+ result.append(days[WeekDay(date)]);\r
+ result.append(", ");\r
+ if (dateStr.length() == 1)\r
+ result.append('0');\r
+ result.append(dateStr);\r
+ result.append(' ');\r
+ result.append(months[MonthFromTime(date)]);\r
+ if (year < 0)\r
+ result.append(" -");\r
+ else\r
+ result.append(' ');\r
+ int i;\r
+ for (i = yearStr.length(); i < 4; i++)\r
+ result.append('0');\r
+ result.append(yearStr);\r
+\r
+ if (hourStr.length() == 1)\r
+ result.append(" 0");\r
+ else\r
+ result.append(' ');\r
+ result.append(hourStr);\r
+ if (minStr.length() == 1)\r
+ result.append(":0");\r
+ else\r
+ result.append(':');\r
+ result.append(minStr);\r
+ if (secStr.length() == 1)\r
+ result.append(":0");\r
+ else\r
+ result.append(':');\r
+ result.append(secStr);\r
+\r
+ result.append(" GMT");\r
+ return result.toString();\r
+ }\r
+\r
+ private static double jsFunction_getYear(Context cx, double date) {\r
+\r
+ int result = YearFromTime(LocalTime(date));\r
+\r
+ if (cx.hasFeature(Context.FEATURE_NON_ECMA_GET_YEAR)) {\r
+ if (result >= 1900 && result < 2000) {\r
+ result -= 1900;\r
+ }\r
+ } \r
+ else {\r
+ result -= 1900;\r
+ }\r
+ return result;\r
+ }\r
+\r
+ private static double jsFunction_getTimezoneOffset(double date) {\r
+ return (date - LocalTime(date)) / msPerMinute;\r
+ }\r
+\r
+ public double jsFunction_setTime(double time) {\r
+ this.date = TimeClip(time);\r
+ return this.date;\r
+ }\r
+\r
+ private double makeTime(Object[] args, int maxargs, boolean local) {\r
+ int i;\r
+ double conv[] = new double[4];\r
+ double hour, min, sec, msec;\r
+ double lorutime; /* Local or UTC version of date */\r
+\r
+ double time;\r
+ double result;\r
+\r
+ double date = this.date;\r
+\r
+ /* just return NaN if the date is already NaN */\r
+ if (date != date)\r
+ return date;\r
+\r
+ /* Satisfy the ECMA rule that if a function is called with\r
+ * fewer arguments than the specified formal arguments, the\r
+ * remaining arguments are set to undefined. Seems like all\r
+ * the Date.setWhatever functions in ECMA are only varargs\r
+ * beyond the first argument; this should be set to undefined\r
+ * if it's not given. This means that "d = new Date();\r
+ * d.setMilliseconds()" returns NaN. Blech.\r
+ */\r
+ if (args.length == 0)\r
+ args = ScriptRuntime.padArguments(args, 1);\r
+\r
+ for (i = 0; i < args.length && i < maxargs; i++) {\r
+ conv[i] = ScriptRuntime.toNumber(args[i]);\r
+\r
+ // limit checks that happen in MakeTime in ECMA.\r
+ if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {\r
+ this.date = ScriptRuntime.NaN;\r
+ return this.date;\r
+ }\r
+ conv[i] = ScriptRuntime.toInteger(conv[i]);\r
+ }\r
+\r
+ if (local)\r
+ lorutime = LocalTime(date);\r
+ else\r
+ lorutime = date;\r
+\r
+ i = 0;\r
+ int stop = args.length;\r
+\r
+ if (maxargs >= 4 && i < stop)\r
+ hour = conv[i++];\r
+ else\r
+ hour = HourFromTime(lorutime);\r
+\r
+ if (maxargs >= 3 && i < stop)\r
+ min = conv[i++];\r
+ else\r
+ min = MinFromTime(lorutime);\r
+\r
+ if (maxargs >= 2 && i < stop)\r
+ sec = conv[i++];\r
+ else\r
+ sec = SecFromTime(lorutime);\r
+\r
+ if (maxargs >= 1 && i < stop)\r
+ msec = conv[i++];\r
+ else\r
+ msec = msFromTime(lorutime);\r
+\r
+ time = MakeTime(hour, min, sec, msec);\r
+ result = MakeDate(Day(lorutime), time);\r
+\r
+ if (local)\r
+ result = internalUTC(result);\r
+ date = TimeClip(result);\r
+\r
+ this.date = date;\r
+ return date;\r
+ }\r
+\r
+ private double jsFunction_setHours(Object[] args) {\r
+ return makeTime(args, 4, true);\r
+ }\r
+\r
+ private double jsFunction_setUTCHours(Object[] args) {\r
+ return makeTime(args, 4, false);\r
+ }\r
+\r
+ private double makeDate(Object[] args, int maxargs, boolean local) {\r
+ int i;\r
+ double conv[] = new double[3];\r
+ double year, month, day;\r
+ double lorutime; /* local or UTC version of date */\r
+ double result;\r
+\r
+ double date = this.date;\r
+\r
+ /* See arg padding comment in makeTime.*/\r
+ if (args.length == 0)\r
+ args = ScriptRuntime.padArguments(args, 1);\r
+\r
+ for (i = 0; i < args.length && i < maxargs; i++) {\r
+ conv[i] = ScriptRuntime.toNumber(args[i]);\r
+\r
+ // limit checks that happen in MakeDate in ECMA.\r
+ if (conv[i] != conv[i] || Double.isInfinite(conv[i])) {\r
+ this.date = ScriptRuntime.NaN;\r
+ return this.date;\r
+ }\r
+ conv[i] = ScriptRuntime.toInteger(conv[i]);\r
+ }\r
+\r
+ /* return NaN if date is NaN and we're not setting the year,\r
+ * If we are, use 0 as the time. */\r
+ if (date != date) {\r
+ if (args.length < 3) {\r
+ return ScriptRuntime.NaN;\r
+ } else {\r
+ lorutime = 0;\r
+ }\r
+ } else {\r
+ if (local)\r
+ lorutime = LocalTime(date);\r
+ else\r
+ lorutime = date;\r
+ }\r
+\r
+ i = 0;\r
+ int stop = args.length;\r
+\r
+ if (maxargs >= 3 && i < stop)\r
+ year = conv[i++];\r
+ else\r
+ year = YearFromTime(lorutime);\r
+\r
+ if (maxargs >= 2 && i < stop)\r
+ month = conv[i++];\r
+ else\r
+ month = MonthFromTime(lorutime);\r
+\r
+ if (maxargs >= 1 && i < stop)\r
+ day = conv[i++];\r
+ else\r
+ day = DateFromTime(lorutime);\r
+\r
+ day = MakeDay(year, month, day); /* day within year */\r
+ result = MakeDate(day, TimeWithinDay(lorutime));\r
+\r
+ if (local)\r
+ result = internalUTC(result);\r
+\r
+ date = TimeClip(result);\r
+\r
+ this.date = date;\r
+ return date;\r
+ }\r
+\r
+ private double jsFunction_setYear(double year) {\r
+ double day, result;\r
+ if (year != year || Double.isInfinite(year)) {\r
+ this.date = ScriptRuntime.NaN;\r
+ return this.date;\r
+ }\r
+\r
+ if (this.date != this.date) {\r
+ this.date = 0;\r
+ } else {\r
+ this.date = LocalTime(this.date);\r
+ }\r
+\r
+ if (year >= 0 && year <= 99)\r
+ year += 1900;\r
+\r
+ day = MakeDay(year, MonthFromTime(this.date), DateFromTime(this.date));\r
+ result = MakeDate(day, TimeWithinDay(this.date));\r
+ result = internalUTC(result);\r
+\r
+ this.date = TimeClip(result);\r
+ return this.date;\r
+ }\r
+\r
+ protected String getIdName(int id) {\r
+ if (prototypeFlag) {\r
+ switch (id) {\r
+ case ConstructorId_UTC: return "UTC";\r
+ case ConstructorId_parse: return "parse";\r
+ case Id_constructor: return "constructor"; \r
+ case Id_toString: return "toString";\r
+ case Id_toTimeString: return "toTimeString";\r
+ case Id_toDateString: return "toDateString";\r
+ case Id_toLocaleString: return "toLocaleString";\r
+ case Id_toLocaleTimeString: return "toLocaleTimeString";\r
+ case Id_toLocaleDateString: return "toLocaleDateString";\r
+ case Id_toUTCString: return "toUTCString";\r
+ case Id_valueOf: return "valueOf";\r
+ case Id_getTime: return "getTime";\r
+ case Id_getYear: return "getYear";\r
+ case Id_getFullYear: return "getFullYear";\r
+ case Id_getUTCFullYear: return "getUTCFullYear";\r
+ case Id_getMonth: return "getMonth";\r
+ case Id_getUTCMonth: return "getUTCMonth";\r
+ case Id_getDate: return "getDate";\r
+ case Id_getUTCDate: return "getUTCDate";\r
+ case Id_getDay: return "getDay";\r
+ case Id_getUTCDay: return "getUTCDay";\r
+ case Id_getHours: return "getHours";\r
+ case Id_getUTCHours: return "getUTCHours";\r
+ case Id_getMinutes: return "getMinutes";\r
+ case Id_getUTCMinutes: return "getUTCMinutes";\r
+ case Id_getSeconds: return "getSeconds";\r
+ case Id_getUTCSeconds: return "getUTCSeconds";\r
+ case Id_getMilliseconds: return "getMilliseconds";\r
+ case Id_getUTCMilliseconds: return "getUTCMilliseconds";\r
+ case Id_getTimezoneOffset: return "getTimezoneOffset";\r
+ case Id_setTime: return "setTime";\r
+ case Id_setMilliseconds: return "setMilliseconds";\r
+ case Id_setUTCMilliseconds: return "setUTCMilliseconds";\r
+ case Id_setSeconds: return "setSeconds";\r
+ case Id_setUTCSeconds: return "setUTCSeconds";\r
+ case Id_setMinutes: return "setMinutes";\r
+ case Id_setUTCMinutes: return "setUTCMinutes";\r
+ case Id_setHours: return "setHours";\r
+ case Id_setUTCHours: return "setUTCHours";\r
+ case Id_setDate: return "setDate";\r
+ case Id_setUTCDate: return "setUTCDate";\r
+ case Id_setMonth: return "setMonth";\r
+ case Id_setUTCMonth: return "setUTCMonth";\r
+ case Id_setFullYear: return "setFullYear";\r
+ case Id_setUTCFullYear: return "setUTCFullYear";\r
+ case Id_setYear: return "setYear";\r
+ }\r
+ }\r
+ return null; \r
+ }\r
+\r
+// #string_id_map#\r
+\r
+ protected int mapNameToId(String s) {\r
+ if (!prototypeFlag) { return 0; }\r
+ int id;\r
+// #generated# Last update: 2001-04-22 23:46:59 CEST\r
+ L0: { id = 0; String X = null; int c;\r
+ L: switch (s.length()) {\r
+ case 6: X="getDay";id=Id_getDay; break L;\r
+ case 7: switch (s.charAt(3)) {\r
+ case 'D': c=s.charAt(0);\r
+ if (c=='g') { X="getDate";id=Id_getDate; }\r
+ else if (c=='s') { X="setDate";id=Id_setDate; }\r
+ break L;\r
+ case 'T': c=s.charAt(0);\r
+ if (c=='g') { X="getTime";id=Id_getTime; }\r
+ else if (c=='s') { X="setTime";id=Id_setTime; }\r
+ break L;\r
+ case 'Y': c=s.charAt(0);\r
+ if (c=='g') { X="getYear";id=Id_getYear; }\r
+ else if (c=='s') { X="setYear";id=Id_setYear; }\r
+ break L;\r
+ case 'u': X="valueOf";id=Id_valueOf; break L;\r
+ } break L;\r
+ case 8: c=s.charAt(0);\r
+ if (c=='g') {\r
+ c=s.charAt(7);\r
+ if (c=='h') { X="getMonth";id=Id_getMonth; }\r
+ else if (c=='s') { X="getHours";id=Id_getHours; }\r
+ }\r
+ else if (c=='s') {\r
+ c=s.charAt(7);\r
+ if (c=='h') { X="setMonth";id=Id_setMonth; }\r
+ else if (c=='s') { X="setHours";id=Id_setHours; }\r
+ }\r
+ else if (c=='t') { X="toString";id=Id_toString; }\r
+ break L;\r
+ case 9: X="getUTCDay";id=Id_getUTCDay; break L;\r
+ case 10: c=s.charAt(3);\r
+ if (c=='M') {\r
+ c=s.charAt(0);\r
+ if (c=='g') { X="getMinutes";id=Id_getMinutes; }\r
+ else if (c=='s') { X="setMinutes";id=Id_setMinutes; }\r
+ }\r
+ else if (c=='S') {\r
+ c=s.charAt(0);\r
+ if (c=='g') { X="getSeconds";id=Id_getSeconds; }\r
+ else if (c=='s') { X="setSeconds";id=Id_setSeconds; }\r
+ }\r
+ else if (c=='U') {\r
+ c=s.charAt(0);\r
+ if (c=='g') { X="getUTCDate";id=Id_getUTCDate; }\r
+ else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; }\r
+ }\r
+ break L;\r
+ case 11: switch (s.charAt(3)) {\r
+ case 'F': c=s.charAt(0);\r
+ if (c=='g') { X="getFullYear";id=Id_getFullYear; }\r
+ else if (c=='s') { X="setFullYear";id=Id_setFullYear; }\r
+ break L;\r
+ case 'M': X="toGMTString";id=Id_toGMTString; break L;\r
+ case 'T': X="toUTCString";id=Id_toUTCString; break L;\r
+ case 'U': c=s.charAt(0);\r
+ if (c=='g') {\r
+ c=s.charAt(9);\r
+ if (c=='r') { X="getUTCHours";id=Id_getUTCHours; }\r
+ else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; }\r
+ }\r
+ else if (c=='s') {\r
+ c=s.charAt(9);\r
+ if (c=='r') { X="setUTCHours";id=Id_setUTCHours; }\r
+ else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; }\r
+ }\r
+ break L;\r
+ case 's': X="constructor";id=Id_constructor; break L;\r
+ } break L;\r
+ case 12: c=s.charAt(2);\r
+ if (c=='D') { X="toDateString";id=Id_toDateString; }\r
+ else if (c=='T') { X="toTimeString";id=Id_toTimeString; }\r
+ break L;\r
+ case 13: c=s.charAt(0);\r
+ if (c=='g') {\r
+ c=s.charAt(6);\r
+ if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; }\r
+ else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; }\r
+ }\r
+ else if (c=='s') {\r
+ c=s.charAt(6);\r
+ if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; }\r
+ else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; }\r
+ }\r
+ break L;\r
+ case 14: c=s.charAt(0);\r
+ if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; }\r
+ else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; }\r
+ else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; }\r
+ break L;\r
+ case 15: c=s.charAt(0);\r
+ if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; }\r
+ else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; }\r
+ break L;\r
+ case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L;\r
+ case 18: c=s.charAt(0);\r
+ if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; }\r
+ else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; }\r
+ else if (c=='t') {\r
+ c=s.charAt(8);\r
+ if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; }\r
+ else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; }\r
+ }\r
+ break L;\r
+ }\r
+ if (X!=null && X!=s && !X.equals(s)) id = 0;\r
+ }\r
+// #/generated#\r
+ return id;\r
+ }\r
+\r
+ private static final int\r
+ ConstructorId_UTC = -2,\r
+ ConstructorId_parse = -1,\r
+\r
+ Id_constructor = 1,\r
+ Id_toString = 2,\r
+ Id_toTimeString = 3,\r
+ Id_toDateString = 4,\r
+ Id_toLocaleString = 5,\r
+ Id_toLocaleTimeString = 6,\r
+ Id_toLocaleDateString = 7,\r
+ Id_toUTCString = 8,\r
+ Id_valueOf = 9,\r
+ Id_getTime = 10,\r
+ Id_getYear = 11,\r
+ Id_getFullYear = 12,\r
+ Id_getUTCFullYear = 13,\r
+ Id_getMonth = 14,\r
+ Id_getUTCMonth = 15,\r
+ Id_getDate = 16,\r
+ Id_getUTCDate = 17,\r
+ Id_getDay = 18,\r
+ Id_getUTCDay = 19,\r
+ Id_getHours = 20,\r
+ Id_getUTCHours = 21,\r
+ Id_getMinutes = 22,\r
+ Id_getUTCMinutes = 23,\r
+ Id_getSeconds = 24,\r
+ Id_getUTCSeconds = 25,\r
+ Id_getMilliseconds = 26,\r
+ Id_getUTCMilliseconds = 27,\r
+ Id_getTimezoneOffset = 28,\r
+ Id_setTime = 29,\r
+ Id_setMilliseconds = 30,\r
+ Id_setUTCMilliseconds = 31,\r
+ Id_setSeconds = 32,\r
+ Id_setUTCSeconds = 33,\r
+ Id_setMinutes = 34,\r
+ Id_setUTCMinutes = 35,\r
+ Id_setHours = 36,\r
+ Id_setUTCHours = 37,\r
+ Id_setDate = 38,\r
+ Id_setUTCDate = 39,\r
+ Id_setMonth = 40,\r
+ Id_setUTCMonth = 41,\r
+ Id_setFullYear = 42,\r
+ Id_setUTCFullYear = 43,\r
+ Id_setYear = 44,\r
+\r
+ MAX_PROTOTYPE_ID = 44;\r
+\r
+ private static final int\r
+ Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6\r
+// #/string_id_map#\r
+\r
+ /* cached values */\r
+ private static java.util.TimeZone thisTimeZone;\r
+ private static double LocalTZA;\r
+ private static java.text.DateFormat timeZoneFormatter;\r
+ private static java.text.DateFormat localeDateTimeFormatter;\r
+ private static java.text.DateFormat localeDateFormatter;\r
+ private static java.text.DateFormat localeTimeFormatter;\r
+\r
+ private double date;\r
+\r
+ private boolean prototypeFlag;\r
+}\r
+\r
+\r