Gebruikers van de Microsoft Zune-muziekspeler kregen op oudjaar het apparaatje niet meer in gang: het herstartte vanzelf en bleef bij het opstartscherm hangen. In Microsofts driver voor de interne klok bleek een fout te zitten waardoor de Zune geen rekening hield met de 366 dagen van het schrikkeljaar 2008. Het 30 Gbyte-model uit 2006 weigerde daardoor op de laatste dag van 2008 op te starten. Microsoft heeft geen bugfix uitgebracht, maar meldde dat het probleem zichzelf op 1 januari zou oplossen (en dat was dan ook de officiële fix!). Gebruikers moesten wel de batterij volledig laten leeglopen en dan opnieuw opstarten.
Toen ik dit las, was ik benieuwd hoe zo’n onnozele fout anno 2008, 8 jaar na Y2K, nog kan voorkomen. Na wat zoekwerk vond ik de broncode van de driver op een Zune forum met uitleg over de fout. De klok slaat de huidige tijd op als het aantal dagen en aantal seconden sinds 1 januari 1980. Wanneer de tijd wordt opgevraagd, wordt het aantal dagen omgezet in de datum in jaren, maanden en dagen. Op het einde van de opstartfase gebeurt dit de eerste keer. Een deel van de C-code gaat als volgt (ORIGINYEAR staat voor 1980):
year = ORIGINYEAR;
while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
}
else
{
days -= 365;
year += 1;
}
}
De functie trekt dus 365 of 366 dagen van het aantal dagen af tot het aantal dagen kleiner dan een jaar is. Daarna (hier niet getoond) wordt de rest omgezet in de juiste maand en dag van de maand. In de code zit echter een fout: als het 31 december in een schrikkeljaar is (zoals 31 december 2008), dan is de vergelijking if (days > 366) niet waar, maar is 366 te groot om de lus while (days > 365) te stoppen. Het resultaat: de Zune blijft in een oneindige lus hangen en blokkeert. Een oplossing is (zoals in het Zune-forum gegeven):
year = ORIGINYEAR;
while (days > 365)
{
if (IsLeapYear(year))
{
if (days > 366)
{
days -= 366;
year += 1;
}
else
{
break;
}
}
else
{
days -= 365;
year += 1;
}
}
Hierdoor wordt op 31 december van een schrikkeljaar het aantal dagen op 366 gehouden, het jaar niet aangepast en door de break-instructie uit de lus gesprongen.
Op 31 december 2012 gaat dit Zune-model opnieuw een dag onbruikbaar zijn als Microsoft tegen dan de bugfix niet heeft uitgebracht. En blijkbaar hebben ze geen haast, lees ik (cursivering van mij):
According to Microsoft’s Matt Akers, of the Zune Product Team, a fix will be released at some point before 2012, when the leap year issue will next arise.
Het zou me niets verbazen als Microsoft de fix ‘vergeet’ voor zijn tegen dan 6 jaar oude muziekspeler…