Via Twitter on the weekend I came across this pastie (see lines 259-274), supposedly containing the code for the Real-Time-Clock running on the 30GB Zune.
As you can see in the code an infinite loop occurs as soon as the local variable ‘days’ is exactly 366 and ‘year’ is a leap year. This was the case on January 1, 2009 GMT and is therefore aptly known as a Y2K9 bug. The glitch resulted in headlines such as:

This could have been prevented had the code coverage report been inspected 😉
I converted the buggy function to Java:

final int ORIGINYEAR = 1980;
Function: ConvertDays
Local helper function that split total days since Jan 1,
ORIGINYEAR into year, month and day
Returns TRUE if successful, otherwise returns FALSE.
boolean ConvertDays(int days, Date lpTime) {
int dayofweek, month, year;
int month_tab;
while (days > 365) {
if (IsLeapYear(year)) {
if (days > 366) {
days -= 366;
year += 1;
} else {
days -= 365;
year += 1;
return true;

and wrote the following test case:

public void testConvertDays() {
final RTC rtc = new RTC();
final ReadableInstant originDate = new DateTime(rtc.ORIGINYEAR, 1, 1, 0, 0, 0, 0);
// test on 2008, 12, 31.
final ReadableInstant date20081231 = new DateTime(2008, 12, 31, 0, 0, 0, 0);
assertTrue(rtc.ConvertDays(Days.daysBetween(originDate, date20081231).getDays(), new Date(date20081231.getMillis())));

Running the test with Clover enabled shows the following:

The if (days > 366) branch never evaluates to false. Adding the next test for this case, causes the infinite loop that Zune users experienced on Y2K9:

final ReadableInstant date20090102 = new DateTime(2009, 1, 1, 0, 0, 0, 0);
rtc.ConvertDays(Days.daysBetween(originDate, date20090102).getDays(), new Date(date20090102.getMillis()));

And in the interest of fair and balance reporting, don’t forget that the iPod was born in an infinite loop…

Fresh ideas, announcements, and inspiration for your team, delivered weekly.

Subscribe now