📄 jsdate.c
字号:
jsval *argv, jsval *rval){ return date_makeTime(cx, obj, argc, argv, 3, JS_FALSE, rval);}static JSBooldate_setHours(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeTime(cx, obj, argc, argv, 4, JS_TRUE, rval);}static JSBooldate_setUTCHours(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeTime(cx, obj, argc, argv, 4, JS_FALSE, rval);}static JSBooldate_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 setters 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 (maxargs < 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 JSBooldate_setDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 1, JS_TRUE, rval);}static JSBooldate_setUTCDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 1, JS_FALSE, rval);}static JSBooldate_setMonth(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 2, JS_TRUE, rval);}static JSBooldate_setUTCMonth(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 2, JS_FALSE, rval);}static JSBooldate_setFullYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 3, JS_TRUE, rval);}static JSBooldate_setUTCFullYear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return date_makeDate(cx, obj, argc, argv, 3, JS_FALSE, rval);}static JSBooldate_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 JSBooldate_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)) { JS_snprintf(buf, sizeof buf, js_NaN_date_str); } else { jsdouble temp = *date; /* Avoid dependence on PRMJ_FormatTimeUSEnglish, because it * requires a PRMJTime... which only has 16-bit years. Sub-ECMA. */ JS_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 PRMJTime date struct. * If findEquivalent is true, then try to map the year to an equivalent year * that's in range. */static voidnew_explode(jsdouble timeval, PRMJTime *split, JSBool findEquivalent){ jsint year = YearFromTime(timeval); int16 adjustedYear; /* If the year doesn't fit in a PRMJTime, find something to do about it. */ if (year > 32767 || year < -32768) { if (findEquivalent) { /* We're really just trying to get a timezone string; map the year * to some equivalent year in the range 0 to 2800. Borrowed from * A. D. Olsen. */ jsint cycles;#define CYCLE_YEARS 2800L cycles = (year >= 0) ? year / CYCLE_YEARS : -1 - (-1 - year) / CYCLE_YEARS; adjustedYear = (int16)(year - cycles * CYCLE_YEARS); } else { /* Clamp it to the nearest representable year. */ adjustedYear = (int16)((year > 0) ? 32767 : - 32768); } } else { adjustedYear = (int16)year; } split->tm_usec = (int32) msFromTime(timeval) * 1000; split->tm_sec = (int8) SecFromTime(timeval); split->tm_min = (int8) MinFromTime(timeval); split->tm_hour = (int8) HourFromTime(timeval); split->tm_mday = (int8) DateFromTime(timeval); split->tm_mon = (int8) MonthFromTime(timeval); split->tm_wday = (int8) WeekDay(timeval); split->tm_year = (int16) adjustedYear; split->tm_yday = (int16) DayWithinYear(timeval, year); /* not sure how this affects things, but it doesn't seem to matter. */ split->tm_isdst = (DaylightSavingTA(timeval) != 0);}typedef enum formatspec { FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME} formatspec;/* helper function */static JSBooldate_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval){ char buf[100]; JSString *str; char tzbuf[100]; JSBool usetz; size_t i, tzlen; PRMJTime split; if (!JSDOUBLE_IS_FINITE(date)) { JS_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(AdjustTime(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 * PRMJ_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, JS_TRUE); if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) { /* Decide whether to use the resulting timezone string. * * Reject it if it contains any non-ASCII, non-alphanumeric * characters. It's then likely in some other character * encoding, and we probably won't display it correctly. */ usetz = JS_TRUE; tzlen = strlen(tzbuf); if (tzlen > 100) { usetz = JS_FALSE; } else { for (i = 0; i < tzlen; i++) { jschar c = tzbuf[i]; if (c > 127 || !(isalpha(c) || isdigit(c) || c == ' ' || c == '(' || c == ')')) { usetz = JS_FALSE; } } } /* Also reject it if it's not parenthesized or if it's '()'. */ if (tzbuf[0] != '(' || tzbuf[1] == ')') usetz = JS_FALSE; } else usetz = JS_FALSE; switch (format) { case FORMATSPEC_FULL: /* * Avoid dependence on PRMJ_FormatTimeUSEnglish, because it * requires a PRMJTime... which only has 16-bit years. Sub-ECMA. */ /* Tue Oct 31 2000 09:41:40 GMT-0800 (PST) */ JS_snprintf(buf, sizeof buf, "%s %s %.2d %.4d %.2d:%.2d:%.2d GMT%+.4d%s%s", days[WeekDay(local)], months[MonthFromTime(local)], DateFromTime(local), YearFromTime(local), HourFromTime(local), MinFromTime(local), SecFromTime(local), offset, usetz ? " " : "", usetz ? tzbuf : ""); break; case FORMATSPEC_DATE: /* Tue Oct 31 2000 */ JS_snprintf(buf, sizeof buf, "%s %s %.2d %.4d", days[WeekDay(local)], months[MonthFromTime(local)], DateFromTime(local), YearFromTime(local)); break; case FORMATSPEC_TIME: /* 09:41:40 GMT-0800 (PST) */ JS_snprintf(buf, sizeof buf, "%.2d:%.2d:%.2d GMT%+.4d%s%s", HourFromTime(local), MinFromTime(local), SecFromTime(local), offset, usetz ? " " : "", usetz ? tzbuf : ""); break; } } str = JS_NewStringCopyZ(cx, buf); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); return JS_TRUE;}static JSBooldate_toLocaleHelper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval, char *format){ char buf[100]; JSString *str; PRMJTime split; jsdouble *date = date_getProlog(cx, obj, argv); if (!date) return JS_FALSE; if (!JSDOUBLE_IS_FINITE(*date)) { JS_snprintf(buf, sizeof buf, js_NaN_date_str); } else { intN result_len; jsdouble local = LocalTime(*date); new_explode(local, &split, JS_FALSE); /* let PRMJTime format it. */ result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split); /* If it failed, default to toString. */ if (result_len == 0) return date_format(cx, *date, FORMATSPEC_FULL, rval); /* Hacked check against undesired 2-digit year 00/00/00 form. */ if (strcmp(format, "%x") == 0 && result_len >= 6 && /* Format %x means use OS settings, which may have 2-digit yr, so hack end of 3/11/22 or 11.03.22 or 11Mar22 to use 4-digit yr...*/ !isdigit(buf[result_len - 3]) && isdigit(buf[result_len - 2]) && isdigit(buf[result_len - 1]) && /* ...but not if starts with 4-digit year, like 2022/3/11. */ !(isdigit(buf[0]) && isdigit(buf[1]) && isdigit(buf[2]) && isdigit(buf[3]))) { JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2), "%d", js_DateGetYear(cx, obj)); } } if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode) return cx->localeCallbacks->localeToUnicode(cx, buf, rval); str = JS_NewStringCopyZ(cx, buf); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); return JS_TRUE;}static JSBooldate_toLocaleString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ /* 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. */ return date_toLocaleHelper(cx, obj, argc, argv, rval,#if defined(_WIN32) && !defined(__MWERKS__) "%#c"#else "%c"#endif );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -