Why is using JavaScript to plan Q1 year 22034 unreliable in Safari?
There is something fishy about the calculation of far future dates when done on the browser side (Safari 5.0.1), passing strings into the Date() constructor:
I narrowed it down to the February-March transition in year 22034:
d = new Date('1 Mar 22034')
Tue Feb 28 22034 00:00:00 GMT+0000 (GMT)
Feeding it any later date, the constructor always returns a Date object off-by-one day!
What about earlier dates? The last day in February looks good:
d=new Date('28 Feb 22034')
Tue Feb 28 22034 00:00:00 GMT+0000 (GMT)
My gut-feeling tells me that looks like a leap-year related bug. But what is the pattern in play here, what could be the explanation of the bug开发者_运维问答?
Edit:
How about if we ask for February 29th?
d=new Date('29 Feb 22034')
Wed Mar 01 22034 00:00:00 GMT+0000 (GMT)
That returns the last of Feb + 1 day (its standard behavior).
It's because the date format you're giving new Date()
is non-standard. The fact you're getting anything is because Safari is doing you a favor. (See section 15.9.1.15 of the spec for valid formats; basically a simplified ISO-8601. And having any standard for parsing date/time strings is relatively new [5th edition].)
If you use a standard constructor, e.g., new Date (22034, 2, 1)
(months start at zero, so that's March 1, 22034), it works fine. You can test it like this (live copy):
display("With non-standard string: " + new Date("1 Mar 22034"));
display("Using standard constructor: " + new Date(22034, 2, 1));
Which for me using Safari for Windows results in:
With non-standard string: Tue Feb 28 22034 00:00:00 GMT+0000 (GMT Standard Time)
Using standard constructor: Wed Mar 01 22034 00:00:00 GMT+0000 (GMT Standard Time)
As you can see, the first line shows the incorrect date, while the second line shows the correct one.
The standard constructor also works correctly in Chrome, Opera, and Firefox (all under Ubuntu), IE6, IE7, and IE8: http://jsbin.com/ogiqu
If it were really true that Safari couldn't handle that date (as opposed to not parsing the non-standard string you gave it reliably), it would be a surprising Safari-specific bug. From section 15.9.1.1 of the spec:
Time is measured in ECMAScript in milliseconds since 01 January, 1970 UTC. In time values leap seconds are ignored. It is assumed that there are exactly 86,400,000 milliseconds per day. ECMAScript Number values can represent all integers from –9,007,199,254,740,991 to 9,007,199,254,740,991; this range suffices to measure times to millisecond precision for any instant that is within approximately 285,616 years, either forward or backward, from 01 January, 1970 UTC.
But as Safari seems to handle it fine when you don't ask it to go off-piste, apparently the problem is in the parsing code for non-standard strings.
精彩评论