All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mozilla.javascript.NativeDate Maven / Gradle / Ivy

The newest version!
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript;

import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.TimeZone;

/**
 * This class implements the Date native object.
 * See ECMA 15.9.
 * @author Mike McCabe
 *
 * Significant parts of this code are adapted from the venerable jsdate.cpp (also Mozilla):
 * https://dxr.mozilla.com/baidu/openrasp/org/mozilla-central/source/js/src/jsdate.cpp
 */
final class NativeDate extends IdScriptableObject
{
    static final long serialVersionUID = -8307438915861678966L;

    private static final Object DATE_TAG = "Date";

    private static final String js_NaN_date_str = "Invalid Date";

    static void init(Scriptable scope, boolean sealed)
    {
        NativeDate obj = new NativeDate();
        // Set the value of the prototype Date to NaN ('invalid date');
        obj.date = ScriptRuntime.NaN;
        obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed);
    }

    private NativeDate()
    {
        if (thisTimeZone == null) {
            // j.u.TimeZone is synchronized, so setting class statics from it
            // should be OK.
            thisTimeZone = TimeZone.getDefault();
            LocalTZA = thisTimeZone.getRawOffset();
        }
    }

    @Override
    public String getClassName()
    {
        return "Date";
    }

    @Override
    public Object getDefaultValue(Class typeHint)
    {
        if (typeHint == null)
            typeHint = ScriptRuntime.StringClass;
        return super.getDefaultValue(typeHint);
    }

    double getJSTimeValue()
    {
        return date;
    }

    @Override
    protected void fillConstructorProperties(IdFunctionObject ctor)
    {
        addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_now,
                              "now", 0);
        addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_parse,
                              "parse", 1);
        addIdFunctionProperty(ctor, DATE_TAG, ConstructorId_UTC,
                              "UTC", 7);
        super.fillConstructorProperties(ctor);
    }

    @Override
    protected void initPrototypeId(int id)
    {
        String s;
        int arity;
        switch (id) {
          case Id_constructor:        arity=7; s="constructor";        break;
          case Id_toString:           arity=0; s="toString";           break;
          case Id_toTimeString:       arity=0; s="toTimeString";       break;
          case Id_toDateString:       arity=0; s="toDateString";       break;
          case Id_toLocaleString:     arity=0; s="toLocaleString";     break;
          case Id_toLocaleTimeString: arity=0; s="toLocaleTimeString"; break;
          case Id_toLocaleDateString: arity=0; s="toLocaleDateString"; break;
          case Id_toUTCString:        arity=0; s="toUTCString";        break;
          case Id_toSource:           arity=0; s="toSource";           break;
          case Id_valueOf:            arity=0; s="valueOf";            break;
          case Id_getTime:            arity=0; s="getTime";            break;
          case Id_getYear:            arity=0; s="getYear";            break;
          case Id_getFullYear:        arity=0; s="getFullYear";        break;
          case Id_getUTCFullYear:     arity=0; s="getUTCFullYear";     break;
          case Id_getMonth:           arity=0; s="getMonth";           break;
          case Id_getUTCMonth:        arity=0; s="getUTCMonth";        break;
          case Id_getDate:            arity=0; s="getDate";            break;
          case Id_getUTCDate:         arity=0; s="getUTCDate";         break;
          case Id_getDay:             arity=0; s="getDay";             break;
          case Id_getUTCDay:          arity=0; s="getUTCDay";          break;
          case Id_getHours:           arity=0; s="getHours";           break;
          case Id_getUTCHours:        arity=0; s="getUTCHours";        break;
          case Id_getMinutes:         arity=0; s="getMinutes";         break;
          case Id_getUTCMinutes:      arity=0; s="getUTCMinutes";      break;
          case Id_getSeconds:         arity=0; s="getSeconds";         break;
          case Id_getUTCSeconds:      arity=0; s="getUTCSeconds";      break;
          case Id_getMilliseconds:    arity=0; s="getMilliseconds";    break;
          case Id_getUTCMilliseconds: arity=0; s="getUTCMilliseconds"; break;
          case Id_getTimezoneOffset:  arity=0; s="getTimezoneOffset";  break;
          case Id_setTime:            arity=1; s="setTime";            break;
          case Id_setMilliseconds:    arity=1; s="setMilliseconds";    break;
          case Id_setUTCMilliseconds: arity=1; s="setUTCMilliseconds"; break;
          case Id_setSeconds:         arity=2; s="setSeconds";         break;
          case Id_setUTCSeconds:      arity=2; s="setUTCSeconds";      break;
          case Id_setMinutes:         arity=3; s="setMinutes";         break;
          case Id_setUTCMinutes:      arity=3; s="setUTCMinutes";      break;
          case Id_setHours:           arity=4; s="setHours";           break;
          case Id_setUTCHours:        arity=4; s="setUTCHours";        break;
          case Id_setDate:            arity=1; s="setDate";            break;
          case Id_setUTCDate:         arity=1; s="setUTCDate";         break;
          case Id_setMonth:           arity=2; s="setMonth";           break;
          case Id_setUTCMonth:        arity=2; s="setUTCMonth";        break;
          case Id_setFullYear:        arity=3; s="setFullYear";        break;
          case Id_setUTCFullYear:     arity=3; s="setUTCFullYear";     break;
          case Id_setYear:            arity=1; s="setYear";            break;
          case Id_toISOString:        arity=0; s="toISOString";        break;
          case Id_toJSON:             arity=1; s="toJSON";             break;
          default: throw new IllegalArgumentException(String.valueOf(id));
        }
        initPrototypeMethod(DATE_TAG, id, s, arity);
    }

    @Override
    public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
                             Scriptable thisObj, Object[] args)
    {
        if (!f.hasTag(DATE_TAG)) {
            return super.execIdCall(f, cx, scope, thisObj, args);
        }
        int id = f.methodId();
        switch (id) {
          case ConstructorId_now:
            return ScriptRuntime.wrapNumber(now());

          case ConstructorId_parse:
            {
                String dataStr = ScriptRuntime.toString(args, 0);
                return ScriptRuntime.wrapNumber(date_parseString(dataStr));
            }

          case ConstructorId_UTC:
            return ScriptRuntime.wrapNumber(jsStaticFunction_UTC(args));

          case Id_constructor:
            {
                // if called as a function, just return a string
                // representing the current time.
                if (thisObj != null)
                    return date_format(now(), Id_toString);
                return jsConstructor(args);
            }

          case Id_toJSON:
            {
                final String toISOString = "toISOString";

                Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj);
                Object tv = ScriptRuntime.toPrimitive(o, ScriptRuntime.NumberClass);
                if (tv instanceof Number) {
                    double d = ((Number) tv).doubleValue();
                    if (d != d || Double.isInfinite(d)) {
                        return null;
                    }
                }
                Object toISO = ScriptableObject.getProperty(o, toISOString);
                if (toISO == NOT_FOUND) {
                    throw ScriptRuntime.typeError2("msg.function.not.found.in",
                            toISOString,
                            ScriptRuntime.toString(o));
                }
                if ( !(toISO instanceof Callable) ) {
                    throw ScriptRuntime.typeError3("msg.isnt.function.in",
                            toISOString,
                            ScriptRuntime.toString(o),
                            ScriptRuntime.toString(toISO));
                }
                Object result = ((Callable) toISO).call(cx, scope, o,
                            ScriptRuntime.emptyArgs);
                if ( !ScriptRuntime.isPrimitive(result) ) {
                    throw ScriptRuntime.typeError1("msg.toisostring.must.return.primitive",
                            ScriptRuntime.toString(result));
                }
                return result;
            }

        }

        // The rest of Date.prototype methods require thisObj to be Date

        if (!(thisObj instanceof NativeDate))
            throw incompatibleCallError(f);
        NativeDate realThis = (NativeDate)thisObj;
        double t = realThis.date;

        switch (id) {

          case Id_toString:
          case Id_toTimeString:
          case Id_toDateString:
            if (t == t) {
                return date_format(t, id);
            }
            return js_NaN_date_str;

          case Id_toLocaleString:
          case Id_toLocaleTimeString:
          case Id_toLocaleDateString:
            if (t == t) {
                return toLocale_helper(t, id);
            }
            return js_NaN_date_str;

          case Id_toUTCString:
            if (t == t) {
                return js_toUTCString(t);
            }
            return js_NaN_date_str;

          case Id_toSource:
            return "(new Date("+ScriptRuntime.toString(t)+"))";

          case Id_valueOf:
          case Id_getTime:
            return ScriptRuntime.wrapNumber(t);

          case Id_getYear:
          case Id_getFullYear:
          case Id_getUTCFullYear:
            if (t == t) {
                if (id != Id_getUTCFullYear) t = LocalTime(t);
                t = YearFromTime(t);
                if (id == Id_getYear) {
                    if (cx.hasFeature(Context.FEATURE_NON_ECMA_GET_YEAR)) {
                        if (1900 <= t && t < 2000) {
                            t -= 1900;
                        }
                    } else {
                        t -= 1900;
                    }
                }
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getMonth:
          case Id_getUTCMonth:
            if (t == t) {
                if (id == Id_getMonth) t = LocalTime(t);
                t = MonthFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getDate:
          case Id_getUTCDate:
            if (t == t) {
                if (id == Id_getDate) t = LocalTime(t);
                t = DateFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getDay:
          case Id_getUTCDay:
            if (t == t) {
                if (id == Id_getDay) t = LocalTime(t);
                t = WeekDay(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getHours:
          case Id_getUTCHours:
            if (t == t) {
                if (id == Id_getHours) t = LocalTime(t);
                t = HourFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getMinutes:
          case Id_getUTCMinutes:
            if (t == t) {
                if (id == Id_getMinutes) t = LocalTime(t);
                t = MinFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getSeconds:
          case Id_getUTCSeconds:
            if (t == t) {
                if (id == Id_getSeconds) t = LocalTime(t);
                t = SecFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getMilliseconds:
          case Id_getUTCMilliseconds:
            if (t == t) {
                if (id == Id_getMilliseconds) t = LocalTime(t);
                t = msFromTime(t);
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_getTimezoneOffset:
            if (t == t) {
                t = (t - LocalTime(t)) / msPerMinute;
            }
            return ScriptRuntime.wrapNumber(t);

          case Id_setTime:
            t = TimeClip(ScriptRuntime.toNumber(args, 0));
            realThis.date = t;
            return ScriptRuntime.wrapNumber(t);

          case Id_setMilliseconds:
          case Id_setUTCMilliseconds:
          case Id_setSeconds:
          case Id_setUTCSeconds:
          case Id_setMinutes:
          case Id_setUTCMinutes:
          case Id_setHours:
          case Id_setUTCHours:
            t = makeTime(t, args, id);
            realThis.date = t;
            return ScriptRuntime.wrapNumber(t);

          case Id_setDate:
          case Id_setUTCDate:
          case Id_setMonth:
          case Id_setUTCMonth:
          case Id_setFullYear:
          case Id_setUTCFullYear:
            t = makeDate(t, args, id);
            realThis.date = t;
            return ScriptRuntime.wrapNumber(t);

          case Id_setYear:
            {
                double year = ScriptRuntime.toNumber(args, 0);

                if (year != year || Double.isInfinite(year)) {
                    t = ScriptRuntime.NaN;
                } else {
                    if (t != t) {
                        t = 0;
                    } else {
                        t = LocalTime(t);
                    }

                    if (year >= 0 && year <= 99)
                        year += 1900;

                    double day = MakeDay(year, MonthFromTime(t),
                                         DateFromTime(t));
                    t = MakeDate(day, TimeWithinDay(t));
                    t = internalUTC(t);
                    t = TimeClip(t);
                }
            }
            realThis.date = t;
            return ScriptRuntime.wrapNumber(t);

          case Id_toISOString:
            if (t == t) {
                return js_toISOString(t);
            }
            String msg = ScriptRuntime.getMessage0("msg.invalid.date");
            throw ScriptRuntime.constructError("RangeError", msg);

          default: throw new IllegalArgumentException(String.valueOf(id));
        }

    }

    /* ECMA helper functions */

    private static final double HalfTimeDomain = 8.64e15;
    private static final double HoursPerDay    = 24.0;
    private static final double MinutesPerHour = 60.0;
    private static final double SecondsPerMinute = 60.0;
    private static final double msPerSecond    = 1000.0;
    private static final double MinutesPerDay  = (HoursPerDay * MinutesPerHour);
    private static final double SecondsPerDay  = (MinutesPerDay * SecondsPerMinute);
    private static final double SecondsPerHour = (MinutesPerHour * SecondsPerMinute);
    private static final double msPerDay       = (SecondsPerDay * msPerSecond);
    private static final double msPerHour      = (SecondsPerHour * msPerSecond);
    private static final double msPerMinute    = (SecondsPerMinute * msPerSecond);

    private static double Day(double t)
    {
        return Math.floor(t / msPerDay);
    }

    private static double TimeWithinDay(double t)
    {
        double result;
        result = t % msPerDay;
        if (result < 0)
            result += msPerDay;
        return result;
    }

    private static boolean IsLeapYear(int year)
    {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }

    /* math here has to be f.p, because we need
     *  floor((1968 - 1969) / 4) == -1
     */
    private static double DayFromYear(double y)
    {
        return ((365 * ((y)-1970) + Math.floor(((y)-1969)/4.0)
                 - Math.floor(((y)-1901)/100.0) + Math.floor(((y)-1601)/400.0)));
    }

    private static double TimeFromYear(double y)
    {
        return DayFromYear(y) * msPerDay;
    }

    private static int YearFromTime(double t)
    {
        if (Double.isInfinite(t) || Double.isNaN(t)) {
            return 0;
        }

        double y = Math.floor(t / (msPerDay * 365.2425)) + 1970;
        double t2 = TimeFromYear(y);

        /*
         * Adjust the year if the approximation was wrong.  Since the year was
         * computed using the average number of ms per year, it will usually
         * be wrong for dates within several hours of a year transition.
         */
        if (t2 > t) {
            y--;
        } else {
            if (t2 + msPerDay * DaysInYear(y) <= t)
                y++;
        }
        return (int)y;
    }

    private static double DayFromMonth(int m, int year)
    {
        int day = m * 30;

        if (m >= 7) { day += m / 2 - 1; }
        else if (m >= 2) { day += (m - 1) / 2 - 1; }
        else { day += m; }

        if (m >= 2 && IsLeapYear(year)) { ++day; }

        return day;
    }

    private static double DaysInYear(double year)
    {
        if (Double.isInfinite(year) || Double.isNaN(year)) {
            return ScriptRuntime.NaN;
        }
        return IsLeapYear((int)year) ? 366.0 : 365.0;
    }

    private static int DaysInMonth(int year, int month)
    {
        // month is 1-based for DaysInMonth!
        if (month == 2)
            return IsLeapYear(year) ? 29 : 28;
        return month >= 8
               ? 31 - (month & 1)
               : 30 + (month & 1);
    }

    private static int MonthFromTime(double t)
    {
        int year = YearFromTime(t);
        int d = (int)(Day(t) - DayFromYear(year));

        d -= 31 + 28;
        if (d < 0) {
            return (d < -28) ? 0 : 1;
        }

        if (IsLeapYear(year)) {
            if (d == 0)
                return 1; // 29 February
            --d;
        }

        // d: date count from 1 March
        int estimate = d / 30; // approx number of month since March
        int mstart;
        switch (estimate) {
            case 0: return 2;
            case 1: mstart = 31; break;
            case 2: mstart = 31+30; break;
            case 3: mstart = 31+30+31; break;
            case 4: mstart = 31+30+31+30; break;
            case 5: mstart = 31+30+31+30+31; break;
            case 6: mstart = 31+30+31+30+31+31; break;
            case 7: mstart = 31+30+31+30+31+31+30; break;
            case 8: mstart = 31+30+31+30+31+31+30+31; break;
            case 9: mstart = 31+30+31+30+31+31+30+31+30; break;
            case 10: return 11; //Late december
            default: throw Kit.codeBug();
        }
        // if d < mstart then real month since March == estimate - 1
        return (d >= mstart) ? estimate + 2 : estimate + 1;
    }

    private static int DateFromTime(double t)
    {
        int year = YearFromTime(t);
        int d = (int)(Day(t) - DayFromYear(year));

        d -= 31 + 28;
        if (d < 0) {
            return (d < -28) ? d + 31 + 28 + 1 : d + 28 + 1;
        }

        if (IsLeapYear(year)) {
            if (d == 0)
                return 29; // 29 February
            --d;
        }

        // d: date count from 1 March
        int mdays, mstart;
        switch (Math.round(d / 30)) { // approx number of month since March
            case 0: return d + 1;
            case 1: mdays = 31; mstart = 31; break;
            case 2: mdays = 30; mstart = 31+30; break;
            case 3: mdays = 31; mstart = 31+30+31; break;
            case 4: mdays = 30; mstart = 31+30+31+30; break;
            case 5: mdays = 31; mstart = 31+30+31+30+31; break;
            case 6: mdays = 31; mstart = 31+30+31+30+31+31; break;
            case 7: mdays = 30; mstart = 31+30+31+30+31+31+30; break;
            case 8: mdays = 31; mstart = 31+30+31+30+31+31+30+31; break;
            case 9: mdays = 30; mstart = 31+30+31+30+31+31+30+31+30; break;
            case 10:
                return d - (31+30+31+30+31+31+30+31+30) + 1; //Late december
            default: throw Kit.codeBug();
        }
        d -= mstart;
        if (d < 0) {
            // wrong estimate: sfhift to previous month
            d += mdays;
        }
        return d + 1;
     }

    private static int WeekDay(double t)
    {
        double result;
        result = Day(t) + 4;
        result = result % 7;
        if (result < 0)
            result += 7;
        return (int) result;
    }

    private static double now()
    {
        return System.currentTimeMillis();
    }

    private static double DaylightSavingTA(double t)
    {
        // Another workaround!  The JRE doesn't seem to know about DST
        // before year 1 AD, so we map to equivalent dates for the
        // purposes of finding DST. To be safe, we do this for years
        // before 1970.
        if (t < 0.0) {
            int year = EquivalentYear(YearFromTime(t));
            double day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
            t = MakeDate(day, TimeWithinDay(t));
        }
        Date date = new Date((long) t);
        if (thisTimeZone.inDaylightTime(date))
            return msPerHour;
        else
            return 0;
    }

    /*
     * Find a year for which any given date will fall on the same weekday.
     *
     * This function should be used with caution when used other than
     * for determining DST; it hasn't been proven not to produce an
     * incorrect year for times near year boundaries.
     */
    private static int EquivalentYear(int year)
    {
        int day = (int) DayFromYear(year) + 4;
        day = day % 7;
        if (day < 0)
            day += 7;
        // Years and leap years on which Jan 1 is a Sunday, Monday, etc.
        if (IsLeapYear(year)) {
            switch (day) {
                case 0: return 1984;
                case 1: return 1996;
                case 2: return 1980;
                case 3: return 1992;
                case 4: return 1976;
                case 5: return 1988;
                case 6: return 1972;
            }
        } else {
            switch (day) {
                case 0: return 1978;
                case 1: return 1973;
                case 2: return 1985;
                case 3: return 1986;
                case 4: return 1981;
                case 5: return 1971;
                case 6: return 1977;
            }
        }
        // Unreachable
        throw Kit.codeBug();
    }

    private static double LocalTime(double t)
    {
        return t + LocalTZA + DaylightSavingTA(t);
    }

    private static double internalUTC(double t)
    {
        return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
    }

    private static int HourFromTime(double t)
    {
        double result;
        result = Math.floor(t / msPerHour) % HoursPerDay;
        if (result < 0)
            result += HoursPerDay;
        return (int) result;
    }

    private static int MinFromTime(double t)
    {
        double result;
        result = Math.floor(t / msPerMinute) % MinutesPerHour;
        if (result < 0)
            result += MinutesPerHour;
        return (int) result;
    }

    private static int SecFromTime(double t)
    {
        double result;
        result = Math.floor(t / msPerSecond) % SecondsPerMinute;
        if (result < 0)
            result += SecondsPerMinute;
        return (int) result;
    }

    private static int msFromTime(double t)
    {
        double result;
        result =  t % msPerSecond;
        if (result < 0)
            result += msPerSecond;
        return (int) result;
    }

    private static double MakeTime(double hour, double min,
                                   double sec, double ms)
    {
        return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec)
            * msPerSecond + ms;
    }

    private static double MakeDay(double year, double month, double date)
    {
        year += Math.floor(month / 12);

        month = month % 12;
        if (month < 0)
            month += 12;

        double yearday = Math.floor(TimeFromYear(year) / msPerDay);
        double monthday = DayFromMonth((int)month, (int)year);

        return yearday + monthday + date - 1;
    }

    private static double MakeDate(double day, double time)
    {
        return day * msPerDay + time;
    }

    private static double TimeClip(double d)
    {
        if (d != d ||
            d == Double.POSITIVE_INFINITY ||
            d == Double.NEGATIVE_INFINITY ||
            Math.abs(d) > HalfTimeDomain)
        {
            return ScriptRuntime.NaN;
        }
        if (d > 0.0)
            return Math.floor(d + 0.);
        else
            return Math.ceil(d + 0.);
    }

    /* end of ECMA helper functions */

    /* find UTC time from given date... no 1900 correction! */
    private static double date_msecFromDate(double year, double mon,
                                            double mday, double hour,
                                            double min, double sec,
                                            double msec)
    {
        double day;
        double time;
        double result;

        day = MakeDay(year, mon, mday);
        time = MakeTime(hour, min, sec, msec);
        result = MakeDate(day, time);
        return result;
    }

    /* compute the time in msec (unclipped) from the given args */
    private static final int MAXARGS = 7;
    private static double date_msecFromArgs(Object[] args)
    {
        double array[] = new double[MAXARGS];
        int loop;
        double d;

        for (loop = 0; loop < MAXARGS; loop++) {
            if (loop < args.length) {
                d = ScriptRuntime.toNumber(args[loop]);
                if (d != d || Double.isInfinite(d)) {
                    return ScriptRuntime.NaN;
                }
                array[loop] = ScriptRuntime.toInteger(args[loop]);
            } else {
                if (loop == 2) {
                    array[loop] = 1; /* Default the date argument to 1. */
                } else {
                    array[loop] = 0;
                }
            }
        }

        /* adjust 2-digit years into the 20th century */
        if (array[0] >= 0 && array[0] <= 99)
            array[0] += 1900;

        return date_msecFromDate(array[0], array[1], array[2],
                                 array[3], array[4], array[5], array[6]);
    }

    private static double jsStaticFunction_UTC(Object[] args)
    {
        return TimeClip(date_msecFromArgs(args));
    }

    /**
     * 15.9.1.15 Date Time String Format
* Parse input string according to simplified ISO-8601 Extended Format: *
    *
  • YYYY-MM-DD'T'HH:mm:ss.sss'Z'
  • *
  • or YYYY-MM-DD'T'HH:mm:ss.sss[+-]hh:mm
  • *
*/ private static double parseISOString(String s) { // we use a simple state machine to parse the input string final int ERROR = -1; final int YEAR = 0, MONTH = 1, DAY = 2; final int HOUR = 3, MIN = 4, SEC = 5, MSEC = 6; final int TZHOUR = 7, TZMIN = 8; int state = YEAR; // default values per [15.9.1.15 Date Time String Format] int[] values = { 1970, 1, 1, 0, 0, 0, 0, -1, -1 }; int yearlen = 4, yearmod = 1, tzmod = 1; int i = 0, len = s.length(); if (len != 0) { char c = s.charAt(0); if (c == '+' || c == '-') { // 15.9.1.15.1 Extended years i += 1; yearlen = 6; yearmod = (c == '-') ? -1 : 1; } else if (c == 'T') { // time-only forms no longer in spec, but follow spidermonkey here i += 1; state = HOUR; } } loop: while (state != ERROR) { int m = i + (state == YEAR ? yearlen : state == MSEC ? 3 : 2); if (m > len) { state = ERROR; break; } int value = 0; for (; i < m; ++i) { char c = s.charAt(i); if (c < '0' || c > '9') { state = ERROR; break loop; } value = 10 * value + (c - '0'); } values[state] = value; if (i == len) { // reached EOF, check for end state switch (state) { case HOUR: case TZHOUR: state = ERROR; } break; } char c = s.charAt(i++); if (c == 'Z') { // handle abbrevation for UTC timezone values[TZHOUR] = 0; values[TZMIN] = 0; switch (state) { case MIN: case SEC: case MSEC: break; default: state = ERROR; } break; } // state transition switch (state) { case YEAR: case MONTH: state = (c == '-' ? state + 1 : c == 'T' ? HOUR : ERROR); break; case DAY: state = (c == 'T' ? HOUR : ERROR); break; case HOUR: state = (c == ':' ? MIN : ERROR); break; case TZHOUR: // state = (c == ':' ? state + 1 : ERROR); // Non-standard extension, https://bugzilla.mozilla.org/show_bug.cgi?id=682754 if (c != ':') { // back off by one and try to read without ':' separator i -= 1; } state = TZMIN; break; case MIN: state = (c == ':' ? SEC : c == '+' || c == '-' ? TZHOUR : ERROR); break; case SEC: state = (c == '.' ? MSEC : c == '+' || c == '-' ? TZHOUR : ERROR); break; case MSEC: state = (c == '+' || c == '-' ? TZHOUR : ERROR); break; case TZMIN: state = ERROR; break; } if (state == TZHOUR) { // save timezone modificator tzmod = (c == '-') ? -1 : 1; } } syntax: { // error or unparsed characters if (state == ERROR || i != len) break syntax; // check values int year = values[YEAR], month = values[MONTH], day = values[DAY]; int hour = values[HOUR], min = values[MIN], sec = values[SEC], msec = values[MSEC]; int tzhour = values[TZHOUR], tzmin = values[TZMIN]; if (year > 275943 // ceil(1e8/365) + 1970 = 275943 || (month < 1 || month > 12) || (day < 1 || day > DaysInMonth(year, month)) || hour > 24 || (hour == 24 && (min > 0 || sec > 0 || msec > 0)) || min > 59 || sec > 59 || tzhour > 23 || tzmin > 59 ) { break syntax; } // valid ISO-8601 format, compute date in milliseconds double date = date_msecFromDate(year * yearmod, month - 1, day, hour, min, sec, msec); if (tzhour == -1) { // Spec says to use UTC timezone, the following bug report says // that local timezone was meant to be used. Stick with spec for now. // https://bugs.ecmascript.org/show_bug.cgi?id=112 // date = internalUTC(date); } else { date -= (tzhour * 60 + tzmin) * msPerMinute * tzmod; } if (date < -HalfTimeDomain || date > HalfTimeDomain) break syntax; return date; } // invalid ISO-8601 format, return NaN return ScriptRuntime.NaN; } private static double date_parseString(String s) { double d = parseISOString(s); if (d == d) { return d; } int year = -1; int mon = -1; int mday = -1; int hour = -1; int min = -1; int sec = -1; char c = 0; char si = 0; int i = 0; int n = -1; double tzoffset = -1; char prevc = 0; int limit = 0; boolean seenplusminus = false; limit = s.length(); while (i < limit) { c = s.charAt(i); i++; if (c <= ' ' || c == ',' || c == '-') { if (i < limit) { si = s.charAt(i); if (c == '-' && '0' <= si && si <= '9') { prevc = c; } } continue; } if (c == '(') { /* comments) */ int depth = 1; while (i < limit) { c = s.charAt(i); i++; if (c == '(') depth++; else if (c == ')') if (--depth <= 0) break; } continue; } if ('0' <= c && c <= '9') { n = c - '0'; while (i < limit && '0' <= (c = s.charAt(i)) && c <= '9') { n = n * 10 + c - '0'; i++; } /* allow TZA before the year, so * 'Wed Nov 05 21:49:11 GMT-0800 1997' * works */ /* uses of seenplusminus allow : in TZA, so Java * no-timezone style of GMT+4:30 works */ if ((prevc == '+' || prevc == '-')/* && year>=0 */) { /* make ':' case below change tzoffset */ seenplusminus = true; /* offset */ if (n < 24) n = n * 60; /* EG. "GMT-3" */ else n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */ if (prevc == '+') /* plus means east of GMT */ n = -n; if (tzoffset != 0 && tzoffset != -1) return ScriptRuntime.NaN; tzoffset = n; } else if (n >= 70 || (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) { if (year >= 0) return ScriptRuntime.NaN; else if (c <= ' ' || c == ',' || c == '/' || i >= limit) year = n < 100 ? n + 1900 : n; else return ScriptRuntime.NaN; } else if (c == ':') { if (hour < 0) hour = /*byte*/ n; else if (min < 0) min = /*byte*/ n; else return ScriptRuntime.NaN; } else if (c == '/') { if (mon < 0) mon = /*byte*/ n-1; else if (mday < 0) mday = /*byte*/ n; else return ScriptRuntime.NaN; } else if (i < limit && c != ',' && c > ' ' && c != '-') { return ScriptRuntime.NaN; } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */ if (tzoffset < 0) tzoffset -= n; else tzoffset += n; } else if (hour >= 0 && min < 0) { min = /*byte*/ n; } else if (min >= 0 && sec < 0) { sec = /*byte*/ n; } else if (mday < 0) { mday = /*byte*/ n; } else { return ScriptRuntime.NaN; } prevc = 0; } else if (c == '/' || c == ':' || c == '+' || c == '-') { prevc = c; } else { int st = i - 1; while (i < limit) { c = s.charAt(i); if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))) break; i++; } int letterCount = i - st; if (letterCount < 2) return ScriptRuntime.NaN; /* * Use ported code from jsdate.c rather than the locale-specific * date-parsing code from Java, to keep js and rhino consistent. * Is this the right strategy? */ String wtb = "am;pm;" +"monday;tuesday;wednesday;thursday;friday;" +"saturday;sunday;" +"january;february;march;april;may;june;" +"july;august;september;october;november;december;" +"gmt;ut;utc;est;edt;cst;cdt;mst;mdt;pst;pdt;"; int index = 0; for (int wtbOffset = 0; ;) { int wtbNext = wtb.indexOf(';', wtbOffset); if (wtbNext < 0) return ScriptRuntime.NaN; if (wtb.regionMatches(true, wtbOffset, s, st, letterCount)) break; wtbOffset = wtbNext + 1; ++index; } if (index < 2) { /* * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as * 12:30, instead of blindly adding 12 if PM. */ if (hour > 12 || hour < 0) { return ScriptRuntime.NaN; } else if (index == 0) { // AM if (hour == 12) hour = 0; } else { // PM if (hour != 12) hour += 12; } } else if ((index -= 2) < 7) { // ignore week days } else if ((index -= 7) < 12) { // month if (mon < 0) { mon = index; } else { return ScriptRuntime.NaN; } } else { index -= 12; // timezones switch (index) { case 0 /* gmt */: tzoffset = 0; break; case 1 /* ut */: tzoffset = 0; break; case 2 /* utc */: tzoffset = 0; break; case 3 /* est */: tzoffset = 5 * 60; break; case 4 /* edt */: tzoffset = 4 * 60; break; case 5 /* cst */: tzoffset = 6 * 60; break; case 6 /* cdt */: tzoffset = 5 * 60; break; case 7 /* mst */: tzoffset = 7 * 60; break; case 8 /* mdt */: tzoffset = 6 * 60; break; case 9 /* pst */: tzoffset = 8 * 60; break; case 10 /* pdt */:tzoffset = 7 * 60; break; default: Kit.codeBug(); } } } } if (year < 0 || mon < 0 || mday < 0) return ScriptRuntime.NaN; if (sec < 0) sec = 0; if (min < 0) min = 0; if (hour < 0) hour = 0; double msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0); if (tzoffset == -1) { /* no time zone specified, have to use local */ return internalUTC(msec); } else { return msec + tzoffset * msPerMinute; } } private static String date_format(double t, int methodId) { StringBuilder result = new StringBuilder(60); double local = LocalTime(t); /* Tue Oct 31 09:41:40 GMT-0800 (PST) 2000 */ /* Tue Oct 31 2000 */ /* 09:41:40 GMT-0800 (PST) */ if (methodId != Id_toTimeString) { appendWeekDayName(result, WeekDay(local)); result.append(' '); appendMonthName(result, MonthFromTime(local)); result.append(' '); append0PaddedUint(result, DateFromTime(local), 2); result.append(' '); int year = YearFromTime(local); if (year < 0) { result.append('-'); year = -year; } append0PaddedUint(result, year, 4); if (methodId != Id_toDateString) result.append(' '); } if (methodId != Id_toDateString) { append0PaddedUint(result, HourFromTime(local), 2); result.append(':'); append0PaddedUint(result, MinFromTime(local), 2); result.append(':'); append0PaddedUint(result, SecFromTime(local), 2); // offset from GMT in minutes. The offset includes daylight // savings, if it applies. int minutes = (int) Math.floor((LocalTZA + DaylightSavingTA(t)) / msPerMinute); // map 510 minutes to 0830 hours int offset = (minutes / 60) * 100 + minutes % 60; if (offset > 0) { result.append(" GMT+"); } else { result.append(" GMT-"); offset = -offset; } append0PaddedUint(result, offset, 4); if (timeZoneFormatter == null) timeZoneFormatter = new SimpleDateFormat("zzz"); // Find an equivalent year before getting the timezone // comment. See DaylightSavingTA. if (t < 0.0) { int equiv = EquivalentYear(YearFromTime(local)); double day = MakeDay(equiv, MonthFromTime(t), DateFromTime(t)); t = MakeDate(day, TimeWithinDay(t)); } result.append(" ("); Date date = new Date((long) t); synchronized (timeZoneFormatter) { result.append(timeZoneFormatter.format(date)); } result.append(')'); } return result.toString(); } /* the javascript constructor */ private static Object jsConstructor(Object[] args) { NativeDate obj = new NativeDate(); // if called as a constructor with no args, // return a new Date with the current time. if (args.length == 0) { obj.date = now(); return obj; } // if called with just one arg - if (args.length == 1) { Object arg0 = args[0]; if (arg0 instanceof Scriptable) arg0 = ((Scriptable) arg0).getDefaultValue(null); double date; if (arg0 instanceof CharSequence) { // it's a string; parse it. date = date_parseString(arg0.toString()); } else { // if it's not a string, use it as a millisecond date date = ScriptRuntime.toNumber(arg0); } obj.date = TimeClip(date); return obj; } double time = date_msecFromArgs(args); if (!Double.isNaN(time) && !Double.isInfinite(time)) time = TimeClip(internalUTC(time)); obj.date = time; return obj; } private static String toLocale_helper(double t, int methodId) { DateFormat formatter; switch (methodId) { case Id_toLocaleString: if (localeDateTimeFormatter == null) { localeDateTimeFormatter = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); } formatter = localeDateTimeFormatter; break; case Id_toLocaleTimeString: if (localeTimeFormatter == null) { localeTimeFormatter = DateFormat.getTimeInstance(DateFormat.LONG); } formatter = localeTimeFormatter; break; case Id_toLocaleDateString: if (localeDateFormatter == null) { localeDateFormatter = DateFormat.getDateInstance(DateFormat.LONG); } formatter = localeDateFormatter; break; default: throw new AssertionError(); // unreachable } synchronized (formatter) { return formatter.format(new Date((long) t)); } } private static String js_toUTCString(double date) { StringBuilder result = new StringBuilder(60); appendWeekDayName(result, WeekDay(date)); result.append(", "); append0PaddedUint(result, DateFromTime(date), 2); result.append(' '); appendMonthName(result, MonthFromTime(date)); result.append(' '); int year = YearFromTime(date); if (year < 0) { result.append('-'); year = -year; } append0PaddedUint(result, year, 4); result.append(' '); append0PaddedUint(result, HourFromTime(date), 2); result.append(':'); append0PaddedUint(result, MinFromTime(date), 2); result.append(':'); append0PaddedUint(result, SecFromTime(date), 2); result.append(" GMT"); return result.toString(); } private static String js_toISOString(double t) { StringBuilder result = new StringBuilder(27); int year = YearFromTime(t); if (year < 0) { result.append('-'); append0PaddedUint(result, -year, 6); } else if (year > 9999) { append0PaddedUint(result, year, 6); } else { append0PaddedUint(result, year, 4); } result.append('-'); append0PaddedUint(result, MonthFromTime(t) + 1, 2); result.append('-'); append0PaddedUint(result, DateFromTime(t), 2); result.append('T'); append0PaddedUint(result, HourFromTime(t), 2); result.append(':'); append0PaddedUint(result, MinFromTime(t), 2); result.append(':'); append0PaddedUint(result, SecFromTime(t), 2); result.append('.'); append0PaddedUint(result, msFromTime(t), 3); result.append('Z'); return result.toString(); } private static void append0PaddedUint(StringBuilder sb, int i, int minWidth) { if (i < 0) Kit.codeBug(); int scale = 1; --minWidth; if (i >= 10) { if (i < 1000 * 1000 * 1000) { for (;;) { int newScale = scale * 10; if (i < newScale) { break; } --minWidth; scale = newScale; } } else { // Separated case not to check against 10 * 10^9 overflow minWidth -= 9; scale = 1000 * 1000 * 1000; } } while (minWidth > 0) { sb.append('0'); --minWidth; } while (scale != 1) { sb.append((char)('0' + (i / scale))); i %= scale; scale /= 10; } sb.append((char)('0' + i)); } private static void appendMonthName(StringBuilder sb, int index) { // Take advantage of the fact that all month abbreviations // have the same length to minimize amount of strings runtime has // to keep in memory String months = "Jan"+"Feb"+"Mar"+"Apr"+"May"+"Jun" +"Jul"+"Aug"+"Sep"+"Oct"+"Nov"+"Dec"; index *= 3; for (int i = 0; i != 3; ++i) { sb.append(months.charAt(index + i)); } } private static void appendWeekDayName(StringBuilder sb, int index) { String days = "Sun"+"Mon"+"Tue"+"Wed"+"Thu"+"Fri"+"Sat"; index *= 3; for (int i = 0; i != 3; ++i) { sb.append(days.charAt(index + i)); } } private static double makeTime(double date, Object[] args, int methodId) { if (args.length == 0) { /* * Satisfy the ECMA rule that if a function is called with * fewer arguments than the specified formal arguments, the * remaining arguments are set to undefined. Seems like all * the Date.setWhatever functions in ECMA are only varargs * beyond the first argument; this should be set to undefined * if it's not given. This means that "d = new Date(); * d.setMilliseconds()" returns NaN. Blech. */ return ScriptRuntime.NaN; } int maxargs; boolean local = true; switch (methodId) { case Id_setUTCMilliseconds: local = false; // fallthrough case Id_setMilliseconds: maxargs = 1; break; case Id_setUTCSeconds: local = false; // fallthrough case Id_setSeconds: maxargs = 2; break; case Id_setUTCMinutes: local = false; // fallthrough case Id_setMinutes: maxargs = 3; break; case Id_setUTCHours: local = false; // fallthrough case Id_setHours: maxargs = 4; break; default: throw Kit.codeBug(); } boolean hasNaN = false; int numNums = args.length < maxargs ? args.length : maxargs; assert numNums <= 4; double[] nums = new double[4]; for (int i = 0; i < numNums; i++) { double d = ScriptRuntime.toNumber(args[i]); if (d != d || Double.isInfinite(d)) { hasNaN = true; } else { nums[i] = ScriptRuntime.toInteger(d); } } // just return NaN if the date is already NaN, // limit checks that happen in MakeTime in ECMA. if (hasNaN || date != date) { return ScriptRuntime.NaN; } int i = 0, stop = numNums; double hour, min, sec, msec; double lorutime; /* Local or UTC version of date */ if (local) lorutime = LocalTime(date); else lorutime = date; if (maxargs >= 4 && i < stop) hour = nums[i++]; else hour = HourFromTime(lorutime); if (maxargs >= 3 && i < stop) min = nums[i++]; else min = MinFromTime(lorutime); if (maxargs >= 2 && i < stop) sec = nums[i++]; else sec = SecFromTime(lorutime); if (maxargs >= 1 && i < stop) msec = nums[i++]; else msec = msFromTime(lorutime); double time = MakeTime(hour, min, sec, msec); double result = MakeDate(Day(lorutime), time); if (local) result = internalUTC(result); return TimeClip(result); } private static double makeDate(double date, Object[] args, int methodId) { /* see complaint about ECMA in date_MakeTime */ if (args.length == 0) { return ScriptRuntime.NaN; } int maxargs; boolean local = true; switch (methodId) { case Id_setUTCDate: local = false; // fallthrough case Id_setDate: maxargs = 1; break; case Id_setUTCMonth: local = false; // fallthrough case Id_setMonth: maxargs = 2; break; case Id_setUTCFullYear: local = false; // fallthrough case Id_setFullYear: maxargs = 3; break; default: throw Kit.codeBug(); } boolean hasNaN = false; int numNums = args.length < maxargs ? args.length : maxargs; assert 1 <= numNums && numNums <= 3; double[] nums = new double[3]; for (int i = 0; i < numNums; i++) { double d = ScriptRuntime.toNumber(args[i]); if (d != d || Double.isInfinite(d)) { hasNaN = true; } else { nums[i] = ScriptRuntime.toInteger(d); } } // limit checks that happen in MakeTime in ECMA. if (hasNaN) { return ScriptRuntime.NaN; } int i = 0, stop = numNums; double year, month, day; double lorutime; /* Local or UTC version of date */ /* return NaN if date is NaN and we're not setting the year, * If we are, use 0 as the time. */ if (date != date) { if (maxargs < 3) { return ScriptRuntime.NaN; } else { lorutime = 0; } } else { if (local) lorutime = LocalTime(date); else lorutime = date; } if (maxargs >= 3 && i < stop) year = nums[i++]; else year = YearFromTime(lorutime); if (maxargs >= 2 && i < stop) month = nums[i++]; else month = MonthFromTime(lorutime); if (maxargs >= 1 && i < stop) day = nums[i++]; else day = DateFromTime(lorutime); day = MakeDay(year, month, day); /* day within year */ double result = MakeDate(day, TimeWithinDay(lorutime)); if (local) result = internalUTC(result); return TimeClip(result); } // #string_id_map# @Override protected int findPrototypeId(String s) { int id; // #generated# Last update: 2009-07-22 05:44:02 EST L0: { id = 0; String X = null; int c; L: switch (s.length()) { case 6: c=s.charAt(0); if (c=='g') { X="getDay";id=Id_getDay; } else if (c=='t') { X="toJSON";id=Id_toJSON; } break L; case 7: switch (s.charAt(3)) { case 'D': c=s.charAt(0); if (c=='g') { X="getDate";id=Id_getDate; } else if (c=='s') { X="setDate";id=Id_setDate; } break L; case 'T': c=s.charAt(0); if (c=='g') { X="getTime";id=Id_getTime; } else if (c=='s') { X="setTime";id=Id_setTime; } break L; case 'Y': c=s.charAt(0); if (c=='g') { X="getYear";id=Id_getYear; } else if (c=='s') { X="setYear";id=Id_setYear; } break L; case 'u': X="valueOf";id=Id_valueOf; break L; } break L; case 8: switch (s.charAt(3)) { case 'H': c=s.charAt(0); if (c=='g') { X="getHours";id=Id_getHours; } else if (c=='s') { X="setHours";id=Id_setHours; } break L; case 'M': c=s.charAt(0); if (c=='g') { X="getMonth";id=Id_getMonth; } else if (c=='s') { X="setMonth";id=Id_setMonth; } break L; case 'o': X="toSource";id=Id_toSource; break L; case 't': X="toString";id=Id_toString; break L; } break L; case 9: X="getUTCDay";id=Id_getUTCDay; break L; case 10: c=s.charAt(3); if (c=='M') { c=s.charAt(0); if (c=='g') { X="getMinutes";id=Id_getMinutes; } else if (c=='s') { X="setMinutes";id=Id_setMinutes; } } else if (c=='S') { c=s.charAt(0); if (c=='g') { X="getSeconds";id=Id_getSeconds; } else if (c=='s') { X="setSeconds";id=Id_setSeconds; } } else if (c=='U') { c=s.charAt(0); if (c=='g') { X="getUTCDate";id=Id_getUTCDate; } else if (c=='s') { X="setUTCDate";id=Id_setUTCDate; } } break L; case 11: switch (s.charAt(3)) { case 'F': c=s.charAt(0); if (c=='g') { X="getFullYear";id=Id_getFullYear; } else if (c=='s') { X="setFullYear";id=Id_setFullYear; } break L; case 'M': X="toGMTString";id=Id_toGMTString; break L; case 'S': X="toISOString";id=Id_toISOString; break L; case 'T': X="toUTCString";id=Id_toUTCString; break L; case 'U': c=s.charAt(0); if (c=='g') { c=s.charAt(9); if (c=='r') { X="getUTCHours";id=Id_getUTCHours; } else if (c=='t') { X="getUTCMonth";id=Id_getUTCMonth; } } else if (c=='s') { c=s.charAt(9); if (c=='r') { X="setUTCHours";id=Id_setUTCHours; } else if (c=='t') { X="setUTCMonth";id=Id_setUTCMonth; } } break L; case 's': X="constructor";id=Id_constructor; break L; } break L; case 12: c=s.charAt(2); if (c=='D') { X="toDateString";id=Id_toDateString; } else if (c=='T') { X="toTimeString";id=Id_toTimeString; } break L; case 13: c=s.charAt(0); if (c=='g') { c=s.charAt(6); if (c=='M') { X="getUTCMinutes";id=Id_getUTCMinutes; } else if (c=='S') { X="getUTCSeconds";id=Id_getUTCSeconds; } } else if (c=='s') { c=s.charAt(6); if (c=='M') { X="setUTCMinutes";id=Id_setUTCMinutes; } else if (c=='S') { X="setUTCSeconds";id=Id_setUTCSeconds; } } break L; case 14: c=s.charAt(0); if (c=='g') { X="getUTCFullYear";id=Id_getUTCFullYear; } else if (c=='s') { X="setUTCFullYear";id=Id_setUTCFullYear; } else if (c=='t') { X="toLocaleString";id=Id_toLocaleString; } break L; case 15: c=s.charAt(0); if (c=='g') { X="getMilliseconds";id=Id_getMilliseconds; } else if (c=='s') { X="setMilliseconds";id=Id_setMilliseconds; } break L; case 17: X="getTimezoneOffset";id=Id_getTimezoneOffset; break L; case 18: c=s.charAt(0); if (c=='g') { X="getUTCMilliseconds";id=Id_getUTCMilliseconds; } else if (c=='s') { X="setUTCMilliseconds";id=Id_setUTCMilliseconds; } else if (c=='t') { c=s.charAt(8); if (c=='D') { X="toLocaleDateString";id=Id_toLocaleDateString; } else if (c=='T') { X="toLocaleTimeString";id=Id_toLocaleTimeString; } } break L; } if (X!=null && X!=s && !X.equals(s)) id = 0; break L0; } // #/generated# return id; } private static final int ConstructorId_now = -3, ConstructorId_parse = -2, ConstructorId_UTC = -1, Id_constructor = 1, Id_toString = 2, Id_toTimeString = 3, Id_toDateString = 4, Id_toLocaleString = 5, Id_toLocaleTimeString = 6, Id_toLocaleDateString = 7, Id_toUTCString = 8, Id_toSource = 9, Id_valueOf = 10, Id_getTime = 11, Id_getYear = 12, Id_getFullYear = 13, Id_getUTCFullYear = 14, Id_getMonth = 15, Id_getUTCMonth = 16, Id_getDate = 17, Id_getUTCDate = 18, Id_getDay = 19, Id_getUTCDay = 20, Id_getHours = 21, Id_getUTCHours = 22, Id_getMinutes = 23, Id_getUTCMinutes = 24, Id_getSeconds = 25, Id_getUTCSeconds = 26, Id_getMilliseconds = 27, Id_getUTCMilliseconds = 28, Id_getTimezoneOffset = 29, Id_setTime = 30, Id_setMilliseconds = 31, Id_setUTCMilliseconds = 32, Id_setSeconds = 33, Id_setUTCSeconds = 34, Id_setMinutes = 35, Id_setUTCMinutes = 36, Id_setHours = 37, Id_setUTCHours = 38, Id_setDate = 39, Id_setUTCDate = 40, Id_setMonth = 41, Id_setUTCMonth = 42, Id_setFullYear = 43, Id_setUTCFullYear = 44, Id_setYear = 45, Id_toISOString = 46, Id_toJSON = 47, MAX_PROTOTYPE_ID = Id_toJSON; private static final int Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6 // #/string_id_map# /* cached values */ private static TimeZone thisTimeZone; private static double LocalTZA; private static DateFormat timeZoneFormatter; private static DateFormat localeDateTimeFormatter; private static DateFormat localeDateFormatter; private static DateFormat localeTimeFormatter; private double date; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy