PHP, mktime() und die Oktalzahlen

Von in php

Wenn man im Inter­net nach der PHP-​Funktion mktime() sucht, erhält man über eine Mil­li­on Ergeb­nis­se. Neben all­ge­mei­nen Beschrei­bun­gen über die Funk­ti­on han­deln vie­le von der Pro­ble­ma­tik der Rei­hen­fol­ge über­ge­be­ner Argu­men­te (Monat, Tag, Jahr), man­che auch über uner­war­te­te Rück­ga­be­wer­te. Letz­te­res war mir einen zwei­ten Blick und schließ­lich einen Arti­kel wert, denn über die Pro­ble­ma­tik, die Argu­men­te (unbe­wusst) in Form von Oktal­zah­len zu über­ge­ben, fin­det sich kaum etwas im Inter­net. Lesen Sie hier, wie Oktal­zah­len das Ergeb­nis ver­än­dern und war­um es in Ver­bin­dung mit der date()-Funktion zu kei­nen Pro­ble­men kom­men kann.

Zuge­ge­ben, mir sel­ber hat es viel Kopf­zer­bre­chen und Zeit gekos­tet her­aus­zu­fin­den, war­um fol­gen­de Ein­ga­be ein ver­meint­lich fal­sches Ergeb­nis lie­fert:

echo date("d.m.Y",mktime(0,0,0,08,05,2009));
// 05.12.2008

Man mag fast ein wenig an sei­nem Ver­stand zwei­feln, ruft man die mktime()-Funktion wie folgt auf:

echo date("d.m.Y",mktime(0,0,0,07,05,2009));
// 05.07.2009

Wie kann es zu einem sol­chen Ergeb­nis kom­men?

Zunächst soll­te man wis­sen, wie PHP mit Zah­len rech­net, die eine (oder meh­re­re) füh­ren­de Nul­len haben. PHP inter­pre­tiert die­se näm­lich als Oktal­zahl. So bedeu­tet die Zahl “07” ins Dezi­mal­sys­tem über­setzt “7” und die Zahl “010” “8”:

var_dump(010);
// int(8)

So lässt sich auch schon erah­nen, war­um die mktime()-Funktion völ­lig durch­ein­an­der kommt, wenn man sie wie folgt auf­ruft:

mktime(0,0,0,08,09,2009);

Die Zah­len “08” und “09” exis­tie­ren im Oktal­sys­tem nicht. Trotz­dem wer­den sie von PHP als Oktal­zahl inter­pre­tiert:

var_dump(08);
// int(0)

mktime() akzep­tiert jedoch als Argu­men­te an 4. und 5. Stel­le kei­ne Null und retour­niert ein unbrauch­ba­res Ergeb­nis. Inter­es­sant ist an die­ser Stel­le viel­leicht, dass es hier­bei zu kei­ner Feh­ler­aus­ga­be kommt.

Die mktime-​Funktion kann man nun zu vie­ler­lei tol­len Sachen ver­wen­den. Die Kom­bi­na­ti­on mit der Funk­ti­on date() wird hier bekannt sein. Sehen wir uns die­se Funk­ti­on mit fol­gen­den Argu­men­ten an:

echo date("j.n.Y",time());
// z.B. 5.9.2009
echo date("d.m.Y",time());
// z.B. 05.09.2009

Das Mus­ter “j.n.Y” gibt also den Tag und das Monat ohne, “d.m.Y” jedoch mit füh­ren­den Nul­len aus. Was wür­de nun pas­sie­ren, füt­ter­ten wir die mktime-​Funktion mit dem zwei­ten Mus­ter unse­rer Date-​Funktion nach fol­gen­dem Sche­ma?

echo date("d.m.Y",mktime(0,0,0,date("m",time());
date("d",time()),date("Y",time())));

Hier wer­den also Tag und Monat mit füh­ren­den Nul­len über­ge­ben. Wird die mktime-​Funktion wie­der unbrauch­ba­re Ergeb­nis­se lie­fern, wenn die Oktal­zah­len einen ungül­ti­gen Wert haben?

// z.B. 05.09.2009

Selt­sa­mer­wei­se berech­net PHP hier das (fik­ti­ve) Datum völ­lig kor­rekt. Wie kann das sein?

Die Lösung lie­fert fol­gen­de Aus­ga­be:

var_dump(010);
// int(8)
var_dump(date("m",1249779600));
// string(2) "08"

Damit es der date-​Funktion über­haupt mög­lich ist, Wer­te wie z.B. “03.09.2009” aus­zu­ge­ben, muss das Ergeb­nis natür­lich ein String sein. Über­gibt man der mktime-​Funktion die Argu­men­te ohne Anfüh­rungs­zei­chen, ver­sucht PHP sie zuerst als Zahl zu behan­deln. Und wie es dabei mit füh­ren­den Nul­len umgeht, wis­sen wir bereits. Somit bin ich noch einen letz­ten Beweis schul­dig:

echo date("d.m.Y",mktime(0,0,0,"08","09",2009));
// 09.08.2009

Wer übri­gens nur schnell ein­mal ein paar Zei­len Code inter­pre­tiert haben möch­te, ohne gleich eine kom­plet­te Ent­wick­lungs­um­ge­bung auf­bau­en zu müs­sen, kann sich Online-​Parser zunut­ze machen. Einen sol­chen gibt es unter codepad.org.

Share on Google+Share on RedditTweet about this on TwitterShare on LinkedInShare on FacebookShare on XingEmail this to someone