Letzte Woche habe ich auf meiner Rätselseite ein neues Quiz online gestellt. Eine der Besonderheiten dieses Quiz ist, dass es 5 verschiedene Highscorelisten gibt: Tag, Woche, Monat, Jahr, alltime. In diesem Artikel erkläre ich, wie ich die verschiedenen Zeiträume mit Hilfe der PHP-Datumsfunktionen ermittelt habe und auf welchen Fehler ich dabei gestoßen bin.
Der einfachste Zeitraum ist „alltime“. Hierfür reicht es aus, wenn ich die entsprechende Variable auf 0 setze:
$zeitraum=0;
Die Funktion strtotime()
Zur Ermittlung der anderen Zeiträume habe ich die Funktion strtotime() genutzt. Diese liefert mir den Unix-Timestamp des angegebenen Zeitraums. Beim Tag ist das ganz simpel:
$zeitraum=strtotime("today");
Das Ergebnis ist der Unix-Timestamp des heutigen Tages, 0 Uhr.
Für die Ermittlung des Jahresbeginns muss man den 1.1. als Argument angeben:
$zeitraum=strtotime("1/1 this year");
Beim Monat wird es schon deutlich komplizierter:
$zeitraum=strtotime("first day of this month");
liefert mir zwar den 1. März, allerdings nicht um 0 Uhr, sondern mit der aktuellen Uhrzeit.
Um den Monatsbeginn zu erhalten, muss der Aufruf lauten:
$zeitraum=strtotime("midnight first day of this month");
Mit Abstand am kompliziertesten ist es allerdings die aktuelle Kalenderwoche zu ermitteln.
Ermittlung des Wochenbeginns in PHP
Auf den ersten Blick ist die Ermittlung des Wochenbeginns nicht weiter schwierig. Analog zur Ermittlung des Jahresbeginns könnte man ja einfach schreiben:
$zeitraum=strtotime("monday this week");
Das funktioniert auch hervorragend. Allerdings leider nur im Zeitraum Montag bis Samstag.
Die Funktion strtotime() hat nämlich einen kleinen Pferdefuß. Die Woche beginnt nicht wie in unserem Kulturraum üblich an einem Montag, sondern an einem Sonntag.
Dies gilt selbst dann, wenn man die deutsche Zeitzone setzt:
date_default_timezone_set('Europe/Berlin');
In der aktuellen Woche liefert strtotime(„monday this week“) den UNIX-Timestamp für folgende Zeit, wenn sie montags bis samstags abgerufen wird:
19. März 2012, 0 Uhr
Wenn ich die gleiche Funktion aber heute, also an einem Sonntag, aufrufe, wird der UNIX-Timestamp für folgende Zeit geliefert:
26. März 2012, 0 Uhr
also für den morgigen Montag.
Die einzige Möglichkeit dies zu umgehen ist es abzufragen, welcher Wochentag heute ist und die strtotime()-Funktion dementsprechend anzupassen.
Für die Abfrage des aktuellen Wochentags habe ich die Funktion date() genutzt. Das Formatzeichen „N“ gibt den Wochentag als Ziffer an. Seltsamerweise ist es bei date() aber so, dass der Montag die Ziffer „1“ und der Sonntag die „7“ hat. Bei date() ist der Montag also der 1. Tag der Woche.
Die Formel für die Ermittlung des Wochenbeginns, 0 Uhr, lautet somit:
if (date("N")!=7) $zeitraum=strtotime("monday this week"); else $zeitraum=strtotime("last monday");
Wenn heute kein Sonntag ist, liefert strtotime(„monday this week“) den Wochenbeginn. Falls es sich um einen Sonntag handelt, beziehe ich mich auf den letzten Montag um den Wochenbeginn zu erhalten. Das Ergebnis dieser Abfrage ist also auf jeden Fall:
19. März 2012, 0 Uhr
Zeitraum mit mySQL abfragen
Die mySQL-Abfrage für den jeweiligen Zeitraum ist überall gleich:
SELECT spalten FROM tabelle WHERE endzeit > $zeitraum
In der Spalte endzeit habe ich bei allen Usern die Zeit des Quizendes gespeichert (als Unix-Timestamp). Die mySQL-Abfrage liefert mir somit alle Datensätze bei denen das Quizende nach Beginn des Zeitraums (z. B. Wochenbeginn) liegt.
Fehler bei strtotime()?
Meiner Meinung nach ist die Funktion strtotime() fehlerhaft. Zumindest für mich ist es nicht nachvollziehbar, warum bei dieser Funktion die Woche mit Sonntag beginnt und bei date() der Wochenbeginn montags ist. Und das obwohl in beiden Fällen die Zeitzone für Deutschland gesetzt wurde. Wenn ihr euch die Versionsgeschichte von strtotime() mal anseht, seht ihr auch, dass es bei dieser Funktion regelmäßig Fehlerkorrekturen gibt. Auf meinem Server ist übrigens die PHP-Version 5.3.10 installiert. Vielleicht ist der Fehler, wenn es denn einer ist, auch schon mit der neuen Version 5.4 behoben.
Weitere Infos über die PHP-Datumsfunktionen
date()
strtotime()
Relative Formats
Auch in meinem Artikel Adventskalender erstellen – Teil 2: Die Datumsabfrage könnt ihr noch einiges über die PHP-Datumsfunktionen nachlesen.
Interessant, dass du darauf gestoßen bist, für so etwas habe ich strtotime() bisher noch nicht gebraucht, deswegen ist mir das noch gar nicht aufgefallen.
Aber wie du ja geschrieben hast, kann man das ganz einfach „selber fixen“ und sollte es sich um keinen Fehler handeln, müsstest du die Funktion ja einfach überschreiben können.
Ach & interessantes Quiz, habe ich gleich mal ausprobiert: 6 von 10 – immerhin.
Alternativ könnte man das Ganze auch direkt in der SQL Abfrage unterbringen. Zum Beispiel mit der Methode DATEDIFF(date1,date2) > ANZAHL DER TAGE. (date2 = aktuelles Datum)
Oder per (TO_DAYS(now()) – TO_DAYS(date)) > ANZAHL_DER_TAGE
Und um wirklich nur die aktuelle Woche auszulesen würde sowas noch helfen
YEARWEEK(date) = YEARWEEK(date)
Beste Grüße
Danke für den Tipp. Die Funktion zur Abfrage des Wochentages konnte ich in einem aktuellen Projekt von mir gut gebrauchen.