Christian Seiler: date()

Beitrag lesen

Hallo Tom,

Was gibt denn date('w') bei einem Timestamp, der zu groß oder negativ ist?
Das habe ich vergessen...

Negative Timestamps:
   - Windows: funktionieren nicht
   - Andere Betriebsysteme: Bis zur Integer-Grenze runter (irgendwann im
     Jahr 1901 für 32-bit-Systeme) funktioniert's problemlos.

Betragsmäßig zu große Timestamps: Die kriegt man in PHP gar nicht erst in eine Integer-Variable - und deswegen braucht man auch gar nicht darüber spekulieren, was eine Funktion ausspucken würde, die eine Integer-Variable erwartet.

Wenn man portabel Wochentage für Daten kleiner als 1970 berechnen will (naja, und für > 2038, aber ehrlich gesagt leuchtet mir nicht ein, warum man das tun sollte ;-)), dann muss man das selbst tun. Am einfachsten wandelt man das Datum in eine Julianische Tageszahl um und berechnet dann den Modulo zu 7 - dann erhält man den Wochentag:

// $g: Ob der gregorianische oder julianische Kalender  
// verwendet werden soll; vor dem 15.10.1582 GC (5.10.1582 JC)  
// wurde nur der julianische Kalender verwendet, danach  
// hängt die Verwendung des Kalenders von der Lokalität ab  
// (Griechenland hat erst Anfang des 20. Jhdts. auf GC umgestellt)  
function wochentag ($jahr, $monat, $tag, $g = true) {  
 static $wochentage = array (  
  'Montag',  
  'Dienstag',  
  'Mittwoch',  
  'Donnerstag',  
  'Freitag',  
  'Samstag',  
  'Sonntag'  
 );  
  
 // Das Jahr fängt im März an, dann lassen sich die  
 // Monatsanfänge per linearer Regression an eine Gerade  
 // anpassen.  
 if ($monat <= 2) {  
  $jahr--;  
  $monat += 12;  
 }  
  
 if ($g) {  
  // korrektur für den gregorianischen Kalender:  
  // Die Schaltjahresregel ist hier eine andere, deswegen  
  // muss ein Korrekturterm hinzugefügt werden  
  $jahrhundert = floor ($jahr / 100);  
  $korrektur = 2 - $jahrhundert + floor ($jahrhundert / 4);  
 } else {  
  $korrektur = 0;  
 }  
 // die julianische tageszahl ist definiert als die anzahl an  
 // tage seit Montag, 1. Januar 4713 v.u.Z. JC (d.h. $jahr == -4712)  
 // Wenn wir also 4716 Jahre darauf addieren, dann erhalten wir  
 // 4 Jahre zuveil (dafür macht uns floor() keine Probleme), die  
 // 4 Jahre (1461 Tage) müssen wir später aber wieder abziehen  
 $jul_tag_zahl = floor (365.25 * ($jahr + 4716));  
  
 // Monatsanteil: Wir gehen davon aus, dass das Jahr im März beginnt,  
 // die Folge floor (30.6001 * ($monat + 1)) - 122 ergibt gerade die  
 // korrekten Offsets für die Monate (0 für März, 31 für April, 61 für  
 // Mai, etc.) - die -122 werden später berücksichtigt  
 $jul_tag_zahl += floor (30.6001 * ($monat + 1));  
  
 // Den Tag addieren wir einfach darauf - allerdings müssen wir  
 // später 1 abziehen, da der Tag 1 ja den Abstand 0 haben soll  
 $jul_tag_zahl += $tag;  
  
 // Die Korrektur für den gregorianischen Kalender muss berücksichtigt  
 // werden.  
 $jul_tag_zahl += $korrektur;  
  
 // Nun wird noch der feste Offset von obigen Rechnungen berücksichtigt:  
 // 1461 Tage zuviel von der Jahresberechnung  
 // 122 Tage zuviel von der Monatsberechnung  
 // 60 Tage zuwenig, weil das Jahr eben nicht im März anfängt  
 //                  (4713 v.u.Z. war ein Schaltjahr)  
 // 1 Tag zuviel von der Tageszahl  
 // = 1524 Tage zuviel  
 $jul_tag_zahl -= 1524;  
  
 // 1.1.4713 v.u.Z. JC war ein Montag hätte $jul_tag_zahl 0, d.h.  
 // $jul_tag_zahl % 7 ergibt den Wochentag mit 0 als Montag  
 return $wochentage[$jul_tag_zahl % 7];  
}

Wenn man dann andere Berechnungen anstellen will, wie z.B. die Anzahl der Tage zwischen zwei Daten, dann kann man beide Daten einfach in eine Julianische Tageszahl umwandeln und die dann voneinander abziehen.

Viele Grüße,
Christian