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.

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!

                                Ratings

                                There are no comments available yet.

                                Here you can write a comment


                                Please enter at least 10 characters.
                                Loading... Please wait.
                                * Pflichtangabe

                                Related topics

                                Einfaches Gästebuch basierend auf php4 und MySQL

                                In diesem Tutorial lernt Ihr wie einfach es ist, ein Gästebuch mit php4 und MySQL zustellen. ...

                                webmaster1@

                                Autor : webmaster1@
                                Category: PHP-Tutorials

                                abhängige Listen

                                In einem Formular sollen neben mehreren anderen Eingabefeldern auch zwei Listen (Select-Felder) zum Einsatz kommen. Dabei soll der Inhalt der zweiten Liste vom gewählten Wert der ersten Liste abhängig verändert werden. ...

                                Patrick_PQ

                                Autor : Patrick_PQ
                                Category: mySQL-Tutorials

                                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. ...

                                EVAMasters

                                Autor : EVAMasters
                                Category: PHP-Tutorials

                                Counter auf MySQL Basis

                                Neben der Möglichkeitet, einen Counter per Textfiles zu programmieren, besteht auch die Möglichkeit, MySQL zu verwenden. ...

                                Lukas Beck

                                Autor : Lukas Beck
                                Category: PHP-Tutorials

                                Installation von MySQL auf Linux

                                SuSE Linux Pro 8.2 mit mysql einfach installieren ...

                                Moqui

                                Autor : Moqui
                                Category: Linux & Server Tutorials

                                Login Skript mit OOP, Sessions und einer MySql Datenbank (Teil 1)

                                Realisierung eines Login Skriptes mit einer MySql Datenbank, Sessions und PHP mit Objekt orientierter Programmierung. ...

                                Samir

                                Autor : Samir
                                Category: PHP-Tutorials

                                Fortschrittsbalkens mit PHP

                                ProgressClass stellt eine PHP-Klasse für die dynamische Anzeige und Veränderung eines Fortschrittsbalkens zur Verfügung. ...

                                what@

                                Autor : what@
                                Category: PHP-Tutorials

                                Programmierung - SQL

                                Dieser SQL-Kurs wendet sich vor allem an Programmierer, die mit Hilfe von SQL auf Datebaken zugreifen, und an alle, die Datenbanken neu entwerfen, erweitern oder abändern wollen ...

                                webmaster205@

                                Autor : webmaster205@
                                Category: mySQL-Tutorials

                                Publish a tutorial

                                Share your knowledge with other developers worldwide

                                Share your knowledge with other developers worldwide

                                You are a professional in your field and want to share your knowledge, then sign up now and share it with our PHP community

                                learn more

                                Publish a tutorial