Christian Seiler: Timestamp für Wochenbeginn und -ende errechnen

Beitrag lesen

Hallo Christian,

[Zu gegebener Woche einen ]
Wie kann ich jetzt Sommer- und Winterzeitverschiebungen ausgleichen?

Indem Du Sekunden auf Timestamps addierst: Gar nicht. Denn Timestamps sind kontinuierlich, unsere Zeit jedoch nicht (wegen der Sommer-/Winterzeitumstellung). Die einzige Möglichkeit, hier sinnvoll etwas zu machen, ist über Kalenderberechnungen, d.h. Dir erst den jeweiligen Tag zusammensuchen und Dir dann den Timestamp daraus und aus der Uhrzeit zu basteln.

PHP ab Version 5.2 bietet Dir die Möglichkeit, mit DateTime-Objects herumzuspielen und dort eine ganze Menge kalendarischer Berechnungen für Dich durchführen zu lassen. In Deinem Fall wäre zum Beispiel folgender Code zielführend:

function wocheInfo ($jahr, $woche) {  
 $datum = new DateTime;  
 // montag holen  
 $datum->setISODate ($jahr, $woche, 1);  
 $datum->setTime (0, 0, 0);  
 $start = (int)($datum->format ('U'));  
 // sonntag holen  
 $datum->setISODate ($jahr, $woche, 7);  
 $datum->setTime (23, 59, 59);  
 $ende = (int)($datum->format ('U'));  
 // zurückgeben  
 return array ($start, $ende);  
}

Die Methode setISODate übernimmt dabei die komplette Wochenberechnung für Dich.

Wenn Du eine ältere PHP-Version hast, bleibt Dir immer noch die Möglichkeit, die Kalenderberechnung selbst durchzuführen. In meinen Augen ist es dabei am sinnvollsten, julianische Tageszahlen zur Kalenderberechnung zu verwenden. Hier wäre eine Implementierung für PHP < 5.2 (inklusive PHP 4):

// Hilfsfunktion: Julianische Tageszahl in Jahr, Monat und Tag  
// Zurückrechnen.  
// (Siehe [link:http://de.wikipedia.org/w/index.php?title=Julianisches_Datum&oldid=18407571])  
function julZuDatum ($jul_tag_zahl) {  
 $korrektur = floor (($jul_tag_zahl - 1867216.25) / 36524.25);  
 $jul_tag_zahl = $jul_tag_zahl + 1 + $korrektur - floor ($korrektur / 4);  
 // Hilfsvariablen anlegen  
 $B = $jul_tag_zahl + 1524;  
 $C = floor (($B - 122.1) / 365.25);  
 $D = floor (365.25 * $C);  
 $E = floor (($B - $D) / 30.6001);  
 // Ergebnis  
 $tag = (int)($B - $D - floor (30.6001 * $E));  
 $monat = (int)($E < 14 ? $E - 1 : $E - 13);  
 $jahr = (int)($monat > 2 ? $C - 4716 : $C - 4715);  
 return array ($jahr, $monat, $tag);  
}  
  
// Wochen-Start und Ende einer ISO8601-Woche in einem gegebenen  
// Jahr bestimmen (als UNIX-Timestamp)  
function wocheInfo ($jahr, $woche) {  
 // Erster Schritt: Hole die julianische Tageszahl des 4. Januars  
 // des gegebenen ISO8601-Jahres.  
 $jahrhundert = (int) (($jahr + 4799) / 100) - 48;  
 $korrektur = 2 - $jahrhundert + (int) (($jahrhundert + 48) / 4) - 12;  
 $jahr_start = (int) (365.25 * ($jahr + 4715)) + $korrektur - 1092;  
 // Nun den Wochentag abziehen, damit wir den Start des ISO8601-Jahres  
 // erhalten  
 $jahr_start -= ($jahr_start % 7);  
 // Start- und Enddatum erzeugen  
 $start_datum = $jahr_start + ($woche - 1) * 7;  
 $end_datum = $start_datum + 6;  
 // Wieder zurück in Jahr/Monat/Tag rechnen  
 $start_datum = julZuDatum ($start_datum);  
 $end_datum = julZuDatum ($end_datum);  
 // Gib zurück  
 return array (mktime (0, 0, 0, $start_datum[1], $start_datum[2], $start_datum[0]),  
   mktime (23, 59, 59, $end_datum[1], $end_datum[2], $end_datum[0]));  
}

(Da der Code Sommer- und Winterzeit selbst nicht berücksichtigt - und in der Kürze auch nicht kann - muss dies eben PHP machen, und damit braucht man mktime() und damit muss überhaupt die julianische Tageszahl erst zurückgerechnet werden auf Jahr, Monat und Tag - wenn man das Zeitzonenoffset bereits kennt, lässt sich eine julianische Tageszahl VIEL einfacher in einem Timestamp verwandeln.)

Viele Grüße,
Christian