📄 jsdate.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS date methods. *//* * "For example, OS/360 devotes 26 bytes of the permanently * resident date-turnover routine to the proper handling of * December 31 on leap years (when it is Day 366). That * might have been left to the operator." * * Frederick Brooks, 'The Second-System Effect'. */#include "jsstddef.h"#include <ctype.h>#include <locale.h>#include <math.h>#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsprf.h"#include "prmjtime.h"#include "jsutil.h" /* Added by JSIFY */#include "jsapi.h"#include "jsconfig.h"#include "jscntxt.h"#include "jsdate.h"#include "jsinterp.h"#include "jsnum.h"#include "jsobj.h"#include "jsstr.h"/* * The JS 'Date' object is patterned after the Java 'Date' object. * Here is an script: * * today = new Date(); * * print(today.toLocaleString()); * * weekDay = today.getDay(); * * * These Java (and ECMA-262) methods are supported: * * UTC * getDate (getUTCDate) * getDay (getUTCDay) * getHours (getUTCHours) * getMinutes (getUTCMinutes) * getMonth (getUTCMonth) * getSeconds (getUTCSeconds) * getMilliseconds (getUTCMilliseconds) * getTime * getTimezoneOffset * getYear * getFullYear (getUTCFullYear) * parse * setDate (setUTCDate) * setHours (setUTCHours) * setMinutes (setUTCMinutes) * setMonth (setUTCMonth) * setSeconds (setUTCSeconds) * setMilliseconds (setUTCMilliseconds) * setTime * setYear (setFullYear, setUTCFullYear) * toGMTString (toUTCString) * toLocaleString * toString * * * These Java methods are not supported * * setDay * before * after * equals * hashCode *//* * 11/97 - jsdate.c has been rewritten to conform to the ECMA-262 language * definition and reduce dependence on NSPR. NSPR is used to get the current * time in milliseconds, the time zone offset, and the daylight savings time * offset for a given time. NSPR is also used for Date.toLocaleString(), for * locale-specific formatting, and to get a string representing the timezone. * (Which turns out to be platform-dependent.) * * To do: * (I did some performance tests by timing how long it took to run what * I had of the js ECMA conformance tests.) * * - look at saving results across multiple calls to supporting * functions; the toString functions compute some of the same values * multiple times. Although - I took a quick stab at this, and I lost * rather than gained. (Fractionally.) Hard to tell what compilers/processors * are doing these days. * * - look at tweaking function return types to return double instead * of int; this seems to make things run slightly faster sometimes. * (though it could be architecture-dependent.) It'd be good to see * how this does on win32. (Tried it on irix.) Types could use a * general going-over. *//* * Supporting functions - ECMA 15.9.1.* */#define HalfTimeDomain 8.64e15#define HoursPerDay 24.0#define MinutesPerDay (HoursPerDay * MinutesPerHour)#define MinutesPerHour 60.0#define SecondsPerDay (MinutesPerDay * SecondsPerMinute)#define SecondsPerHour (MinutesPerHour * SecondsPerMinute)#define SecondsPerMinute 60.0#if defined(XP_WIN) || defined(XP_OS2)/* Work around msvc double optimization bug by making these runtime values; if * they're available at compile time, msvc optimizes division by them by * computing the reciprocal and multiplying instead of dividing - this loses * when the reciprocal isn't representable in a double. */static jsdouble msPerSecond = 1000.0;static jsdouble msPerDay = SecondsPerDay * 1000.0;static jsdouble msPerHour = SecondsPerHour * 1000.0;static jsdouble msPerMinute = SecondsPerMinute * 1000.0;#else#define msPerDay (SecondsPerDay * msPerSecond)#define msPerHour (SecondsPerHour * msPerSecond)#define msPerMinute (SecondsPerMinute * msPerSecond)#define msPerSecond 1000.0#endif#define Day(t) floor((t) / msPerDay)static jsdoubleTimeWithinDay(jsdouble t){ jsdouble result; result = fmod(t, msPerDay); if (result < 0) result += msPerDay; return result;}#define DaysInYear(y) ((y) % 4 == 0 && ((y) % 100 || ((y) % 400 == 0)) \ ? 366 : 365)/* math here has to be f.p, because we need * floor((1968 - 1969) / 4) == -1 */#define DayFromYear(y) (365 * ((y)-1970) + floor(((y)-1969)/4.0) \ - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0))#define TimeFromYear(y) (DayFromYear(y) * msPerDay)static jsintYearFromTime(jsdouble t){ jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970; jsdouble t2 = (jsdouble) TimeFromYear(y); if (t2 > t) { y--; } else { if (t2 + msPerDay * DaysInYear(y) <= t) y++; } return y;}#define InLeapYear(t) (JSBool) (DaysInYear(YearFromTime(t)) == 366)#define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year)))/* * The following array contains the day of year for the first day of * each month, where index 0 is January, and day 0 is January 1. */static jsdouble firstDayOfMonth[2][12] = { {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0}, {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0}};#define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m];static intNMonthFromTime(jsdouble t){ intN d, step; jsint year = YearFromTime(t); d = DayWithinYear(t, year); if (d < (step = 31)) return 0; step += (InLeapYear(t) ? 29 : 28); if (d < step) return 1; if (d < (step += 31)) return 2; if (d < (step += 30)) return 3; if (d < (step += 31)) return 4; if (d < (step += 30)) return 5; if (d < (step += 31)) return 6; if (d < (step += 31)) return 7; if (d < (step += 30)) return 8; if (d < (step += 31)) return 9; if (d < (step += 30)) return 10; return 11;}static intNDateFromTime(jsdouble t){ intN d, step, next; jsint year = YearFromTime(t); d = DayWithinYear(t, year); 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 intNWeekDay(jsdouble t){ jsint result; result = (jsint) Day(t) + 4; result = result % 7; if (result < 0) result += 7; return (intN) result;}#define MakeTime(hour, min, sec, ms) \((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms))static jsdoubleMakeDay(jsdouble year, jsdouble month, jsdouble date){ JSBool leap; jsdouble yearday; jsdouble monthday; year += floor(month / 12); month = fmod(month, 12.0); if (month < 0) month += 12; leap = (DaysInYear((jsint) year) == 366); yearday = floor(TimeFromYear(year) / msPerDay); monthday = DayFromMonth(month, leap); return yearday + monthday + date - 1;}#define MakeDate(day, time) ((day) * msPerDay + (time))/* * Years and leap years on which Jan 1 is a Sunday, Monday, etc. * * yearStartingWith[0][i] is an example non-leap year where * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc. * * yearStartingWith[1][i] is an example leap year where * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc. */static jsint yearStartingWith[2][7] = { {1978, 1973, 1974, 1975, 1981, 1971, 1977}, {1984, 1996, 1980, 1992, 1976, 1988, 1972}};/* * 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. */static jsintEquivalentYearForDST(jsint year){ jsint day; JSBool isLeapYear; day = (jsint) DayFromYear(year) + 4; day = day % 7; if (day < 0) day += 7; isLeapYear = (DaysInYear(year) == 366); return yearStartingWith[isLeapYear][day];}/* LocalTZA gets set by js_InitDateClass() */static jsdouble LocalTZA;static jsdoubleDaylightSavingTA(jsdouble t){ volatile int64 PR_t; int64 ms2us; int64 offset; jsdouble result; /* abort if NaN */ if (JSDOUBLE_IS_NaN(t)) return t; /* * If earlier than 1970 or after 2038, potentially beyond the ken of * many OSes, map it to an equivalent year before asking. */ if (t < 0.0 || t > 2145916800000.0) { jsint year; jsdouble day; year = EquivalentYearForDST(YearFromTime(t)); day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); t = MakeDate(day, TimeWithinDay(t)); } /* put our t in an LL, and map it to usec for prtime */ JSLL_D2L(PR_t, t); JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC); JSLL_MUL(PR_t, PR_t, ms2us); offset = PRMJ_DSTOffset(PR_t); JSLL_DIV(offset, offset, ms2us); JSLL_L2D(result, offset); return result;}#define AdjustTime(t) fmod(LocalTZA + DaylightSavingTA(t), msPerDay)#define LocalTime(t) ((t) + AdjustTime(t))static jsdoubleUTC(jsdouble t){ return t - AdjustTime(t - LocalTZA);}static intNHourFromTime(jsdouble t){ intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay); if (result < 0) result += (intN)HoursPerDay; return result;}static intNMinFromTime(jsdouble t){ intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour); if (result < 0) result += (intN)MinutesPerHour; return result;}static intNSecFromTime(jsdouble t){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -