The truth is rarely pure and never simple

PHP: strptime / strftime und Kalenderwochen

Von einem gegebenen Datum auf einen Wochentag zu schließen, ist dank strftime() recht komfortabel. Obwohl laut Dokumentation strptime() in der Lage sein sollte, den umgekehrten Weg zu beschreiten, schlägt das fehl (PHP 5.2.10 unter Gentoo).

Eigentlich müsste folgender Schnipsel zumindest den heutigen Tag errechnen können.

[php] var_dump(strptime(strftime(‘%V %G’, time()), ‘%V %G’));[/php]

Leider ist das Ergebnis ein wenig ernüchternd:
[plain]array(9) {
["tm_sec"]=> int(0)
["tm_min"]=> int(0)
["tm_hour"]=> int(0)
["tm_mday"]=> int(0)
["tm_mon"]=> int(0)
["tm_year"]=> int(0)
["tm_wday"]=> int(0)
["tm_yday"]=> int(0)
["unparsed"]=> string(0) ""
}[/plain]
Selbst, wenn man noch den Wochentag mitgibt, …
[php]var_dump(strptime(strftime(‘%u %V %G’, time()), ‘%u %V %G’));[/php]
… verbessert das das Ergebnis nur unwesentlich.
[plain]array(9) {
["tm_sec"]=> int(0)
["tm_min"]=> int(0)
["tm_hour"]=> int(0)
["tm_mday"]=> int(0)
["tm_mon"]=> int(0)
["tm_year"]=> int(0)
["tm_wday"]=> int(1)
["tm_yday"]=> int(0)
["unparsed"]=> string(0) ""
}[/plain]
Diese Funktion gleicht den kleinen Makel aus. Wer nicht mit UTC arbeitet, muss noch eine Unterscheidung nach Sommer- und Winterzeit einführen und das Datum auf einen Tag ändern, der entweder immer in der Sommerzeit oder immer in der Winterzeit liegt.

[php] function getFirstWeekDay($year, $week) {
// beliebiges Datum, das nicht in der ersten oder letzten Woche des Jahres liegt
$baseTime = mktime(0, 0, 0, 10, 18, $year);
$baseWeek = strftime(‘%V’, $baseTime);
$baseDay = strftime(‘%u’, $baseTime);

// Berechnung des Zeitstempels des Montags der Woche in die obiges Datum fällt
$monday = $baseTime – (($baseDay – 1) * 24*60*60);
return $monday + ($week – $baseWeek) * 7*24*60*60;
}[/php]

Das Verfahren ist denkbar simpel: man nehme einen Tag, der garantiert nicht in der ersten oder letzten Woche eines Jahres liegt und suche den letzten Montag vor diesem Tag. Davon ausgehend kann man über die Differenz der jeweiligen Kalenderwochen den gesuchten Zeitstempel liefern.