PHP/Zeit- und Datumsfunktionen

Aus Mikiwiki
< PHP
Version vom 17. Januar 2009, 11:04 Uhr von Michi (Diskussion | Beiträge) (Die Seite wurde neu angelegt: == Kalenderfunktionen == Alle Kalender basieren auf einem identischen Anfangsdatum, von dem ausgehend der benötigte Tag berechnet wird. Dies ist der sogenannte julian...)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Kalenderfunktionen

Alle Kalender basieren auf einem identischen Anfangsdatum, von dem ausgehend der benötigte Tag berechnet wird. Dies ist der sogenannte julianische Tag, der 1. Januar 4713 vor Christus. Wenn ein Datum als beispielsweise vom gregorianischen in den julianischen Kalender umgerechnet werden soll, wird erst die Differenz zum julianischen Tag in dem einen Kalender bestimmt und dann die Anzahl im anderen berechnet.

Funktion Beschreibung
jdtogregorian Wandelt ein Datum des Julianischen Kalenders in das gregorianische Format.
gregoriantojd Wandelt das gregorianische Format in eine Datum des Julianischen Kalenders.
jdtojulian Wandelt ein julianisches Tagesdatum in einen julianischen Tageswert um (für Berechnungen mit diesem).
juliantojd Wandelt einen julianischen Tageswert in ein julianisches Tagesdatum um.
jdtojewish Wandelt einen julianischen Tageswert in ein Datum des Jüdischen Kalenders um.
jewishtojd Wandelt ein Datum des Jüdischen Kalenders in einen julianischen Tageswert um.
jdtofrench Wandelt ein julianisches Datum in ein ein Datum des Kalenders der französischen Republik um.
frenchtojd Wandelt ein Datum des Kalenders der französischen Republik in ein julianisches Datum um.
jdmonthname Gibt einen Monatsnamen zurück, wobei die Datumsangabe dem Julianischen Kalender entsprechen muss. Die Ausgabe kann durch einen zweiten Parameter gesteuert werden, der den Ursprungskalender bestimmt.
jddayofweek Gibt den Wochentag zurück, entweder als Zahl oder als Wort (aus dem englisch-gregorianischen Kalender).
easter_date Gibt den Unix-Zeitcode für Ostersonntag des angegebenen Jahres zurück; die Funktion ist also nur innerhalb der Unix-Zeitdefinition zwischen 1970 und 2037 einsetzbar.
easter_days Gibt die Anzahl der Tage aus, die Ostern nach dem 21. März des angegebenen Jahres liegt.
cal_days_in_month Gibt die Anzahl der Tage eines bestimmten Monats in einem bestimmten Jahr des gewählten Kalenders aus. Mögliche Kalender sind:
Konstante Bedeutung
CAL_FRENCH Kalender der französischen Republik
CAL_GREGORIAN Gregorianischer Kalender
CAL_JEWISH Jüdischer Kalender
CAL_JULIAN Julianischer Kalender
cal_from_jd Wandelt ein Datum im julianischen Format in eines der unterstützten Kalender und gibt weitere Informationen zurück.

Anzeige des Osterdatums.

<?php
setlocale(LC_TIME, "de");
echo "Ostern ist am " . strftime("%d.%m.%Y", easter_date(2008));
?>
Ostern ist am 23.03.2008

Anzeige der Anzahl Tage des Monats Februar im Jahre 2008.

<?php
echo cal_days_in_month(CAL_GREGORIAN, 2, 2008);
?>
29

Datumsfunktionen

Funktion Beschreibung
checkdate Gibt "TRUE" zurück, wenn das angegebene Datum plausibel ist. Benötigt drei Argumente für Monat, Tag und Jahr (in dieser Reihenfolge).
date Formatiert ein Datum für die Ausgabe, sodass lokale Besonderheiten leicht berücksichtigt werden können. Die Funktion benötigt zwei Argumente: eine Formatieranweisung und eine Zeitinformation als Unix-Zeitstempel. Wenn der zweite Parameter entfällt, wird die aktuelle Zeit genommen. Innerhalb der Formatieranweisung ist eine Vielzahl von Symbolen erlaubt (siehe Formatierung von Datumsangaben).
getdate Gibt ein assoziatives Array mit Datums- und Zeitangaben zurück.
gmdate Formatiert ein Datum unter Berücksichtigung der GMT für die Ausgabe.

Für die Arbeit mit Datumswerten ist das aktuelle Datum oft von grosser Bedeuetung. PHP bezieht sich allerdings immer auf das Systemdatum des Rechners. Wird PHP in den USA gehostet, so wird das Ergebnis nicht unbedingt den Erwartungen entsprechen, wenn etwa die Benutzer zeitabhängig begrüsst werden sollen.

Folgendes Beispiel zeigt die Anwendung der Funktion "date".

<?php
echo date("l dS of F Y")                    . "<br />";
echo date("l dS of F Y h:i:s A")            . "<br />";
echo "The 1st of July 2000 was a ";
echo date("l", mktime(0, 0, 0, 7, 1, 2000)) . "<br />";;
?>

Friday 05th 2008f September 2008
Friday 05th 2008f September 2008 11:31:35 AM
The 1st of July 2000 was a Saturday

Das folgende Beispiel zeigt, wie mit Datumsinformationen Datumsberechnungen angestellt werden können. Die Funktion "mktime" gibt dabei den Zeitstempel für ein Datum zurück (siehe Zeitfunktionen).

<?php
$morgen        = mktime(0, 0, 0, date("m"), date("d") + 1, date("Y"));
$letztermonat  = mktime(0, 0, 0, date("m") - 1, date("d"), date("Y"));
$naechstesjahr = mktime(0, 0, 0, date("m"), date("d", date("Y") + 1));
setlocale(LC_TIME, "ge");
printf ("Tomorrow is %s, the name of the last month is %s.", 
        strftime("%A", $morgen),
        strftime("%B", $letztermonat));
?>
Tomorrow is Saturday, the name of the last month is August.

Information über die Konfiguration

Die Funktion "nl_langinfo"" ermittelt Informationen über die Lokalisierungskonfiguration, um das Verhalten von Funktionen wie "strftime" bestimmen zu können. Folgendes Beispiel gibt die Fomratierungsanweisung zurück, die zuletzt von der Funktion "strftime" benutzt wurde.

$info = nl_langinfo(D_FMT);

Weitere Parameter finden sich in der folgenden Tabelle.

Parameter Beschreibung
CODESET Zeichensatz.
D_F_FMT Zeit und Datum für "strftime".
D_FMT Datum für "strftime".
T_FMT Zeit für "strftime".
DAY_X Für "X" kann ein Wert zwischen 1 und 7 eingesetzt werden, um den Namen des Wochentags zu ermitteln.
ABDAY_X Für "X" kann ein Wert zwischen 1 und 7 eingesetzt werden, um den Kurznamen des Wochentags zu ermitteln (z. B. "Fri").
MON_X Für "X" kann ein Wert zwischen 1 und 12 eingesetzt werden, um den Namen des Monats zu ermitteln.
ABMON_X Für "X" kann ein Wert zwischen 1 und 12 eingesetzt werden, um den Kurznamen des Monats zu ermitteln (z. B. "Dec").
RADIXCHAR Zeichen für den Dezimalpunkt.
THOUSEP Tausendertrennzeichen.
YESEXPR Regulärer Ausdruck für "Yes".
NOEXPR Regulärer Ausdruck für "No".
CRNCYSTR Währungssymbol.

Zeitfunktionen

Funktion Beschreibung
mktime Ermittelt den Zeitstempel für eine bestimmte Zeitangabe.
gmmktime Ermittelt den Zeitstempel für eine bestimmte Zeitangabe unter Berücksichtigung der Greenwich Mean Time (GMT).
time Gibt den Unix-Zeitstempel sekundengenau zurück. Diese Funktion verfügt über keine Formatiereigenschaften, wie das bei "date" der Fall ist.
microtime Gibt den Unix-Zeitstempel mikrosekundengenau zurück. Diese Funktion verfügt über keine Formatiereigenschaften, wie das bei "date" der Fall ist.
strfime Formatiert eine Zeitangabe.
gettimeofday Gibt ein Array mit Angaben zur aktuellen Zeit zurück. Die Elemente des Arrays werden folgendermassen indiziert.
Element Bedeutung
sec Sekunden
usec Mikrosekunden
minuteswest Minuten westlich von Greenwich. Deutschland ist im Winter -60 Minuten entfernt.
dsttime Typ der Sommerzeitkorrektur. "1" entspricht "mit Korrektur".

Viele Datums- und Zeitfunktionen rechnen mit der internen Ausgabe des Unix-Zeitstempels. Diese Angabe stellt die Anzahl der Sekunden seit dem 1. Januar 1970 00:00 Uhr dar. Um eine solche Angabe für ein bestimmtes Datum zu erhalten, wird die Funktion "mktime" eingesetzt. Der Parameter "sz" ist optional. Wird er auf 1 gesetzt, nimmt die Funktion an, dass sich das Datum in der Sommerzeit befindet. Der Wert 0 ist ausserhalb der Sommerzeit, der Standardwert ist -1 und steht für "unbekannt".

$stamp = mktime(stunde, minute, sekunde, monat, tag, jahr, sz);

Der Zeitstempel für den Frühlingsanfang 2006 wird also folgendermassen ermittelt.

$stamp = mktime(0, 0, 0, 3, 21, 2006);

Folgendes Beispiel zeigt die Ausgaben der Funktion "gettimeofday".

<?php
$time = gettimeofday();
echo $time["usec"]               . "&micro;s<br />\n";
echo date("H:m:s", $time["sec"]) . " (Zeit)<br />\n";
echo $time["minuteswest"]        . " min (Diff zu GMT)<br />\n";
echo $time["dsttime"]            . "<br />";
?>

755082µs
12:09:09 (Zeit)
-120 min (Diff zu GMT)
1

Formatierung von Datumsangaben

Die Funktion "strftime" arbeitet ähnlich wie "date" und formatiert eine Datums- und Zeitangabe anhand einer Formatieranweisung. Die Parameter der beiden Funktionen stimmen allerdings nur teilweise überien und haben in einzelnen Fällen eine völlig andere Bedeutung!

date strftime Beschreibung
a %p "am" oder "pm".
A %r "AM" oder "PM".
B Swatch-Internetzeit. Diese Zeit teilt den Tag ohne Zeitzonen in 1'000 Einheiten.
d %d Monatstag als zweistellige Zahl zwischen "01" und "31" mit führender Null bei einstelligen Werten.
%e Monatstag als Zahl zwischen " 1" und "31" mit führendem Leerzeichen bei einstelligen Werten.
D %a Wochentag mit drei Buchstaben (z. B. "Fri"). "date" verwendet nur englische Bezeichnungen.
F %B Monatsname (z. B. "January"). "date" verwendet nur englische Bezeichnungen.
h Stunde im 12-Stunden-Format zwischen "01" bis "12" mit führender Null bei einstelligen Werten.
H Stunde im 24-Stunden-Format zwischen "00" bis "23" mit führender Null bei einstelligen Werten.
g %I Stunde im 12-Stunden-Format zwischen "1" bis "12" ohne führender Null bei einstelligen Werten.
G %H Stunde im 24-Stunden-Format zwischen "0" bis "23" ohne führende Null bei einstelligen Werten.
i Minuten "00" bis "59" mit führender Null bei einstelligen Werten.
%M Minuten "0" bis "59" als Dezimalwert.
I "1" in der Sommerzeit, sonst "0".
j Monatstag "1" bis "31" ohne führende Null bei einstelligen Werten.
l %A Ausgeschriebener Wochentag (z. B. "Friday"). "date" verwendet nur englische Bezeichnungen.
L Boolescher Werts für das Schaltjahr: "0" oder "1".
m %m Monat "01" bis "12" mit führender Null bei einstelligen Werten.
n Monat "1" bis "12" ohne führende Null bei einstelligen Werten.
M %b Monat als Abkürzung mit drei Buchstaben (z. B. "Jan"). "date" verwendet nur englische Bezeichnungen.
O Zeitdifferenz zum UTC in Stunden als Zeichenkette (z. B. "+0200").
r Datum und Zeit im RFC 822-Format, das folgende Form hat: "Thu, 5 Mar 2008 19:03:00 +0100". Die RFC 822 definiert Datumsformate wie sie in E-Mails verwendet werden.
s %S Sekunden "00" bis "59" mit führender Null bei einstelligen Werten.
S Suffix der englischen Ordnungszahlen: "st", "nd", "rd", "th" usw.
t Anzahl Tage des Monats "28" bis "31".
T Zeitzoneneinstellung des Rechners (z. B. "EST" oder "MDT").
U Sekunden der Unix-Epoche (seit 1. Januar 1970). Entspricht der Ausgabe der Funktion "time".
w %w Wochentag "0" (Sonntag) bis "6" (Samstag).
W Wochennummer des Jahres im ISO-8601-Format (ab erste Woche mit einem Montag drin).
Y %Y Jahr im vierstelligen Format (z. B. "2008").
y %y Jahr im zweistelligen Format (z. B. "08").
z %j Tag im Jahr "0" bis "365".
Z %Z Offset der Zeitzonen gegenüber dem UTC in Sekunden von -43200 bis 43200 (86400 Sekunden entsprechen einem Tag).
%G Jahr im vierstelligen Format (wie "%Y", also z. B. "2008"), aber nur bei vollen Wochen. Angefangene Wochen zählen im vorhergehenden bzw. folgenden Jahr.
%g Jahr im zweistelligen Format (wie "%y", also z. B. "08"), aber nur bei vollen Wochen. Angefangene Wochen zählen im vorhergehenden bzw. folgenden Jahr.
%x Zeit nach lokalen Systemeinstellungen.
%X Datum nach lokalen Systemeinstellungen.
%c Zeit und Datum nach lokalen Systemeinstellungen.
%D Entspricht der Folge "%m/%d/%y" (z. B. "03/31/08").
%U Wochennummer, wobei die Woche mit dem Sonntag beginnt.
%V Kalenderwoche nach ISO 8601.
%W Wochennummer, wobei die Woche mit dem Montag beginnt.
%R Vollständige Zeit im 24-Stunden-Format.
%C Jahrhundert (z. B. "2003" gibt "20" zurück).
%t Tabulator.
%n Zeilenvorschub.
%% Prozentzeichen.

Mit Hilfe der Funktion "setlocale" lassen sich die Ausgaben an die sprachlichen Besonderheiten eines bestimmten Gebiets anpassen.

string setlocale(<category>, <localeID>)

Der Parameter "category" wird durch folgende Werte bestimmt:

Wert Bedeutung
LC_ALL Alle weiteren Angaben.
LC_COLLATE Wirkt auf Zeichenkettenvergleiche.
LC_CTYPE Wirkt auf zeichensetzung (z. B. in "strtoupper()").
LC_MONETARY Wirkt auf Währungsfunktionen (z. B. "localeconv()").
LC_NUMERIC Bestimmt die Dezimaltrennzeichen.
LC_TIME Wirkt auf Datums- und Zeitformatierungen mit "strftime()".

Als "localeID" wird der ISO-Landescode angegeben, auf dessen Parameter die Ausgaben gesetzt werden sollen. Wird eine leere Zeichenkette genutzt, so versucht PHP entsprechende (gleichlautende) Variablen in der Betriebssystemumgebung zu finden. Wird eine "0" angegeben, so werden die aktuellen Einstellungen nicht geändert, aber zurückgegeben. Die Funktion gibt "FALSE" zurück, wenn der lokale Code nicht implementiert wurde.

Die ISO-Ländercodes berücksichtigen sowohl die Sprachen als auch das Land. Für Deutschland heisst der Code "de_DE", für die Schweiz gibt es die Varianten "de_CH" und "fr_CH". Die konkrete Umsetzung hängt jedoch vom Betriebssystem ab. Unix liefert diese Tabellen in "/usr/share/language" mit. Je nach System gelten die dort befindlichen Daten. Allgemein gilt folgende Regel für Unix-Systeme:

  • Das Grundformat ist "sprache_LAND", also z. B. "de_CH".
  • Zur Ausgabe bestimmter Sonderzeichen einer Sprache kann eine Codeseite angegeben werden, z. B. "kr_KR.949".

Der zweite Parameter "localeID" kann auch entfallen - dann wird die aktuelle Rechnerzeit gesetzt. Das scheint aber - wie aus der Ausgabe ersichtlich - ohnehin einen Dreck zu bewirken...

<?php
print(strftime("%A heisst auf Deutsch "));
setlocale(LC_TIME, "ge");
print(strftime("%A.<br />\n"));
?>
Friday heisst auf Deutsch Friday.

Die lokalisierten Einstellungen wirken sich auch auf die interne Verarbeitung von Zahlen aus. Normalerweise gilt für alle numerischen Werte die Schreibweise mit Dezimalpunkt. Daran ändern auch die lokalen Einstellungen mit "setlocale" nichts. Werden dagegen Zahlen als Zeichenketten angegeben und mit diesen einfache mathematische Operationen ausgeführt, so rechnet PHP auch mit Dezimalkommata. das folgende Beispiel zeigt, wie das aussieht. Die Funktion "setlocale" basiert auf der internen Umwandlung zwischen Datentypen, die PHP automatisch vornimmt. Da der Operator "*" auf Zeichenketten keine Anwendungfinden kann, wird der passende Datentyp (hier "double") ermittelt und dann die Multiplikation ausgeführt.

<?php
setlocale(LC_ALL, "ge");
$net   = "1234,56";
$gross = "1,16" * $net;
printf("Netto: %04.2f, Brutto: %04.2f", $net, $gross);
?>
Netto: 1234.00, Brutto: 1234.00

Die folgende Zeile ist dagegen nicht zulässig.

$net = 1234,56;

Vor dem intensiven Einsatz der Funktion "setlocale" sollte man sich mit der Funktion "number_format" beschäftigen. Die Formatierung zur Ausgabe birgt deutlich weniger Risiken und ist weitestgehend versions- und plattformunabhängig.

Es ist ausserdem eine gute Idee, alle internen Berechnungen und Verarbeitungen mit den Standarddatenformaten (also englischen Zahlen und Daten) im Unix-Zeitstempel-Format vorzunehmen und nur für die Ausgabe umzuwandeln. Dies vermindert die Zahl der Eingriffe bei der Übertragung des Skripts von einem System auf ein anderes ganz erheblich.

Datumsbehandlung

Die folgende Funktion fragt ein HTML-Formularfeld ab und wandelt ein darin enthaltenes Datum so um, dass es ohne Probleme in das Datumsfeld einer MySQL-Tabelle eingefügt werden kann. Das interne Datumsformat in MySQL sieht ohne Zeitangaben wie folgt aus.

YYYY-MM-DD

Folgende Eingabeformate sind zulässig:

  • "d.m.y"
  • "y.m.d"
  • "d.m"
  • "d"

Fehlt ein Datumsbestandteil, so wird die entsprechende Information dem aktuellen Systemdatum entnommen. Gibt die Funktion eine leere Zeichenkette zurück, so konnte das Eingabedatum nicht ausgewertet werden. Die Funktion kann wie folgt benutzt werden.

$date_ok = input2date($date_from_form_field);
<?php
function input2date($idate)
{
  ## Die Funktion "strtok" sucht bei jedem erneuten Aufruf das nächste
  ## Element in der Zeichenkette. Der folgende Teil zerlegt die
  ## Zeichenkette tatsächlich in vier Teile.
  $token="-./ ";
  $p1 = strtok($idate, $token);
  $p2 = strtok($token);
  $p3 = strtok($token);
  $p4 = strtok($token);
  $date = $y = $m = $d = "";
  ## Wenn hier zweistellige Jahreszahlen akzeptiert werden, muss eine
  ## Priorität festgelegt werden, da sonst Daten wie "11.3.03" nicht
  ## richtig erkannt werden können (könnte 11. März 2003 oder auch 3.
  ## November 2013 sein).
  ## Prüfen der Kombination "d.m.y" (Standard)
  if (($p1 > 0 && $p1 < 32) && ($p2 > 0 && $p2 < 13) && ($p3 > 0))
  {
    $y = $p3;
    $m = $p2;
    $d = $p1;
  }
  ## Alternative Prüfung auf "y.m.d"
  elseif ($p1 > 0 && ($p2 > 0 && $p2 < 13) && ($p3 > 0 && $p3 < 32))
  {
    $y = $p1;
    $m = $p2;
    $d = $p3;
  }
  ## Prüfen der Kombination "d.m"
  if ($y == "" && ($p3 == "") && ($p2 > 0 && $p2 < 13) && ($p1 > 0 && $p1 < 32)) 
  { 
    $y = date("Y");
    $m = $p2;
    $d = $p1;
  } 
  ## Prüfen der Kombination "d"
  if ($y == "" && ($p3 == "") && ($p2 == "") && ($p1 > 0 && $p1 < 32))
  {
    $y = date("Y");
    $m = date("m");
    $d = $p1;
  }
  ## Hinzufügen von 1900 oder 2000 zum Jahr
  if ($y != "" && $y <= 99)
  { 
    if ($y >= 70) $y = $y + 1900;
    if ($y <  70) $y = $y + 2000;
  }
  if ($y != "")
  {
    if (checkdate($m, $d, $y)) $date = "$y-$m-$d";
  }
  return $date;
}
?>
Geben Sie einen Datumswert ein und beobachten Sie die Reaktion:
<p>
<form method="post" action="<?=$_SERVER['PHP_SELF']?>">
  Testwert:
  <input type="text" size="8" name="checkdate" value="">
  <input type="submit" value="Testen">
</form>
<hr noshade size=1>
<?php
if (isset($_POST['checkdate']))
{
  echo "Das Datum <b>{$_POST['checkdate']}</b> im MySQL-Format ist: ";
  echo "<b>";
  echo input2date($_POST['checkdate']);
  echo "</b>";
}
?>