Closed Bug 58116 Opened 25 years ago Closed 20 years ago

ECMA Compliance: daylight savings time computed wrong before 1970

Categories

(Core :: JavaScript Engine, defect, P3)

defect

Tracking

()

VERIFIED FIXED
Future

People

(Reporter: david, Unassigned)

Details

(Keywords: js1.5)

Attachments

(1 file, 3 obsolete files)

Spidermonkey computes daylight savings time wrong for years before 1970. It appears to never recognize daylight savings time before 1970. js> d = new Date() Thu Oct 26 14:20:13 GMT-0700 (PDT) 2000 js> d.getTimezoneOffset() 420 js> d.setYear(1968) -37244386070 js> d Sat Oct 26 14:20:13 GMT-0800 (PST) 1968 js> d.getTimezoneOffset() 480 js> d.setMonth(7) -42514786070 js> d Mon Aug 26 14:20:13 GMT-0800 (PST) 1968 js> d.getTimezoneOffset() 480 See section 15.9.1.8 of the ECMA v3 spec, which says that the daylight savings time adjustment should be applied to all dates, regardless of year. That is, there should be not attempt to track the actual historical definitions and adoption of daylight savings time. This bug also appears in Rhino, and will be reported separately
Here is the ECMA section: 15.9.1.8 Daylight Saving Time Adjustment An implementation of ECMAScript is expected to determine the daylight saving time algorithm. The algorithm to determine the daylight saving time adjustment DaylightSavingTA(t), measured in milliseconds, must depend only on four things: (1) the time since the beginning of the year t – TimeFromYear(YearFromTime(t)) (2) whether t is in a leap year InLeapYear(t) (3) the week day of the beginning of the year WeekDay(TimeFromYear(YearFromTime(t)) and (4) the geographic location. The implementation of ECMAScript should not try to determine whether the exact time was subject to daylight saving time, but just whether daylight saving time would have been in effect if the current daylight saving time algorithm had been used at the time. This avoids complications such as taking into account the years that the locale observed daylight saving time year round. If the host environment provides functionality for determining daylight saving time, the implementation of ECMAScript is free to map the year in question to an equivalent year (same leap-year-ness and same starting week day for the year) for which the host environment provides daylight saving time information. The only restriction is that all equivalent years should produce the same result.
Confirming bug -
Status: UNCONFIRMED → NEW
Ever confirmed: true
Reassigning to mccabe -
Assignee: rogerl → mccabe
Using SpiderMonkey on Linux; built 2000-10-25. Following David's test above. For those who are smarter than I am: do all the years after 1970 look correct? js> for (i=2010; i!=1959; i--) { d.setFullYear(i); print('Year = ' + i + '; ' + d.getTimezoneOffset()); } Year = 2010; 420 Year = 2009; 480 Year = 2008; 480 Year = 2007; 420 Year = 2006; 420 Year = 2005; 420 Year = 2004; 420 Year = 2003; 480 Year = 2002; 420 Year = 2001; 420 Year = 2000; 420 Year = 1999; 420 Year = 1998; 480 Year = 1997; 480 Year = 1996; 420 Year = 1995; 480 Year = 1994; 480 Year = 1993; 480 Year = 1992; 480 Year = 1991; 480 Year = 1990; 480 Year = 1989; 480 Year = 1988; 480 Year = 1987; 480 Year = 1986; 480 Year = 1985; 480 Year = 1984; 480 Year = 1983; 480 Year = 1982; 480 Year = 1981; 480 Year = 1980; 480 Year = 1979; 480 Year = 1978; 480 Year = 1977; 480 Year = 1976; 480 Year = 1975; 480 Year = 1974; 480 Year = 1973; 480 Year = 1972; 480 Year = 1971; 480 Year = 1970; 480 Year = 1969; 480 Year = 1968; 480 Year = 1967; 480 Year = 1966; 480 Year = 1965; 480 Year = 1964; 480 Year = 1963; 480 Year = 1962; 480 Year = 1961; 480 Year = 1960; 480
Compare Rhino bug 58118
Here's what I get on Linux with Rhino, built 2000-10-25. It's different: Year = 2010; 420 Year = 2009; 480 Year = 2008; 480 Year = 2007; 420 Year = 2006; 420 Year = 2005; 420 Year = 2004; 420 Year = 2003; 480 Year = 2002; 420 Year = 2001; 420 Year = 2000; 420 Year = 1999; 420 Year = 1998; 480 Year = 1997; 480 Year = 1996; 420 Year = 1995; 420 Year = 1994; 420 Year = 1993; 420 Year = 1992; 480 Year = 1991; 420 Year = 1990; 420 Year = 1989; 420 Year = 1988; 420 Year = 1987; 480 Year = 1986; 480 Year = 1985; 420 Year = 1984; 420 Year = 1983; 420 Year = 1982; 420 Year = 1981; 480 Year = 1980; 480 Year = 1979; 420 Year = 1978; 420 Year = 1977; 420 Year = 1976; 420 Year = 1975; 480 Year = 1974; 420 Year = 1973; 420 Year = 1972; 420 Year = 1971; 420 Year = 1970; 480 Year = 1969; 480 Year = 1968; 420 Year = 1967; 420 Year = 1966; 420 Year = 1965; 420 Year = 1964; 480 Year = 1963; 420 Year = 1962; 420 Year = 1961; 420 Year = 1960; 420
Phil - your test would be simpler if you were running it in July or August -- months that are always daylight time. Right now in late october we're on the cusp; some years it is daylight time, other years it isn't. So if you rerun your test code but start with a date in some other month, you should see a more reasonable pattern of values from getTimezoneOffset()
Not high priority, but I'd like a fix for js1.5, personally. Hope it is easy. /be
Keywords: js1.5
Here's the same experiment as above, with d = August 1st. Again getting a discrepancy between SpiderMonkey and Rhino - IN SPIDERMONKEY: js> d = new Date(2000, 7) Tue Aug 01 00:00:00 GMT-0700 (PDT) 2000 Year = 2010; 420 Year = 2009; 420 Year = 2008; 420 Year = 2007; 420 Year = 2006; 420 Year = 2005; 420 Year = 2004; 420 Year = 2003; 420 Year = 2002; 420 Year = 2001; 420 Year = 2000; 420 Year = 1999; 420 Year = 1998; 420 Year = 1997; 420 Year = 1996; 420 Year = 1995; 480 Year = 1994; 480 Year = 1993; 480 Year = 1992; 480 Year = 1991; 480 Year = 1990; 480 Year = 1989; 480 Year = 1988; 480 Year = 1987; 480 Year = 1986; 480 Year = 1985; 480 Year = 1984; 480 Year = 1983; 480 Year = 1982; 480 Year = 1981; 480 Year = 1980; 480 Year = 1979; 480 Year = 1978; 480 Year = 1977; 480 Year = 1976; 480 Year = 1975; 480 Year = 1974; 480 Year = 1973; 480 Year = 1972; 480 Year = 1971; 480 Year = 1970; 480 Year = 1969; 480 Year = 1968; 480 Year = 1967; 480 Year = 1966; 480 Year = 1965; 480 Year = 1964; 480 Year = 1963; 480 Year = 1962; 480 Year = 1961; 480 Year = 1960; 480 IN RHINO: js> d=new Date(2000,7) Tue Aug 01 00:00:00 GMT-0700 (PDT) 2000 Year = 2010; 420 Year = 2009; 420 Year = 2008; 420 Year = 2007; 420 Year = 2006; 420 Year = 2005; 420 Year = 2004; 420 Year = 2003; 420 Year = 2002; 420 Year = 2001; 420 Year = 2000; 420 Year = 1999; 420 Year = 1998; 420 Year = 1997; 420 Year = 1996; 420 Year = 1995; 420 Year = 1994; 420 Year = 1993; 420 Year = 1992; 420 Year = 1991; 420 Year = 1990; 420 Year = 1989; 420 Year = 1988; 420 Year = 1987; 420 Year = 1986; 420 Year = 1985; 420 Year = 1984; 420 Year = 1983; 420 Year = 1982; 420 Year = 1981; 420 Year = 1980; 420 Year = 1979; 420 Year = 1978; 420 Year = 1977; 420 Year = 1976; 420 Year = 1975; 420 Year = 1974; 420 Year = 1973; 420 Year = 1972; 420 Year = 1971; 420 Year = 1970; 420 Year = 1969; 420 Year = 1968; 420 Year = 1967; 420 Year = 1966; 420 Year = 1965; 420 Year = 1964; 420 Year = 1963; 420 Year = 1962; 420 Year = 1961; 420 Year = 1960; 420
The discrepancy between spidermonkey and rhino is expected: the bug I reported for Rhino was for dates before the year 1. I reported the spidermonkey bug for dates before 1970, which is still what my tests on Linux indicate. Note that Phil's test above shows the problem year at 1995! Here's what I did: js> d = new Date(2000,6) Sat Jul 01 00:00:00 GMT-0700 (PDT) 2000 js> for(var i = 2005; i > 1965; i--) { d.setFullYear(i); print(d.getTimezoneOffset() + ": " + d); } 420: Fri Jul 01 00:00:00 GMT-0700 (PDT) 2005 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 2004 420: Tue Jul 01 00:00:00 GMT-0700 (PDT) 2003 420: Mon Jul 01 00:00:00 GMT-0700 (PDT) 2002 420: Sun Jul 01 00:00:00 GMT-0700 (PDT) 2001 420: Sat Jul 01 00:00:00 GMT-0700 (PDT) 2000 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 1999 420: Wed Jul 01 00:00:00 GMT-0700 (PDT) 1998 420: Tue Jul 01 00:00:00 GMT-0700 (PDT) 1997 420: Mon Jul 01 00:00:00 GMT-0700 (PDT) 1996 420: Sat Jul 01 00:00:00 GMT-0700 (PDT) 1995 420: Fri Jul 01 00:00:00 GMT-0700 (PDT) 1994 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 1993 420: Wed Jul 01 00:00:00 GMT-0700 (PDT) 1992 420: Mon Jul 01 00:00:00 GMT-0700 (PDT) 1991 420: Sun Jul 01 00:00:00 GMT-0700 (PDT) 1990 420: Sat Jul 01 00:00:00 GMT-0700 (PDT) 1989 420: Fri Jul 01 00:00:00 GMT-0700 (PDT) 1988 420: Wed Jul 01 00:00:00 GMT-0700 (PDT) 1987 420: Tue Jul 01 00:00:00 GMT-0700 (PDT) 1986 420: Mon Jul 01 00:00:00 GMT-0700 (PDT) 1985 420: Sun Jul 01 00:00:00 GMT-0700 (PDT) 1984 420: Fri Jul 01 00:00:00 GMT-0700 (PDT) 1983 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 1982 420: Wed Jul 01 00:00:00 GMT-0700 (PDT) 1981 420: Tue Jul 01 00:00:00 GMT-0700 (PDT) 1980 420: Sun Jul 01 00:00:00 GMT-0700 (PDT) 1979 420: Sat Jul 01 00:00:00 GMT-0700 (PDT) 1978 420: Fri Jul 01 00:00:00 GMT-0700 (PDT) 1977 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 1976 420: Tue Jul 01 00:00:00 GMT-0700 (PDT) 1975 420: Mon Jul 01 00:00:00 GMT-0700 (PDT) 1974 420: Sun Jul 01 00:00:00 GMT-0700 (PDT) 1973 420: Sat Jul 01 00:00:00 GMT-0700 (PDT) 1972 420: Thu Jul 01 00:00:00 GMT-0700 (PDT) 1971 420: Wed Jul 01 00:00:00 GMT-0700 (PDT) 1970 480: Tue Jul 01 00:00:00 GMT-0800 (PST) 1969 480: Mon Jul 01 00:00:00 GMT-0800 (PST) 1968 480: Sat Jul 01 00:00:00 GMT-0800 (PST) 1967 480: Fri Jul 01 00:00:00 GMT-0800 (PST) 1966 Note that things change between 1970 and 1969
the EquivalentYear patch to 61184 should solve this. XP, too. I just tried in in a rough way (ignoring local/gmt adjustments to avoid recursion problems) and it seems to do the trick.
Proposed fix attached. Local time (which would recursively use DaylightSavingsTA) isn't a problem, as times near year boundaries aren't near DST boundaries. (I'm still not sure if it applies at all). CCing reviwers.
Another potential reviewer. Patrick?
Anyone in this chat room (ahem) could review this? All compliance bugs are nice to squash :-) Or maybe some other checkin already fixed this.. that's ok with me ;)
Reassigning Mike's JS Engine bugs to Patrick, as per recent meeting -
Assignee: mike+mozilla → beard
Marking future.
Target Milestone: --- → Future
checked in js/tests/js1_5/Regress/regress-58116.js
Assignee: beard → general
QA Contact: pschwartau → general
This passes js1_5/Regress/regress-58116.js with no regressions in the test suite. I got consistent values for d.getTimezoneOffset() for years 1900-2100.
Attachment #20283 - Attachment is obsolete: true
Attachment #20288 - Attachment is obsolete: true
Attachment #181388 - Flags: review?(brendan)
Flags: testcase+
Attachment #181388 - Flags: review?(brendan) → review?(shaver)
Comment on attachment 181388 [details] [diff] [review] Mike's patch updated to the trunk. >+#define MakeTime(hour, min, sec, ms) \ >+(((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms) We like our macros to be UPPER_CASE, and the parameters to be parenthesized where they're used, to avoid bad interactions with complex expressions. (I see that the old macro didn't do this, but if you're gonna touch it... =) ) >+ result = yearday >+ + monthday >+ + date - 1; >+ return result; Fold the computation onto one line, and possibly even get rid of the temporary assignment, since we're just going to return it right away. >+} >+#define MakeDate(day, time) (day * msPerDay + time) As above re: macros. >+/* Years and leap years on which Jan 1 is a Sunday, Monday, etc. */ >+static jsint yearStartingWith[2][7] = { >+ {1978, 1973, 1974, 1975, 1981, 1971, 1977}, >+ {1984, 1996, 1980, 1992, 1976, 1988, 1972} >+}; Can you add a comment indicating that the second index indicates leap year or not? >+ * 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. Good caution here; can we name the function EquivalentYearForDST to make it a little clearer that it has this restricted purpose? >+ isLeapYear = DaysInYear(year) == 366; I like to overparenthesize equality expressions when used as the RHS of assignments, and I think Brendan does as well. I like this approach to fixing the bug, thanks! r=shaver with the above nits picked; feel free to re-request review on a new patch if you want me to give it another once-over.
Attachment #181388 - Flags: review?(shaver) → review+
shaver: mccabe used the ECMA-262 names for things like MakeTime, IIRC. In the interest of lining up spec and code, perhaps we can wink at that? /be
Hrmph. OK, but I'd still like to see the arguments parenthesized when used!
This patch addresses all of shaver's comments minus the upper case macro names. Shaver, if you could give this a quick review+ I would appreciate it. This passes js1_5/Regress/regress-58116.js with no regressions. I am requesting this for approval for Firefox 1.5 beta as this appears to be a safe fix for a long standing DST bug.
Attachment #181388 - Attachment is obsolete: true
Attachment #190928 - Flags: review?(shaver)
Attachment #190928 - Flags: approval1.8b4?
Comment on attachment 190928 [details] [diff] [review] Mike's patch v2 r+a=shaver, thanks for your work on this.
Attachment #190928 - Flags: review?(shaver)
Attachment #190928 - Flags: review+
Attachment #190928 - Flags: approval1.8b4?
Attachment #190928 - Flags: approval1.8b4+
Checking in jsdate.c; /cvsroot/mozilla/js/src/jsdate.c,v <-- jsdate.c new revision: 3.68; previous revision: 3.67 done
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
verified fixed 1.8.x and trunk.
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: