FreeWRL

 view release on metacpan or  search on metacpan

JS/js/jsdate.c  view on Meta::CPAN


    if (d <= (next = 30))
        return d + 1;
    step = next;
    next += (InLeapYear(t) ? 29 : 28);
    if (d <= next)
        return d - step;
    step = next;
    if (d <= (next += 31))
        return d - step;
    step = next;
    if (d <= (next += 30))
        return d - step;
    step = next;
    if (d <= (next += 31))
        return d - step;
    step = next;
    if (d <= (next += 30))
        return d - step;
    step = next;
    if (d <= (next += 31))
        return d - step;
    step = next;
    if (d <= (next += 31))
        return d - step;
    step = next;
    if (d <= (next += 30))
        return d - step;
    step = next;
    if (d <= (next += 31))
        return d - step;
    step = next;
    if (d <= (next += 30))
        return d - step;
    step = next;
    return d - step;
}

static intN
WeekDay(jsdouble t)
{
    jsint result;
    result = (jsint) Day(t) + 4;
    result = result % 7;
    if (result < 0)
        result += 7;
    return (intN) result;
}

/* LocalTZA gets set by js_InitDateClass() */
static jsdouble LocalTZA;

static jsdouble
DaylightSavingTA(jsdouble t)
{
    int64 PR_t;
    int64 ms2us;
    int64 offset;
    jsdouble result;

    /* abort if NaN */
    if (JSDOUBLE_IS_NaN(t))
        return t;

    /* put our t in an LL, and map it to usec for prtime */
    LL_D2L(PR_t, t);
    LL_I2L(ms2us, PR_USEC_PER_MSEC);
    LL_MUL(PR_t, PR_t, ms2us);

    offset = PR_DSTOffset(PR_t);

    LL_DIV(offset, offset, ms2us);
    LL_L2D(result, offset);
    return result;
}

#define LocalTime(t)    ((t) + LocalTZA + DaylightSavingTA(t))

static jsdouble
UTC(jsdouble t)
{
    return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
}

static intN
HourFromTime(jsdouble t)
{
    intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay);
    if (result < 0)
        result += (intN)HoursPerDay;
    return result;
}

static intN
MinFromTime(jsdouble t)
{
    intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour);
    if (result < 0)
        result += (intN)MinutesPerHour;
    return result;
}

static intN
SecFromTime(jsdouble t)
{
    intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute);
    if (result < 0)
        result += (intN)SecondsPerMinute;
    return result;
}

static intN
msFromTime(jsdouble t)
{
    intN result = (intN) fmod(t, msPerSecond);
    if (result < 0)
        result += (intN)msPerSecond;
    return result;
}

#define MakeTime(hour, min, sec, ms) \
(((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms)

static jsdouble
MakeDay(jsdouble year, jsdouble month, jsdouble date)
{
    jsdouble result;
    JSBool leap;
    jsdouble yearday;
    jsdouble monthday;

    year += floor(month / 12);

    month = fmod(month, 12);
    if (month < 0)
        month += 12;

    leap = (DaysInYear((jsint) year) == 366);

    yearday = floor(TimeFromYear(year) / msPerDay);
    monthday = DayFromMonth(month, leap);

    result = yearday
             + monthday
             + date - 1;
    return result;
}

#define MakeDate(day, time) (day * msPerDay + time)

#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
                      && !((d < 0 ? -d : d) > HalfTimeDomain)) \
                     ? js_DoubleToInteger(d + (+0.)) : *(cx->runtime->jsNaN))

/**
 * end of ECMA 'support' functions
 */

/*
 * Other Support routines and definitions
 */

static JSClass date_class = {
    "Date",
    JSCLASS_HAS_PRIVATE,
    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
};

/* for use by date_parse */

static char* 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"
    /* time zone table needs to be expanded */
};

static int ttb[] = {
    0, 1, 0, 0, 0, 0, 0, 0, 0,
    2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
    10000 + 0, 10000 + 0, 10000 + 0,   /* GMT/UT/UTC */
    10000 + 5 * 60, 10000 + 4 * 60,    /* EST/EDT */
    10000 + 6 * 60, 10000 + 5 * 60,    /* CST/CDT */
    10000 + 7 * 60, 10000 + 6 * 60,    /* MST/MDT */
    10000 + 8 * 60, 10000 + 7 * 60     /* PST/PDT */
};

/* helper for date_parse */
static JSBool
date_regionMatches(const char* s1, int s1off, const jschar* s2, int s2off,
                   int count, int ignoreCase)
{
    JSBool result = JS_FALSE;
    /* return true if matches, otherwise, false */

    while (count > 0 && s1[s1off] && s2[s2off]) {
        if (ignoreCase) {
            if (JS_TOLOWER((jschar)s1[s1off]) != JS_TOLOWER(s2[s2off])) {
                break;
            }
        } else {
            if ((jschar)s1[s1off] != s2[s2off]) {
                break;
            }
        }
        s1off++;
        s2off++;
        count--;
    }

    if (count == 0) {
        result = JS_TRUE;
    }

    return result;
}

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

    day = MakeDay(year, mon, mday);
    time = MakeTime(hour, min, sec, msec);
    result = MakeDate(day, time);
    return result;
}

/*
 * See ECMA 15.9.4.[3-10];
 */
/* XXX this function must be above date_parseString to avoid a
   horrid bug in the Win16 1.52 compiler */
#define MAXARGS        7
static JSBool
date_UTC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble array[MAXARGS];
    uintN loop;
    jsdouble d;

    for (loop = 0; loop < MAXARGS; loop++) {
        if (loop < argc) {
            if (!js_ValueToNumber(cx, argv[loop], &d))
                return JS_FALSE;
            /* return NaN if any arg is NaN */
            if (!JSDOUBLE_IS_FINITE(d)) {
                return js_NewNumberValue(cx, d, rval);
            }
            array[loop] = floor(d);
        } else {
            array[loop] = 0;
        }
    }

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

    /* if we got a 0 for 'date' (which is out of range)
     * pretend it's a 1.  (So Date.UTC(1972, 5) works) */
    if (array[2] < 1)
        array[2] = 1;

    d = date_msecFromDate(array[0], array[1], array[2],
                              array[3], array[4], array[5], array[6]);
    d = TIMECLIP(d);

    return js_NewNumberValue(cx, d, rval);
}

static JSBool
date_parseString(const jschar *s, jsdouble *result)
{
    jsdouble msec;

    int year = -1;
    int mon = -1;
    int mday = -1;
    int hour = -1;
    int min = -1;
    int sec = -1;
    int c = -1;
    int i = 0;
    int n = -1;
    jsdouble tzoffset = -1;  /* was an int, overflowed on win16!!! */
    int prevc = 0;
    int limit = 0;
    JSBool seenplusminus = JS_FALSE;

    if (s == 0)
        goto syntax;
    limit = js_strlen(s);
    while (i < limit) {
        c = s[i];
        i++;
        if (c <= ' ' || c == ',' || c == '-') {
            if (c == '-' && '0' <= s[i] && s[i] <= '9') {
              prevc = c;
            }
            continue;
        }
        if (c == '(') { /* comments) */
            int depth = 1;
            while (i < limit) {
                c = s[i];

JS/js/jsdate.c  view on Meta::CPAN

                        if (action == 1) { /* pm */
                            if (hour > 12 || hour < 0) {
                                goto syntax;
                            } else {
                                hour += 12;
                            }
                        } else if (action <= 13) { /* month! */
                            if (mon < 0) {
                                mon = /*byte*/ (action - 2);
                            } else {
                                goto syntax;
                            }
                        } else {
                            tzoffset = action - 10000;
                        }
                    }
                    break;
                }
            if (k < 0)
                goto syntax;
            prevc = 0;
        }
    }
    if (year < 0 || mon < 0 || mday < 0)
        goto syntax;
    if (sec < 0)
        sec = 0;
    if (min < 0)
        min = 0;
    if (hour < 0)
        hour = 0;
    if (tzoffset == -1) { /* no time zone specified, have to use local */
        jsdouble time;
        time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);

        *result = UTC(time);
        return JS_TRUE;
    }

    msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
    msec += tzoffset * msPerMinute;
    *result = msec;
    return JS_TRUE;

syntax:
    /* syntax error */
    *result = 0;
    return JS_FALSE;
}

static JSBool
date_parse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    JSString *str;
    jsdouble result;

    str = js_ValueToString(cx, argv[0]);
    if (!str)
        return JS_FALSE;
    if (!date_parseString(str->chars, &result)) {
        *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
        return JS_TRUE;
    }

    result = TIMECLIP(result);
    return js_NewNumberValue(cx, result, rval);
}

/*
 * Check that obj is an object of class Date, and get the date value.
 * Return NULL on failure.
 */
static jsdouble *
date_getProlog(JSContext *cx, JSObject *obj, jsval *argv)
{
    if (!JS_InstanceOf(cx, obj, &date_class, argv))
        return NULL;
    return JSVAL_TO_DOUBLE(OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE));
}

/*
 * See ECMA 15.9.5.4 thru 15.9.5.23
 */
static JSBool
date_getTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    return js_NewNumberValue(cx, *date, rval);
}

static JSBool
date_getYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble result;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;
    result = *date;

    if (!JSDOUBLE_IS_FINITE(result))
        return js_NewNumberValue(cx, result, rval);

    result = YearFromTime(LocalTime(result));
    result -= 1900;
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getFullYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                 jsval *rval)
{
    jsdouble result;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;
    result = *date;

    if (!JSDOUBLE_IS_FINITE(result))

JS/js/jsdate.c  view on Meta::CPAN

        return js_NewNumberValue(cx, result, rval);

    result = msFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getTimezoneOffset(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                       jsval *rval)
{
    jsdouble result;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;
    result = *date;

    /*
     * Return the time zone offset in minutes for the current locale
     * that is appropriate for this time. This value would be a
     * constant except for daylight savings time.
     */
    result = (result - LocalTime(result)) / msPerMinute;
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_setTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble result;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    if (!js_ValueToNumber(cx, argv[0], &result))
        return JS_FALSE;

    result = TIMECLIP(result);

    *date = result;
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_makeTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
              uintN maxargs, JSBool local, jsval *rval)
{
    uintN i;
    jsdouble args[4], *argp, *stop;
    jsdouble hour, min, sec, msec;
    jsdouble lorutime; /* Local or UTC version of *date */

    jsdouble time;
    jsdouble result;

    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    result = *date;

    /* just return NaN if the date is already NaN */
    if (!JSDOUBLE_IS_FINITE(result))
        return js_NewNumberValue(cx, result, rval);

    /* 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.
     */
    if (argc == 0)
        argc = 1;   /* should be safe, because length of all settors is 1 */
    else if (argc > maxargs)
        argc = maxargs;  /* clamp argc */

    for (i = 0; i < argc; i++) {
        if (!js_ValueToNumber(cx, argv[i], &args[i]))
            return JS_FALSE;
        if (!JSDOUBLE_IS_FINITE(args[i])) {
            *date = *(cx->runtime->jsNaN);
            return js_NewNumberValue(cx, *date, rval);
        }
        args[i] = js_DoubleToInteger(args[i]);
    }

    if (local)
        lorutime = LocalTime(result);
    else
        lorutime = result;

    argp = args;
    stop = argp + argc;
    if (maxargs >= 4 && argp < stop)
        hour = *argp++;
    else
        hour = HourFromTime(lorutime);

    if (maxargs >= 3 && argp < stop)
        min = *argp++;
    else
        min = MinFromTime(lorutime);

    if (maxargs >= 2 && argp < stop)
        sec = *argp++;
    else
        sec = SecFromTime(lorutime);

    if (maxargs >= 1 && argp < stop)
        msec = *argp;
    else
        msec = msFromTime(lorutime);

    time = MakeTime(hour, min, sec, msec);
    result = MakeDate(Day(lorutime), time);

/*     fprintf(stderr, "%f\n", result); */

    if (local)
        result = UTC(result);

/*     fprintf(stderr, "%f\n", result); */

    *date = TIMECLIP(result);
    return js_NewNumberValue(cx, *date, rval);
}

static JSBool
date_setMilliseconds(JSContext *cx, JSObject *obj, uintN argc,
                     jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 1, JS_TRUE, rval);
}

static JSBool
date_setUTCMilliseconds(JSContext *cx, JSObject *obj, uintN argc,
                        jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 1, JS_FALSE, rval);
}

JS/js/jsdate.c  view on Meta::CPAN

date_setUTCSeconds(JSContext *cx, JSObject *obj, uintN argc,
                   jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 2, JS_FALSE, rval);
}

static JSBool
date_setMinutes(JSContext *cx, JSObject *obj, uintN argc,
                jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 3, JS_TRUE, rval);
}

static JSBool
date_setUTCMinutes(JSContext *cx, JSObject *obj, uintN argc,
                   jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 3, JS_FALSE, rval);
}

static JSBool
date_setHours(JSContext *cx, JSObject *obj, uintN argc,
              jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 4, JS_TRUE, rval);
}

static JSBool
date_setUTCHours(JSContext *cx, JSObject *obj, uintN argc,
                 jsval *argv, jsval *rval)
{
    return date_makeTime(cx, obj, argc, argv, 4, JS_FALSE, rval);
}

static JSBool
date_makeDate(JSContext *cx, JSObject *obj, uintN argc,
              jsval *argv, uintN maxargs, JSBool local, jsval *rval)
{
    uintN i;
    jsdouble lorutime; /* local or UTC version of *date */
    jsdouble args[3], *argp, *stop;
    jsdouble year, month, day;
    jsdouble result;

    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    result = *date;

    /* see complaint about ECMA in date_MakeTime */
    if (argc == 0)
        argc = 1;   /* should be safe, because length of all settors is 1 */
    else if (argc > maxargs)
        argc = maxargs;   /* clamp argc */

    for (i = 0; i < argc; i++) {
        if (!js_ValueToNumber(cx, argv[i], &args[i]))
            return JS_FALSE;
        if (!JSDOUBLE_IS_FINITE(args[i])) {
            *date = *(cx->runtime->jsNaN);
            return js_NewNumberValue(cx, *date, rval);
        }
        args[i] = js_DoubleToInteger(args[i]);
    }

    /* return NaN if date is NaN and we're not setting the year,
     * If we are, use 0 as the time. */
    if (!(JSDOUBLE_IS_FINITE(result))) {
        if (argc < 3)
            return js_NewNumberValue(cx, result, rval);
        else
            lorutime = +0.;
    } else {
        if (local)
            lorutime = LocalTime(result);
        else
            lorutime = result;
    }

    argp = args;
    stop = argp + argc;
    if (maxargs >= 3 && argp < stop)
        year = *argp++;
    else
        year = YearFromTime(lorutime);

    if (maxargs >= 2 && argp < stop)
        month = *argp++;
    else
        month = MonthFromTime(lorutime);

    if (maxargs >= 1 && argp < stop)
        day = *argp++;
    else
        day = DateFromTime(lorutime);

    day = MakeDay(year, month, day); /* day within year */
    result = MakeDate(day, TimeWithinDay(lorutime));

    if (local)
        result = UTC(result);

    *date = TIMECLIP(result);
    return js_NewNumberValue(cx, *date, rval);
}

static JSBool
date_setDate(JSContext *cx, JSObject *obj, uintN argc,
             jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 1, JS_TRUE, rval);
}

static JSBool
date_setUTCDate(JSContext *cx, JSObject *obj, uintN argc,
                jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 1, JS_FALSE, rval);
}

static JSBool
date_setMonth(JSContext *cx, JSObject *obj, uintN argc,
              jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 2, JS_TRUE, rval);
}

static JSBool
date_setUTCMonth(JSContext *cx, JSObject *obj, uintN argc,
                 jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 2, JS_FALSE, rval);
}

static JSBool
date_setFullYear(JSContext *cx, JSObject *obj, uintN argc,
                 jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 3, JS_TRUE, rval);
}

static JSBool
date_setUTCFullYear(JSContext *cx, JSObject *obj, uintN argc,
                    jsval *argv, jsval *rval)
{
    return date_makeDate(cx, obj, argc, argv, 3, JS_FALSE, rval);
}

static JSBool
date_setYear(JSContext *cx, JSObject *obj, uintN argc,
             jsval *argv, jsval *rval)
{
    jsdouble t;
    jsdouble year;
    jsdouble day;
    jsdouble result;

    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    result = *date;

    if (!js_ValueToNumber(cx, argv[0], &year))
        return JS_FALSE;
    if (!JSDOUBLE_IS_FINITE(year)) {
        *date = *(cx->runtime->jsNaN);
        return js_NewNumberValue(cx, *date, rval);
    }

    year = js_DoubleToInteger(year);

    if (!JSDOUBLE_IS_FINITE(result)) {
        t = +0.0;
    } else {
        t = LocalTime(result);
    }

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

    day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
    result = MakeDate(day, TimeWithinDay(t));
    result = UTC(result);

    *date = TIMECLIP(result);
    return js_NewNumberValue(cx, *date, rval);
}

/* constants for toString, toUTCString */
static char js_NaN_date_str[] = "Invalid Date";
static const char* days[] =
{
   "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
};
static const char* months[] =
{
   "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};

static JSBool
date_toGMTString(JSContext *cx, JSObject *obj, uintN argc,
                 jsval *argv, jsval *rval)
{
    char buf[100];
    JSString *str;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    if (!JSDOUBLE_IS_FINITE(*date)) {
        PR_snprintf(buf, sizeof buf, js_NaN_date_str);
    } else {
        jsdouble temp = *date;

        /* Avoid dependence on PR_FormatTimeUSEnglish, because it
         * requires a PRTime... which only has 16-bit years.  Sub-ECMA.
         */
        PR_snprintf(buf, sizeof buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
                    days[WeekDay(temp)],
                    DateFromTime(temp),
                    months[MonthFromTime(temp)],
                    YearFromTime(temp),
                    HourFromTime(temp),
                    MinFromTime(temp),
                    SecFromTime(temp));
    }
    str = JS_NewStringCopyZ(cx, buf);
    if (!str)
        return JS_FALSE;
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}

/* for Date.toLocaleString; interface to PRTime date struct. */
static void
new_explode(jsdouble time, PRTime *split)
{
    jsint year = YearFromTime(time);

    split->tm_usec = (int32) msFromTime(time) * 1000;
    split->tm_sec = (int8) SecFromTime(time);
    split->tm_min = (int8) MinFromTime(time);
    split->tm_hour = (int8) HourFromTime(time);
    split->tm_mday = (int8) DateFromTime(time);
    split->tm_mon = (int8) MonthFromTime(time);
    split->tm_wday = (int8) WeekDay(time);
    split->tm_year = (int16) year;
    split->tm_yday = (int16) DayWithinYear(time, year);

    /* not sure how this affects things, but it doesn't seem
       to matter. */
    split->tm_isdst = (DaylightSavingTA(time) != 0);
}

static JSBool
date_toLocaleString(JSContext *cx, JSObject *obj, uintN argc,
                    jsval *argv, jsval *rval)
{
    char buf[100];
    JSString *str;
    PRTime split;
    jsdouble *date = date_getProlog(cx, obj, argv);
    if (!date)
        return JS_FALSE;

    if (!JSDOUBLE_IS_FINITE(*date)) {
        PR_snprintf(buf, sizeof buf, js_NaN_date_str);
    } else {
        jsdouble local = LocalTime(*date);
        new_explode(local, &split);

        /* let PRTime format it.  Use '%#c' for windows, because '%c' is
         * backward-compatible and non-y2k with msvc; '%#c' requests that a
         * full year be used in the result string.
         */
        PR_FormatTime(buf, sizeof buf,
#ifdef _WIN32
                      "%#c",
#else
                      "%c",
#endif
                      &split);
    }

    str = JS_NewStringCopyZ(cx, buf);
    if (!str)
        return JS_FALSE;
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}

/* helper function */
static JSBool
date_format(JSContext *cx, jsdouble date, jsval *rval)
{
    char buf[100];
    JSString *str;
    char tzbuf[100];
    PRTime split;

    if (!JSDOUBLE_IS_FINITE(date)) {
        PR_snprintf(buf, sizeof buf, js_NaN_date_str);
    } else {
        jsdouble local = LocalTime(date);

        /* offset from GMT in minutes.  The offset includes daylight savings,
           if it applies. */
        jsint minutes = (jsint) floor((LocalTZA + DaylightSavingTA(date))
                                      / msPerMinute);

        /* map 510 minutes to 0830 hours */
        intN offset = (minutes / 60) * 100 + minutes % 60;

        /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is
         * printed as 'GMT-0800' rather than as 'PST' to avoid
         * operating-system dependence on strftime (which
         * PR_FormatTimeUSEnglish calls, for %Z only.)  win32 prints
         * PST as 'Pacific Standard Time.'  This way we always know
         * what we're getting, and can parse it if we produce it.
         * The OS TZA string is included as a comment.
         */

        /* get a timezone string from the OS to include as a
           comment. */
        new_explode(date, &split);
        PR_FormatTime(tzbuf, sizeof tzbuf, "(%Z) ", &split);

        /* Avoid dependence on PR_FormatTimeUSEnglish, because it
         * requires a PRTime... which only has 16-bit years.  Sub-ECMA.
         */
        PR_snprintf(buf, sizeof buf, "%s %s %.2d %.2d:%.2d:%.2d GMT%+.4d %s%.4d",
                    days[WeekDay(local)],
                    months[MonthFromTime(local)],
                    DateFromTime(local),
                    HourFromTime(local),
                    MinFromTime(local),
                    SecFromTime(local),
                    offset,

                    /* don't print anything for the TZA comment if we got '()'
                     * or something non-parenthesized from the OS.
                     */
                    ((tzbuf[0] == '(' && tzbuf[1] != ')') ? tzbuf : ""),

                    YearFromTime(local));
    }

    str = JS_NewStringCopyZ(cx, buf);
    if (!str)
        return JS_FALSE;
    *rval = STRING_TO_JSVAL(str);
    return JS_TRUE;
}

#if JS_HAS_TOSOURCE
#include "prdtoa.h"

static JSBool
date_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
	      jsval *rval)
{
    jsdouble *date;

JS/js/jsdate.c  view on Meta::CPAN

}

static JSBool
Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    jsdouble *date;
    JSString *str;
    jsdouble d;

    /* Date called as function */
    if (!cx->fp->constructing) {
        int64 us, ms, us2ms;
        jsdouble time;

        /* NSPR 2.0 docs say 'We do not support PR_NowMS and PR_NowS',
         * so compute ms from PR_Now.
         */
        us = PR_Now();
        LL_UI2L(us2ms, PR_USEC_PER_MSEC);
        LL_DIV(ms, us, us2ms);
        LL_L2D(time, ms);

        return date_format(cx, time, rval);
    }

    /* Date called as constructor */
    if (argc == 0) {
        int64 us, ms, us2ms;
        jsdouble time;

        date = date_constructor(cx, obj);
        if (!date)
            return JS_FALSE;

        us = PR_Now();
        LL_UI2L(us2ms, PR_USEC_PER_MSEC);
        LL_DIV(ms, us, us2ms);
        LL_L2D(time, ms);

        *date = time;
    } else if (argc == 1) {
        if (!JSVAL_IS_STRING(argv[0])) {
            /* the argument is a millisecond number */
            if (!js_ValueToNumber(cx, argv[0], &d))
                    return JS_FALSE;
            date = date_constructor(cx, obj);
            if (!date)
                return JS_FALSE;
            *date = TIMECLIP(d);
        } else {
            /* the argument is a string; parse it. */
            date = date_constructor(cx, obj);
            if (!date)
                return JS_FALSE;

            str = js_ValueToString(cx, argv[0]);
            if (!str)
                return JS_FALSE;

            if (!date_parseString(str->chars, date))
                *date = *(cx->runtime->jsNaN);
            *date = TIMECLIP(*date);
        }
    } else {
        jsdouble array[MAXARGS];
        uintN loop;
        jsdouble d;
        jsdouble day;
        jsdouble time;

        for (loop = 0; loop < MAXARGS; loop++) {
            if (loop < argc) {
                if (!js_ValueToNumber(cx, argv[loop], &d))
                    return JS_FALSE;
                /* if any arg is NaN, make a NaN date object
                   and return */
                if (!JSDOUBLE_IS_FINITE(d)) {
                    date = date_constructor(cx, obj);
                    if (!date)
                        return JS_FALSE;
                    *date = *(cx->runtime->jsNaN);
                    return JS_TRUE;
                }
                array[loop] = js_DoubleToInteger(d);
            } else {
                array[loop] = 0;
            }
        }

        date = date_constructor(cx, obj);
        if (!date)
            return JS_FALSE;

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

        /* if we got a 0 for 'date' (which is out of range)
         * pretend it's a 1 */
        if (array[2] < 1)
            array[2] = 1;

        day = MakeDay(array[0], array[1], array[2]);
        time = MakeTime(array[3], array[4], array[5], array[6]);
        time = MakeDate(day, time);
        time = UTC(time);
        *date = TIMECLIP(time);
    }
    return JS_TRUE;
}

JSObject *
js_InitDateClass(JSContext *cx, JSObject *obj)
{
    JSObject *proto;
    jsdouble *proto_date;

    /* set static LocalTZA */
    LocalTZA = -(PR_LocalGMTDifference() * msPerSecond);
    proto = JS_InitClass(cx, obj, NULL, &date_class, Date, MAXARGS,
                         NULL, date_methods, NULL, date_static_methods);
    if (!proto)
        return NULL;

    /* Set the value of the Date.prototype date to NaN */
    proto_date = date_constructor(cx, proto);
    if (!proto_date)
        return NULL;
    *proto_date = *(cx->runtime->jsNaN);

    return proto;
}

JS_FRIEND_API(JSObject *)
js_NewDateObject(JSContext* cx, int year, int mon, int mday,
                 int hour, int min, int sec)
{
    JSObject *obj;
    jsdouble *date;
    jsdouble time;

    obj = js_NewObject(cx, &date_class, NULL, NULL);
    if (!obj)
        return NULL;

    JS_DefineFunctions(cx, obj, date_methods);

    date = date_constructor(cx, obj);
    if (!date)
        return NULL;

    time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
    *date = UTC(time);
    return obj;
}

JS_FRIEND_API(int)
js_DateGetYear(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) YearFromTime(LocalTime(*date));
}

JS_FRIEND_API(int)
js_DateGetMonth(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) MonthFromTime(LocalTime(*date));
}

JS_FRIEND_API(int)
js_DateGetDate(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) DateFromTime(LocalTime(*date));
}

JS_FRIEND_API(int)
js_DateGetHours(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) HourFromTime(LocalTime(*date));
}

JS_FRIEND_API(int)
js_DateGetMinutes(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) MinFromTime(LocalTime(*date));
}

JS_FRIEND_API(int)
js_DateGetSeconds(JSContext *cx, JSObject* obj)
{
    jsdouble *date = date_getProlog(cx, obj, NULL);

    if (!date)
        return 0;
    return (int) SecFromTime(*date);
}

extern JS_FRIEND_API(void)
js_DateSetYear(JSContext *cx, JSObject *obj, int year)
{
    jsdouble local;
    jsdouble *date = date_getProlog(cx, obj, NULL);
    if (!date)
        return;
    local = LocalTime(*date);
    /* reset date if it was NaN */
    if (JSDOUBLE_IS_NaN(local))
        local = 0;
    local = date_msecFromDate(year,
                              MonthFromTime(local),
                              DateFromTime(local),
                              HourFromTime(local),
                              MinFromTime(local),
                              SecFromTime(local),
                              msFromTime(local));
    *date = UTC(local);
}

extern JS_FRIEND_API(void)
js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
{
    jsdouble local;
    jsdouble *date = date_getProlog(cx, obj, NULL);
    if (!date)
        return;
    local = LocalTime(*date);
    /* bail if date was NaN */
    if (JSDOUBLE_IS_NaN(local))
        return;
    local = date_msecFromDate(YearFromTime(local),
                              month,
                              DateFromTime(local),
                              HourFromTime(local),
                              MinFromTime(local),
                              SecFromTime(local),
                              msFromTime(local));
    *date = UTC(local);
}

extern JS_FRIEND_API(void)
js_DateSetDate(JSContext *cx, JSObject *obj, int date)
{
    jsdouble local;
    jsdouble *datep = date_getProlog(cx, obj, NULL);
    if (!datep)
        return;
    local = LocalTime(*datep);
    if (JSDOUBLE_IS_NaN(local))
        return;
    local = date_msecFromDate(YearFromTime(local),
                              MonthFromTime(local),
                              date,
                              HourFromTime(local),
                              MinFromTime(local),
                              SecFromTime(local),
                              msFromTime(local));
    *datep = UTC(local);
}

extern JS_FRIEND_API(void)
js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
{
    jsdouble local;
    jsdouble *date = date_getProlog(cx, obj, NULL);
    if (!date)
        return;
    local = LocalTime(*date);
    if (JSDOUBLE_IS_NaN(local))
        return;
    local = date_msecFromDate(YearFromTime(local),
                              MonthFromTime(local),
                              DateFromTime(local),
                              hours,
                              MinFromTime(local),
                              SecFromTime(local),
                              msFromTime(local));
    *date = UTC(local);
}

extern JS_FRIEND_API(void)
js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
{
    jsdouble local;
    jsdouble *date = date_getProlog(cx, obj, NULL);
    if (!date)
        return;
    local = LocalTime(*date);
    if (JSDOUBLE_IS_NaN(local))
        return;
    local = date_msecFromDate(YearFromTime(local),
                              MonthFromTime(local),
                              DateFromTime(local),
                              HourFromTime(local),
                              minutes,
                              SecFromTime(local),
                              msFromTime(local));
    *date = UTC(local);
}

extern JS_FRIEND_API(void)
js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
{
    jsdouble local;
    jsdouble *date = date_getProlog(cx, obj, NULL);
    if (!date)
        return;
    local = LocalTime(*date);
    if (JSDOUBLE_IS_NaN(local))
        return;
    local = date_msecFromDate(YearFromTime(local),
                              MonthFromTime(local),
                              DateFromTime(local),
                              HourFromTime(local),
                              MinFromTime(local),
                              seconds,
                              msFromTime(local));
    *date = UTC(local);
}



( run in 1.146 second using v1.01-cache-2.11-cpan-39bf76dae61 )