jsdate.c

来自「一个基于alice开发的机器人」· C语言 代码 · 共 2,235 行 · 第 1/4 页

C
2,235
字号
    int mon = -1;
    int mday = -1;
    int hour = -1;
    int min = -1;
    int sec = -1;
    int c = -1;
    int n = -1;
    jsdouble tzoffset = -1;  /* was an int, overflowed on win16!!! */
    int prevc = 0;
    JSBool seenplusminus = JS_FALSE;

    if (limit == 0)
	goto syntax;
    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];
		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[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 = JS_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)
		    goto syntax;
		tzoffset = n;
	    } else if (n >= 70 ||
		       (prevc == '/' && mon >= 0 && mday >= 0 && year < 0)) {
		if (year >= 0)
		    goto syntax;
		else if (c <= ' ' || c == ',' || c == '/' || i >= limit)
		    year = n < 100 ? n + 1900 : n;
		else
		    goto syntax;
	    } else if (c == ':') {
		if (hour < 0)
		    hour = /*byte*/ n;
		else if (min < 0)
		    min = /*byte*/ n;
		else
		    goto syntax;
	    } else if (c == '/') {
		if (mon < 0)
		    mon = /*byte*/ n-1;
		else if (mday < 0)
		    mday = /*byte*/ n;
		else
		    goto syntax;
	    } else if (i < limit && c != ',' && c > ' ' && c != '-') {
		goto syntax;
	    } 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 {
		goto syntax;
	    }
	    prevc = 0;
	} else if (c == '/' || c == ':' || c == '+' || c == '-') {
	    prevc = c;
	} else {
	    size_t st = i - 1;
	    int k;
	    while (i < limit) {
		c = s[i];
		if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
		    break;
		i++;
	    }
	    if (i <= st + 1)
		goto syntax;
	    for (k = (sizeof(wtb)/sizeof(char*)); --k >= 0;)
		if (date_regionMatches(wtb[k], 0, s, st, i-st, 1)) {
		    int action = ttb[k];
		    if (action != 0) {
                        if (action < 0) {
                            /*
                             * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
                             * 12:30, instead of blindly adding 12 if PM.
                             */
                            JS_ASSERT(action == -1 || action == -2);
                            if (hour > 12 || hour < 0) {
                                goto syntax;
                            } else {
                                if (action == -1 && hour == 12) { /* am */
                                    hour = 0;
                                } else if (action == -2 && hour != 12) { /* pm */
                                    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 msec_time;
	msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);

	*result = UTC(msec_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, &result)) {
	*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
	return JS_TRUE;
    }

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

static JSBool
date_now(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
    int64 us, ms, us2ms;
    jsdouble msec_time;

    us = PRMJ_Now();
    JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
    JSLL_DIV(ms, us, us2ms);
    JSLL_L2D(msec_time, ms);

    return js_NewDoubleValue(cx, msec_time, 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));

    /*
     * During the great date rewrite of 1.3, we tried to track the evolving ECMA
     * standard, which then had a definition of getYear which always subtracted
     * 1900.  Which we implemented, not realizing that it was incompatible with
     * the old behavior...  now, rather than thrash the behavior yet again,
     * we've decided to leave it with the - 1900 behavior and point people to
     * the getFullYear method.  But we try to protect existing scripts that
     * have specified a version...
     */
    if (cx->version == JSVERSION_1_0 ||
        cx->version == JSVERSION_1_1 ||
        cx->version == JSVERSION_1_2)
    {
        if (result >= 1900 && result < 2000)
            result -= 1900;
    } else {
        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))
	return js_NewNumberValue(cx, result, rval);

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

static JSBool
date_getUTCFullYear(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(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getMonth(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 = MonthFromTime(LocalTime(result));
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getUTCMonth(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 = MonthFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getDate(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 = LocalTime(result);
    result = DateFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getUTCDate(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 = DateFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getDay(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 = LocalTime(result);
    result = WeekDay(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getUTCDay(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 = WeekDay(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getHours(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 = HourFromTime(LocalTime(result));
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getUTCHours(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 = HourFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getMinutes(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 = MinFromTime(LocalTime(result));
    return js_NewNumberValue(cx, result, rval);
}

static JSBool
date_getUTCMinutes(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 = MinFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

/* Date.getSeconds is mapped to getUTCSeconds */

static JSBool
date_getUTCSeconds(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 = SecFromTime(result);
    return js_NewNumberValue(cx, result, rval);
}

/* Date.getMilliseconds is mapped to getUTCMilliseconds */

static JSBool
date_getUTCMilliseconds(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 = 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 msec_time;
    jsdouble result;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?