A pedant that hangs out in the dark corner-cases of the web.

Thursday, March 30, 2006

Safari Date bug

The parameter for Date.setDate() is converted to a signed byte integer in Safari. This means that it can only be called with numbers from -128 to 127; all other values "roll over" into that range.

So, in Safari:

dt.setDate(128) = dt.setDate(-128)
dt.setDate(129) = dt.setDate(-127)
dt.setDate(130) = dt.setDate(-126)
...
dt.setDate(254) = dt.setDate(-2)
dt.setDate(255) = dt.setDate(-1)
dt.setDate(256) = dt.setDate(0)
dt.setDate(257) = dt.setDate(1)
dt.setDate(258) = dt.setDate(2)
dt.setDate(259) = dt.setDate(3)
...

Months and years/leap years are not exact, unless you use approximate mean months (30.436875) or mean years (365.2425), which can lead to rounding errors. So, if you need to add an arbitrary, exact time period to a date, the easiest way is dt.setDate(dt.getDate()+n), which even works for large values of n, since month and year rollovers are handled automatically.

Unfortunately, the Date.setDate() bug in Safari severely restricts the range of time that can be added to a date; only 96 (31 + 96 = 127) or fewer days can be reliably added. To work around this issue, something like this must be used:

function addDays(d,D)
{
var x= new Date(2000,1,1), y= new Date(2000,1,1);
if(x.setDate(128) > y.valueOf())
{ D.setDate(D.getDate()+d); return D; }
// Safari setDate(uint8) workaround
if(d < 0)
for(var i= -97; d < i; d-= i)
D.setDate(D.getDate()+i);
else
for(var i= 96; d > i; d-= i)
D.setDate(D.getDate()+i);
D.setDate(D.getDate()+d);
return D;
}

Thursday, March 23, 2006

IE7 Mar 20 beta Details

howtocreate.co.uk has a good analysis of IE7 changes.

MIX06 Notes: IE7 Mar 20 beta 2

IE7 now has support for min/max-width/height.

I have to say, though there is still a long way to go for full CSS2.1, XHTML, and other support, what I heard from the folks at Microsoft is very encouraging. I expect IE7.5 and IE8 to really raise the current lowest-common-denominator web client into a competitive position again.