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)
Core
JavaScript Engine
Tracking
()
VERIFIED
FIXED
Future
People
(Reporter: david, Unassigned)
Details
(Keywords: js1.5)
Attachments
(1 file, 3 obsolete files)
3.97 KB,
patch
|
shaver
:
review+
shaver
:
approval1.8b4+
|
Details | Diff | Splinter Review |
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
Comment 1•25 years ago
|
||
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.
Comment 4•25 years ago
|
||
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
Comment 6•25 years ago
|
||
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
Reporter | ||
Comment 7•25 years ago
|
||
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()
Comment 8•25 years ago
|
||
Not high priority, but I'd like a fix for js1.5, personally. Hope it is easy.
/be
Keywords: js1.5
Comment 9•25 years ago
|
||
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
Reporter | ||
Comment 10•25 years ago
|
||
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
Comment 11•25 years ago
|
||
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.
Comment 12•25 years ago
|
||
Comment 13•25 years ago
|
||
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.
Comment 14•25 years ago
|
||
Another potential reviewer. Patrick?
Comment 15•25 years ago
|
||
Comment 16•25 years ago
|
||
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 ;)
Comment 17•25 years ago
|
||
Reassigning Mike's JS Engine bugs to Patrick, as per recent meeting -
Assignee: mike+mozilla → beard
Comment 19•21 years ago
|
||
checked in js/tests/js1_5/Regress/regress-58116.js
Updated•20 years ago
|
Assignee: beard → general
QA Contact: pschwartau → general
Comment 20•20 years ago
|
||
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)
Updated•20 years ago
|
Flags: testcase+
Updated•20 years ago
|
Attachment #181388 -
Flags: review?(brendan) → review?(shaver)
Comment 21•20 years ago
|
||
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+
Comment 22•20 years ago
|
||
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
Comment 23•20 years ago
|
||
Hrmph. OK, but I'd still like to see the arguments parenthesized when used!
Comment 24•20 years ago
|
||
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 25•20 years ago
|
||
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+
Comment 26•20 years ago
|
||
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
You need to log in
before you can comment on or make changes to this bug.
Description
•