Christian Seiler: Datums- und Zeitberechnung mit PHP, Schaltjahre, Zeitzonen

Beitrag lesen

Hallo Dodwin,

Zudem: Meine korrektere Funktion mit größerem Wertebereich wäre hier sowieso schneller. ;-)

Ähhmm... Hast du mit der Hand gestoppt? ;)

Nein. ;-)

Ich habe folgendes genutzt:

<?php  
  
function start_timer() {  
  GLOBAL $script_start_time;  
  $microtime=explode(" ", microtime());  
  $script_start_time=$microtime[1]+$microtime[0];  
}  
  
function stop_timer($stellen) {  
  GLOBAL $script_start_time;  
  $microtime = explode(" ", microtime());  
  $script_stop_time = $microtime[1]+$microtime[0];  
  return number_format(($script_stop_time-$script_start_time),$stellen);  
}  
  
function wochentag ($year, $month_num, $day) {  
  
  $dif = $year - 1990;                        // 1. Jan 1990 war ein Montag  
  $leap_year_dif = $dif;                      // Anzahl der Schaltjahre herausfinden  
  if ($month_num > 2) $leap_year_dif++;       // ...  
  $leap_year = ceil(($leap_year_dif-2)/4);    // ...  
  $dif = $dif*365 + $leap_year;               // Tage berechnen  
  if ($month_num > 1) $dif += 31;             // Tage für Monate dazurechnen  
  if ($month_num > 2) $dif += 28;  
  if ($month_num > 3) $dif += 31;  
  if ($month_num > 4) $dif += 30;  
  if ($month_num > 5) $dif += 31;  
  if ($month_num > 6) $dif += 30;  
  if ($month_num > 7) $dif += 31;  
  if ($month_num > 8) $dif += 31;  
  if ($month_num > 9) $dif += 30;  
  if ($month_num > 10) $dif += 31;  
  if ($month_num > 11) $dif += 30;  
  if ($month_num > 12) $dif += 31;  
  $dif += $day-1;                             // Tag dazurechnen  
  
  return ($dif % 7);                      // Wochentag ausrechnen  
}  
  
start_timer();  
  
/////////////////////////////// Beginn der Wochentag-Berechnung  
  
$year = 2007;  
$month_num = 9;  
$day = 20;  
  
for ($i=0;$i<1000000;$i++) {  
  $weekday = wochentag ($year, $month_num, $day);  
}  
  
/////////////////////////////// 0 => Montag  
/////////////////////////////// 1 => Dienstag  
/////////////////////////////// ...  
/////////////////////////////// 6 => Samstag  
  
/////////////////////////////// Ende der Wochentag-Berechnung  
  
echo stop_timer(9);  
  
?>

Meine Funktion:

<?php  
  
function start_timer() {  
  GLOBAL $script_start_time;  
  $microtime=explode(" ", microtime());  
  $script_start_time=$microtime[1]+$microtime[0];  
}  
  
function stop_timer($stellen) {  
  GLOBAL $script_start_time;  
  $microtime = explode(" ", microtime());  
  $script_stop_time = $microtime[1]+$microtime[0];  
  return number_format(($script_stop_time-$script_start_time),$stellen);  
}  
  
start_timer();  
  
function wochentag ($jahr, $monat, $tag, $g = true) {  
 if ($monat <= 2) {  
  $jahr--;  
  $monat += 12;  
 }  
 if ($g) {  
  $jahrhundert = (int) (($jahr + 4800) / 100) - 48;  
  $korrektur = 2 - $jahrhundert + (int) (($jahrhundert + 48) / 4) - 12;  
 } else {  
  $korrektur = 0;  
 }  
 $jul_tag_zahl = (int) (365.25 * ($jahr + 4716))+ (int) (30.6001 * ($monat + 1)) + $tag + $korrektur - 1524;  
 return $jul_tag_zahl % 7;  
}  
  
$year = 2007;  
$month = 9;  
$day = 20;  
  
for ($i=0;$i<1000000;$i++) {  
  $weekday = wochentag ($year, $month, $day);  
}  
  
echo stop_timer (9);  
  
?>

Zwei Unterschiede zu Deinem Code: Ich habe bei BEIDEN nur die Monatsnummer verwendet (das array_search käme bei beidne dazu und wäre deswegen eine konstante Zeit und nicht hilfreich zum Vergleichen der reinen Laufzeit des unterschiedlichen Codes) und Deinen Teil habe ich auch in eine Funktion gepackt, so wie es im tatsächlichen Code dann wohl auch genutzt würde. Achja, und ich hab 1 Mio statt nur 100 tausend Aufrufe. Ergebnis:

Meine Version: 2.517229080 Sekunden
Deine Version: 3.288582802 Sekunden

System: Pentium M mit 2 GHz, 512 MiB RAM, PHP 5.2.1-pl3-gentoo (cli) (built: May  6 2007 17:39:57).

Und wenn ich BEIDES direkt reinkopiere (ohne Funktion), dann erhalte ich:

Deine Version: 2.056279898s
Meine Version (1): 1.149389029s
Meine Version (2): 1.048664093s

Bei (2) habe ich noch zusätzlich das if ($g) entfernt, da Du ja sowieso nur den gregorianischen Kalender willst.

Klar, wenn Du Deinen Code direkt reinkopiert testest und bei mir den Funktionsaufruf durchführst (kostet Zeit!), dann ist es natürlich logisch, dass Dein Code schneller ist. Wenn ich aber bei BEIDEN gleiche Bedingungen schaffe (d.h. nur den Code teste, der wirklich relevant ist bzw. bei BEIDEN den gleichen Zusätzlichen Code wie Funktionsaufruf reinpacke), dann ist meine Version schneller - und zwar fast doppelt so schnell und das bei größerem Gütligkeitsbereich.

Viele Grüße,
Christian