blog.awill.me

blog.awill.me

01 Jan 2009

Yet another leap year bug

As some of you may have read, the Microsoft Zune (Microsoft’s competitor to the iPod Classic) has a serious bug, where on the last day of each leap year the device is unbootable.
Such a day was yesterday, 31st December, 2008.
The cause?
An incompetent, overpaid programmer.

As is common in computing, time is calculated as seconds elapsed since an arbitrarily picked start time (midnight 1st January 1970 in Unix, or 1980 for Zune/Freescale stuff)

So, quite simply, the clock would show ‘1’ for 12:00:01 on 1st Jan 1970, and keep counting up until you run out of space and overflow. (In 32bit machines this will happen in 2038, but by then, 32-bit stuff shouldn’t be around)

So, what does this code do?
Since humans don’t want to see the current time as a huge number of seconds since 1970, a piece of code (on bootup) converts is to years, months days etc.

The following piece of code (taken from the Freescale website, and actually used in the Zune) attempts to do that.

year = ORIGINYEAR; /* = 1980 */
while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}

This code works by continually subtracting 365 days until there are less than 365 days (or 366 for a leap year).
So, if you had 364 days, it would stay at 364 days, but if you had 367 days, it would give you 1 year and 2 days.

The problem though, is the way a leap year is handled. It gets stuck, as it doesn’t know what to do when the days are exactly 366 (such as the last day in a leap year)

Categories