Spielereien mit Zeit und Datum
Das Rechnen mit Datum und Zeit ist nur selten unproblematisch, PHP stellt uns dafür zahlreiche Funktionen zur Verfügung. Wir wollen uns im folgenden ein paar davon ansehen und an Beispielen erproben.
2010-04-09 07:51:37 2010-04-09 07:51:37 Stephane
Ein Anfang mit time() und date()
Die formatierte Ausgabe von Zeit und der Vergleich verschiedener Zeitangaben ist immer wieder ein beliebtes Thema welches für viel "Freude" sorgt, besonders wenn Zeitangaben aus verschiedenen Quellen stammen und unterschiedlich formatiert sind.
Eine unverzichtbare, wenn auch nicht ganz unproblematische Hilfe bei Berechnungen
oder Vergleichen ist die Unix-Zeit
(siehe http://de.wikipedia.org/wiki/Unixzeit), eine absolute Angabe der vergangenen Sekunden seit dem 1.1.1970.
Während Zeitangaben aus Datenbanken, Formularergebnissen oder XML-Dateien sich
oft vom Aufbau und Syntax her unterscheiden, bietet das Unix-Zeitformat eine absolute
Angabe, mit der leichter gerechnet, verglichen und sortiert werden kann.
PHP bietet mehrere einfache Funktionen um mit der Unix-Zeit zu arbeiten.
echo time(); echo date('d.m.Y', 1269351978);
"time()" liefert die aktuelle Unix-Zeit im Moment des Aufrufs zurück.
Mit "date()" kann eine Unix-Zeit fast beliebig in eine normal formatierte
Zeit umgewandelt werden.
"date" erhält als ersten Parameter einen String mit
dem die Formatierung der Ausgabe festgelegt wird.
Als optionalen, zweiten Parameter kann eine Unix-Zeitangabe
in der Form "date('String', optionale Zeitangabe als Unix-Zeit);"
übergeben werden. Auf der Basis dieser optionalen Angabe wird das
formatierte Datum generiert. Ist der zweite Parameter nicht gesetzt wird die aktuelle Zeit verwendet.
Einige wichtige Parameter für eine formatierte Zeitangabe: d, Tag mit führender Null, sonst j m, Monat mit führender Null, sonst n y, Jahr, zweistellig Y, Jahr, vierstellig H, Stunden mit führender Null, sonst G i, Minuten mit führender Null s, Sekunden mit führender Null t, Anzahl der Tage des Monats z, Tag des Jahres w, Wochentag als 0-6 (Wochenbeginn ist mit 0 Sonntag) U, Unix-Zeit echo date('d.m.Y H:i:s').' entspricht '.date('U').' oder '.time();
Zeichen wie Punkt, Bindestrich, Leerzeichen können beliebig gesetzt werden. Um Wortzeichen als Literale zu verwenden, müssen diese in der bekannten Form escaped werden: "Hallo Welt". Sinnvoll ist dies natürlich nur bei kurzen Texten.
echo date('Unix-Zeit: U');
Es gibt noch weitere Parameter für eine formatierte Ausgabe, die teilweise aber Ausgaben in englischer Sprache veranlassen. Wollen wir einen Wochentag oder einen Monat lesbar ausgeben, müssen wir dies bei der Verwendung von date() selbst berechnen.
$Wochentag = array('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag',_ 'Freitag', 'Samstag'); echo $Wochentag[date('w')]; $Monat = array('0', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli',_ 'August', 'September', 'Oktober', 'November', 'Dezember'); echo $Monat[date('n')];
Der große Bruder von date(): getdate()
Werden mehrere Aspekte einer Zeitangabe verwendet, kann es sinnvoll sein die Funktion "getdate()" zu verwenden, die ausgehend von einer Unix-Zeit eine Vielzahl von Zeitwerten als ein Array zurückgibt.
print_r( getdate() );
"getdate" kann optional eine Unix-Zeit übergeben werden auf deren Basis die Werte berechnet werden, ohne übergebene Unix-Zeit wird die aktuelle System-Zeit verwendet. Die berechneten Werte werden immer ohne führende Null dargestellt. Weitere Informationen zu getdate, welches an dieser Stelle der Einfachheit halber nicht verwendet wird, finden sie unter http://php.net/manual/de/function.getdate.php.
Einige wichtige Ergebnisse von getdate: 'seconds', Sekunden 'minutes', Minuten 'hours', Stunden 'mday', fortlaufender Tag des Monats 'wday', Tag der Woche beginnend mit 0 für Sonntag 'mon', Monat 'year', Jahr, vierstellig 'yday', fortlaufender Tag des Jahres 0 oder '0', die Unix-Zeit $Zeit = getdate(); echo $Zeit['mday'].'.'.$Zeit['mon'].'.'.$Zeit['year'];
Der große Bruder von time(): mktime()
Bisher haben wir lediglich die aktuelle Unix-Zeit mit time() erhalten. Um aus einer beliebigen Zeitangabe eine Unix-Zeit zu erhalten, benötigen wir die Funktion "mktime()", der wir beliebige Aspekte einer Zeitangabe von Sekunden bis zum Jahr übergeben.
$Jahr = 2010; $Monat = 04; $Tag = 01; $Stunde = 12; $Minute = 0; $Sekunde = 0; echo ( mktime($Stunde,$Minute,$Sekunde,$Monat,$Tag,$Jahr) );
Auf den Tag gebracht!
In vielen Fällen hat man eine vollständige Zeitangabe mit Datum, Stunden und Minuten, interessiert sich aber nur für Teile der Zeit, beispielsweise für den Tag an sich. In der Praxis möchte man oft wissen vor wie vielen Tagen eine Datei verändert oder erzeugt wurde.
Um die Minuten oder auch die Stunden verschwinden zu lassen benutzen wir unsere Funktion "mktime", der wir wir nur die Aspekte Monat, Tag und Jahr zur Berechnung der Unix-Zeit übergeben. Alle anderen Angaben können lassen wir außer acht, bzw. setzen sie auf Null. Mit dem Ergebnis in Form der Unix-Zeit können wir komfortabel weitere Berechnungen durchführen. Beispielsweise ziehen wir von dem aktuellen Datum ein anderes Datum ab. Das Ergebnis sind die vergangenen Tage in Sekunden, die wir in Stunden (3600 Sekunden) oder in Tage (3600*24 bzw. 86400 Sekunden) umrechnen.
$Jahr = 2010; $Monat = 04; $Tag = 01; echo ( mktime(0,0,0,date('m'),date('d'),date('Y')) - mktime(0,0,0,$Monat,$Tag,$Jahr) )/ (3600*24) ;
Achtung!
Die Parameter der jeweiligen Zeiteinheiten müssen tatsächlich getrennt innerhalb von "mktime" angegeben werden. Eine Kurzform in der Art "mktime(0,0,0,date('m,d,Y'))" gibt keinen Fehler aus, liefert aber falsche und unerwartete Ergebnisse. "mktime" erkennt die Trennung der von date übergebenen Werte nicht, versucht aber die jetzt fehlenden oder falschen Angaben ohne weitere Meldung zu kompensieren.
Das Geheimnis der fehlenden Stunde
Wie vieles andere, so hat auch die einfache Berechnung der Tage mit der Unix-Zeit ein dunkles Geheimnis. An manchen Tagen fehlt uns eine ganze Stunde. So beträgt der Abstand vom 28. zum 29.03.2010 oder vom 29. zum 30.03.2009 nicht ein Tag, also 24 Stunden, sondern lediglich 23 Stunden.
echo ( mktime(0,0,0,03,29,2010) - mktime(0,0,0,03,28,2010) )/ 3600 ; echo ( mktime( 0,0,0,03,30,2009) - mktime( 0,0,0,03,29,2009 ) )/ 3600 ;
Die grausame Realität, dass der Tag tatsächlich keine vollen 24 Stunden hat, holt
uns hier vermutlich ein und verdirbt uns unsere Berechnungen. Man muss also
berücksichtigen, dass das Ergebnis nicht immer einen Integer-Wert liefert.
Sobald ich die tatsälichen Hintergründe kenne, werde ich dies hier
genauer ausführen.
Bis dahin kann man das Ergebnis mit der Funktion "ceil()" etwas "schönen",
indem das Ergebnis zu ganzen Tagen aufgerundet wird.
Vor wie vielen Tagen wurde eine Datei zuletzt bearbeitet?
Nehmen wir einen konkreten Fall bei dem wir wissen möchten, vor wie vielen Tagen eine Datei zuletzt bearbeitet wurde. Wir erfragen mit "filemtime()" die Unix-Zeit der letzten Änderung und schicken von diesem Ergebnis mit Hilfe von "date" den Tag, Monat und das Jahr in die Funktion "mktime". Das gleiche machen wir mit dem aktuellen Datum und ziehen davon das Ergebnis der Datei ab und rechnen es in Tage um.
$t = filemtime('c:/ordner/datei.txt'); $datei = mktime(0,0,0,date('m',$t),date('d',$t),date('Y',$t)); $heute = mktime(0,0,0,date('m'),date('d'),date('Y')); echo ($heute - $datei) / 86400;
Das Alter aus Dateinamen bestimmen
Oft interessiert uns nicht der Zeitpunkt der letzten Bearbeitung, sondern eine Datumsangabe,
die beispielsweite im Dateinamen vorliegt.
Auch hier lesen wir die Datumsangaben aus, rechnen sie wie beschrieben um
und vergleichen das Ergebnis mit dem aktuellen Datum.
Dazu empfiehlt es sich reguläre Ausdrücke zu verwenden.
Natürlich kann man auch mit gängigen Befehlen wie "substr" versuchen
die Datumsangaben auszulesen, schließlich kann man auch mit verbundenen Augen
über eine Straße gehen oder eine Metall-Gabel in die Mikrowelle legen.
Da wir aber alle wissen, dass sich Dateinamen gerade von der Länge her nie wirklich
dauerhaft an festgelegte Konventionen halten, verwenden wir reguläre Ausdrücke.
$Dateiname = 'dateiname24122009-xy-001.jpg'; preg_match('/(dd)(dd)(dddd)/',$Dateiname,$Ergebnis); $tag = $Ergebnis[1]; $monat = $Ergebnis[2]; $jahr = $Ergebnis[3]; $datei = mktime( 0,0,0,$monat,$tag,$jahr ); $heute = mktime(0,0,0,date('m'),date('d'),date('Y')); echo ($heute - $datei) / 86400;
Natürlich kann man den regulären Ausdruck und auch den Programmcode kürzer gestalten, für die Lesbarkeit ist dies aber nicht hilfreich:
preg_match('/(dd)(dd)(d)/','dateiname01042010-xy-001.jpg',$Erg); echo (mktime(0,0,0,date('m'),date('d'),date('Y'))-mktime(0,0,0,$Erg[2],$Erg[1],$Erg[3]))/86400;
Gestern, heute, übermorgen oder "the icing on the cake"
Manchmal lohnt es sich doch bis zum Ende weiterzulesen, wir kommen jetzt zu einer der interessantesten Funktionen.
Wir erhalten mit Hilfe von "time()" das Jetzt, mit "date()" und "mktime()"
definierte Zeitpunkte und können Zeitangaben fast beliebig formatieren
und umwandeln.
Was uns noch fehlt ist ein definiertes Gestern, Heute, Morgen und ein Irgendwann.
Natürlich können wir auf der Basis der bekannten Funktionen entsprechende Berechnungen
durchführen, aber PHP macht es uns leichter mit der Funktion strtotime()
(siehe http://php.net/manual/de/function.strtotime.php).
Eigentlich erzeugt strtotime die Unix-Zeit auf der Basis einer englischen Zeitangabe, also nicht viel neues. Wenig augenscheinlich ist aber die Möglichkeit mit strtotime aus einer Unix-Zeit relative Zeitangabe in der Form heute, morgen oder gestern ableiten zu lassen.
Als erstes sehen wir uns absolute Angaben an, die ausgehend vom Jetzt den jeweiligen Tag an sich liefern, also ohne anhängende Minuten oder Sekunden:
strtotime('today'); strtotime('tomorrow'); strtotime('yesterday'); echo date('d.m.y H.i.s',strtotime('tomorrow')),' ist Morgen ';
Noch interessanter sind die Angaben für "noon", die uns die
Mittagszeit, 12 Uhr und "midnight", die uns den Tag um Mitternacht,
also auch wieder ohne anhängende Minuten oder Sekunden liefern.
Diesen Angaben können wir auch eine beliebige Unix-Zeit als zweiten
Parameter mitgeben. Von diesem Tag erhalten wir ohne Aufwand
die für Datenbanken oftmals relevante Zeit 12:00:00 des Tages und bei
"midnight" den Tag an sich.
strtotime('noon'); strtotime('midnight'); strtotime('noon',1270113217); strtotime('midnight',1270113217); echo date('d.m.y H.i.s',strtotime('noon',1270113217)); echo date('d.m.y H.i.s',strtotime('midnight',1270113217));
next, last, + und -
Aber das ist noch nicht alles. "strtotime" kennt als Paramter noch weitere Angaben: Sekunden bis zum Jahr können mit einer Angabe wie "next", "last" oder +/-1 bis +/-n verknüpft werden und liefern ausgehend vom Jetzt oder einer angegebenen Unix-Zeit berechnete Zeitangaben in der Vergangenheit oder der Zukunft. Bei der Berechnung von +/-1 bis +/-n können auch mehrere Zeitangaben kombiniert werden.
Spielen sie einfach ein wenig mit den hier angegebenen Beispielen:
echo date('d.m.y H.i.s',strtotime('next day')); echo date('d.m.y H.i.s',strtotime('last year')); echo date('d.m.y H.i.s',strtotime('next day', 1270116000)); echo date('d.m.y H.i.s',strtotime('last year', 1270116000)); echo date('d.m.y H.i.s',strtotime('+1 minute', 1270116000)); echo date('d.m.y H.i.s',strtotime('-2 hour', 1270116000)); echo date('d.m.y H.i.s',strtotime('-1 day')); echo date('d.m.y H.i.s',strtotime('-2 days')); echo date('d.m.y H.i.s',strtotime('+4 week')); echo date('d.m.y H.i.s',strtotime('+4 weeks')); echo date('d.m.y H.i.s',strtotime('+1 year'));
Und weiter?
Dies war nur eine kleine Einführung, die hoffentlich etwas hilfreich ist.
Wer weiter gehen möchte findet unter http://php.net/manual/de/ mit
"strftime" und der DateTime-Klasse weitere
interessante Aspekte der Arbeit mit der Zeit unter PHP.
Oder er fordert einfach einen zweiten Teil als Fortsetzung zu dieser Einführung.
Kommentare oder Verbesserungen sind natürlich immer willkommen!
Vielen Dank!
Erfahrungen
Hier Kannst Du einen Kommentar verfassen
Verwandte Beiträge
plotting masters - a professional guide - Teil II
Grafische Interpolation und Bestapproximation von numerischen Wertepaaren: Wir wollen Punkte auf einer Zeichenebene über verschiedene Verfahren miteinander verbinden. ...
Autor :
EVAMasters
Kategorie:
PHP-Tutorials
ASCII Datenbanken
ASCII Datenbanken sind eigentlich nur Textdateien, in denen man Daten speichert, die durch ein Trennzeichen voneinander getrennt sind. Dieses Tutorial zeigt wie es geht. Mit Übung und Lösung ...
Autor :
deep_space_nine@
Kategorie:
PHP-Tutorials
MySQL Klasse
In meinem kleinen Tutorial zeige ich euch, wie ihr ganz einfach eine kleine MySQL Klasse schreiben könnt. ...
Autor :
Borlabs
Kategorie:
mySQL-Tutorials
grafischen Counter
Oftmals wird gefragt wie man einen grafischen Counter mit PHP realisieren könnte. Hier ist die Antwort ...
Autor :
t63@
Kategorie:
PHP-Tutorials
Zugriff auf die Facebook Graph API mit PHP
In diesem Beispiel zeigt Joey Rivera wie man auf Facebook mit Hilfe von PHP und der Facebook Graph API zugreifen kann. ...
Autor :
admin
Kategorie:
PHP-Tutorials
Verschlüsselungsalgorithmus
Dieses Tutorial zeigt einen Verschlüsselungsalgorithmus von Texten nach dem PHP Data Encryption Standard. ...
Autor :
Lukas Beck
Kategorie:
PHP-Tutorials