Bernhard: deustches Datum per PHP überprüfen

Hallo, ich bin so ziemlich neu auf dem Gebiet der Programmierung. Ich habe ein deutschen Datum das ich über ein Input Feld in einem HTML Formular eingebe. Jetzt möchte ich das deutsche Datum, das so vorliegt 16.03.2020 mittels PHP überprüfen, damit ich es speichern kann.

checkdate ( int $month , int $day , int $year )

Gibt es so einen Befehl nicht auch für unser deustches Datum.

Bernhard

  1. Jetzt möchte ich das deutsche Datum, das so vorliegt 16.03.2020

    Das ist kein Datum, sondern ein String. Der wieder kann (in PHP) explodieren.

    Wenn Du also dafür sorgst, dass der String am Punkt zerbricht, dann hast Du Tag, Monat und Jahr.

    list( $d, $m, $y ) = explode( '.', $sDatum, 3 );
    if ( checkdate ($m , $d , $y ) {
       echo "Oha. Das Datum ist möglicherweise richtig und gültig." . PHP_EOL;
    }
    
    • Und dann wäre da noch: strptime. Damit kann man versuchen, einen String als Datums- und/oder Zeitangabe zu interpretieren.
    1. Hallo,

      ich habe mir mal erlaubt, dein Code-Beispiel zu korrigieren. Kannst deinen Fehler gern über den Versionsvergleich nachvollziehen.

      Ciao,
       Martin

      --
      Ich stamme aus Ironien, einem Land am sarkastischen Ozean.
      1. Danke! Natürlich list(), nicht „lauschen“.

    2. Ich hätte noch einen, sehr dringenden Tipp:

      <input type="date">
      

      Der liefert das Datum als ISO-Datum (YYYY-MM-DD).

  2. Hallo Bernhard,

    das ist eine merkwürdige Frage. Du bekommst vom Browser einen String geschickt (in $_POST oder $_GET). Den musst Du für checkdate ohnehin erstmal zerlegen und in Zahlen umwandeln, bevor Du checkdate nutzen kannst.

    checkdate($_POST['datum'])
    

    würde ohnehin nicht funktionieren.

    Eine einfache Möglichkeit der Prüfung ist date_create_from_format.

    $datum = date_create_from_format("d.m.Y", $_POST['datum']);
    if ($datum === FALSE) {
       // falsches Datum, Fehlermeldung
    }
    

    Du musst das Muster d.m.Y exakt wie angegeben verwenden, das steht für 2-stelligen Tag, 2-stelligen Monat und 4-stelliges Jahr. Kleiner Nachteil: die Eingabe "01.13.2020" wird akzeptiert und als 01.01.2021 gedeutet. Und die Eingabe "17.3.2020" wird abgewiesen.

    Wenn Du das so nicht brauchen kannst, dann musst Du die Eingabe über eine Regex (preg_match) oder mit String-Operationen (substr-Funktion) zerlegen und die Teile in Zahlen umwandeln. Die kannst Du dann in der benötigten Reihenfolge an checkdate übergeben.

    Tipps:

    • Zugriff auf einzelne Zeichen geht mit der Index-Schreibweise: $a[2] liefert das dritte Zeichen im String (Indexe beginnen bei 0)
    • Prüfen, ob ein String eine Zahl ist, geht mit der Funktion is_int (oder is_integer, die sind synonym)
    • Umwandeln eines Strings in eine Zahl geht mit intval. intval taugt nicht zum Prüfen auf Zahlen, weil es abbricht wenn keine Ziffer mehr kommt. Bspw. würde "5a" als 5 gedeutet.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. ich bin so ziemlich neu auf dem Gebiet der Programmierung

      das ist eine merkwürdige Frage.

      Neulinge stellen keine merkwürdigen Fragen. Das kommt anderen, die sich mit der Stur- und Dummheit dieser authistischen Computerdinger abgefunden haben, nur so vor…

    2. Hello,

      [•••]
      und wenn Du mir jetzt noch den erlaubten Wertebereich für die Eingangsgröße beschaffen könntest, würdest Du mich für den Tag motivieren.

      Ich habe danach gesucht und bisher leider nichts gefunden.

      Glück Auf
      Tom vom Berg

      --
      Es gibt nichts Gutes, außer man tut es!
      Das Leben selbst ist der Sinn.
      1. Hallo TS,

        sorry, ich kann deinen Gedanken nicht folgen. Was genau suchst Du?

        Motivationshilfe bis dahin:

        ... Tom! Tom! klatsch-klatsch-klatsch
        ... Tom! Tom! klatsch-klatsch-klatsch

        😂🤣 Rolf

        --
        sumpsi - posui - obstruxi
    3. Das Datum geht aber auch !

      $_POST['datum']='42.19.2020';
      
      
      $datum = date_create_from_format("d.m.Y", $_POST['datum']);
      if ($datum === FALSE) {
         // falsches Datum, Fehlermeldung
      }
      
      1. Hallo Bernhard,

        Das Datum geht aber auch !

        $_POST['datum']='42.19.2020';
        
        
        $datum = date_create_from_format("d.m.Y", $_POST['datum']);
        if ($datum === FALSE) {
           // falsches Datum, Fehlermeldung
        }
        

        Ja, ist der 11. August 2021.

        Bis demnächst
        Matthias

        --
        Du kannst das Projekt SELFHTML unterstützen,
        indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
        1. Hallo Matthias Apsel,

          $_POST['datum']='42.19.2020';
          
          $datum = date_create_from_format("d.m.Y", $_POST['datum']);
          

          Ja, ist der 11. August 2021.

          @Bernhard: Das sollte dir bei der Formulierung der Bedingung helfen.

          Bis demnächst
          Matthias

          --
          Du kannst das Projekt SELFHTML unterstützen,
          indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
      2. Hallo Bernhard,

        ja. Werte für Tag oder Monat, die außerhalb des erlaubten Bereichs sind, werden einfach in den Folgemonat oder ins Folgejahr übertragen. Sinn ist vermutlich mal gewesen, Datumsarithmetik zu vereinfachen. Das geht aber eigentlich mit date_add (oder $date->add) besser.

        Wie gesagt:

        Wenn Du das so nicht brauchen kannst

        dann musst Du die Eingabe von Hand zerlegen und an checkdate übergeben. Wenn Du die Zerlegung alleine nicht hinbekommst, dann zeig mal was Du dafür schon selbst geschafft hast und wir gucken dann weiter.

        Rolf

        --
        sumpsi - posui - obstruxi
      3. Das Datum geht aber auch !

        $_POST['datum']='42.19.2020';
        
        
        $datum = date_create_from_format("d.m.Y", $_POST['datum']);
        if ($datum === FALSE) {
           // falsches Datum, Fehlermeldung
        }
        

        Das kommt davon, dass date_create_from_format() intern mktime() benutzt. Damit kann man schöne Sachen berechnen wie den 34. Februar, den dann je nach Jahr auf dem richtigen Tag im März landet. Es ist eine tolle Funktion, kein Fehler.

        Ich hatte schon gefragt, was denn, bitte, Deine Definition eines gültigen Datums sein soll.

        So ist z.B. ein Topf ohne Deckel nach meiner Ansicht ein gültiger Topf. Es gibt aber Personen oder Einsatzfälle, wo das nicht zutrifft.

        Das folgende Beispiel (für die Konsole¹) zeigt eine Prüfung auf eine formale Gültigkeit des Datums, gefolgt von zwei weiteren Prüfungen hinsichtlich einer Eingrenzung:

        <?php
        
        $dateFormat = 'd.m.Y'; #Format des Inputs
        
        $s='02.02.2019'; # Der Input
        
        $sNotBefore = '01.01.2020'; # Nicht vor
        $sNotAfter  = '31.12.2021'; # Nicht nach
        
        #Zerlegen des Datums:
        list( $d, $m, $y ) = explode( '.', $s, 3 ); 
        
        #checkdate prüft formale Richtigkeit:
        if ( checkdate ($m , $d , $y ) ) { 
        	echo "Oha. Das Datum \"$s\" ist möglicherweise richtig und gültig. Ich prüfe mal weiter:" . PHP_EOL;
        	
        	#Für die nachfolgenden Vergleiche werden die Strings in ein DateTime-Objekt umgewandelt:
        	$d          = date_create_from_format( $dateFormat, $s );
        	$dNotBefore = date_create_from_format( $dateFormat, $sNotBefore );
        	$dNotAfter  = date_create_from_format( $dateFormat, $sNotAfter );
        	
        	# DieseDateTime-Objekte kann man vergleichen:
        	if ( $d > $dNotAfter ) {
        			echo "Schade. Das Datum $s sah gültig aus, liegt aber nach dem $sNotAfter."  . PHP_EOL;
        	} elseif ( $d < $dNotBefore ) {
        			echo "Schade. Das Datum $s sah gültig aus, liegt aber vor dem $sNotBefore."  . PHP_EOL;
        	} else {
        			echo "Bestätige: Gültiges Datum $s zwischen (einschließlich) $sNotBefore und $sNotAfter.". PHP_EOL;
        	}
        } else {
        	echo "Ochnee. Das angebliche Datum \"$s\" ist schlicht ungültig." . PHP_EOL;
        }
        

        ¹) Für die umständliche Ansicht via Webserver und Browser füge am Anfang header( 'Content-type: text/plain; charset=utf-8' ); hinzu. Dann speicher es aber auch in der Kodierung "UTF-8 ohne BOM".

        1. Hallo Raketenexemplierer,

          ¹) Für die umständliche Ansicht via Webserver und Browser füge am Anfang header( 'Content-type: text/plain; charset=utf-8' ); hinzu. Dann speicher es aber auch in der Kodierung "UTF-8 ohne BOM".

          Oder verwende http://sandbox.onlinephpfunctions.com/ oder ähnliche Anbieter.

          Bis demnächst
          Matthias

          --
          Du kannst das Projekt SELFHTML unterstützen,
          indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
          1. Oder verwende http://sandbox.onlinephpfunctions.com/ oder ähnliche Anbieter.

            Das ist ganz schön umständlich… Ich bevorzuge, wegen der Ansicht auf einem Beamer, der Werbefreoheit und der Unabhängigkeit vom Internet, das geniale Programm namens Geany:

        2. Da manche es nicht besonders mögen, wenn ich die Stegreif-Beispiele poste, hier meine Entschuldigung:

          Habe aus dem sehr kleinen, derzeit die Nachrichten dominierenden Grund gerade Entzugerscheinungen weil keine zahlenden Opfer für meine Versuche der Wissensvermittlung.

          Und mir fehlt („Verdammter Mist“), der Beifall.

        3. @@Raketenexemplierer

          	echo "Oha. Das Datum \"$s\" ist möglicherweise richtig und gültig. Ich prüfe mal weiter:" . PHP_EOL;
          

          Das Escapen von Anführungszeichen im Text sollte nicht notwendig sein. " ist für Code; im Text sollte das Zeichen nicht vorkommen, sondern „ und “ (im Deutschen).

          Konsequent warst du auch nicht.

          LLAP 🖖

          --
          Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
          1. Das Escapen von Anführungszeichen im Text sollte nicht notwendig sein. " ist für Code; im Text sollte das Zeichen nicht vorkommen, sondern „ und “ (im Deutschen).

            Konsequent warst du auch nicht.

            LLAP 🖖

            Dann eben so:

            <?php
            
            $dateFormat = 'd.m.Y'; #Format des Inputs
            
            $s='2.12.2020'; # Der Input
            
            $sNotBefore = '01.01.2020'; # Nicht vor
            $sNotAfter  = '31.12.2021'; # Nicht nach
            
            #Zerlegen des Datums:
            list( $d, $m, $y ) = explode( '.', $s, 3 ); 
            
            #checkdate prüft formale Richtigkeit:
            if ( checkdate ($m , $d , $y ) ) { 
            	echo "Oha   : Das Datum „${s}“ ist möglicherweise richtig und gültig." 
            		 . PHP_EOL 
            		 . "      ⟹ Ich prüfe mal weiter..." 
            		 . PHP_EOL;
            	
            	#Für die nachfolgenden Vergleiche werden die Strings in ein DateTime-Objekt umgewandelt:
            	$d          = date_create_from_format( $dateFormat, $s );
            	$dNotBefore = date_create_from_format( $dateFormat, $sNotBefore );
            	$dNotAfter  = date_create_from_format( $dateFormat, $sNotAfter );
            	
            	# DieseDateTime-Objekte kann man vergleichen:
            	if ( $d > $dNotAfter ) {
            			echo "Schade. Das Datum „${s}“ sah gültig aus, liegt aber nach dem $sNotAfter."  . PHP_EOL;
            	} elseif ( $d < $dNotBefore ) {
            			echo "Schade: Das Datum „${s}“ sah gültig aus, liegt aber vor dem $sNotBefore."  . PHP_EOL;
            	} else {
            			echo "Gut   : Gültiges Datum „${s}“ zwischen (einschließlich) $sNotBefore und $sNotAfter.". PHP_EOL;
            	}
            } else {
            	echo "Ochnee. Das angebliche Datum „${s}“ ist schlicht ungültig." . PHP_EOL;
            }