Kasandra: Datum Überprüfen auf ECHTHEIT

Ich möchte ein Datum auf Korrektheit überprüfen, mit diesem Code geht es:

list ($y, $m, $d) = explode ( '-',2011-1-2);  
  
  if ( ! checkdate ( $m, $d, $y ) )  
  {  
    print ( 'Datum ist ungültig!' );  
  }  
  else  
  {  
    print ( 'Datum ist gültig!' );  
  }

Doch wenn das Datum in einem falschen Format kommt, Beispiel: 2011c1-2  statt  2011-1-2
Bekomme ich folgende Fehlermeldung „Notice: Undefined offset“ bei der ersten Zeile, wie kann ich diese Fehlermeldung abfangen, bzw. korrekt verfahren…
Weiter kommt die Korrekte Meldung „Datum ist ungültig!“

Danke

Kasi

  1. Doch wenn das Datum in einem falschen Format kommt, Beispiel: 2011c1-2  statt  2011-1-2
    Bekomme ich folgende Fehlermeldung „Notice: Undefined offset“ bei der ersten Zeile, wie kann ich diese Fehlermeldung abfangen, bzw. korrekt verfahren…

    Stichwort Regular Expressions

    1. @@Georg:

      nuqneH

      Stichwort Regular Expressions

      Ähm ja, das geht sogar. Und nein, das sollte man auf keinen Fall tun.

      Qapla'

      --
      Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
      (Mark Twain)
      1. Hi!

        Stichwort Regular Expressions
        Ähm ja, das geht sogar. Und nein, das sollte man auf keinen Fall tun.

        Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden und diese dann mit checkdate() prüfen.

        Lo!

        1. Ähm ja, das geht sogar. Und nein, das sollte man auf keinen Fall tun.

          Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden und diese dann mit checkdate() prüfen.

          Und nach welchem Muster soll der die Bestandteile finden? Das wird dann schon wieder kompliziert.

          Ein einfacher \d{4}-\d{1,2}-\d{1,2} scheitert bereits, weil es ein Datum wie z.B. 2011-13-13 nicht gibt.

          1. @@suit:

            nuqneH

            Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden und diese dann mit checkdate() prüfen.

            Ein einfacher \d{4}-\d{1,2}-\d{1,2} scheitert bereits, weil es ein Datum wie z.B. 2011-13-13 nicht gibt.

            „[…] und diese [Bestandteile] dann mit checkdate() prüfen.“

            Qapla'

            --
            Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
            (Mark Twain)
            1. @@suit:

              nuqneH

              Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden und diese dann mit checkdate() prüfen.

              Ein einfacher \d{4}-\d{1,2}-\d{1,2} scheitert bereits, weil es ein Datum wie z.B. 2011-13-13 nicht gibt.

              „[…] und diese [Bestandteile] dann mit checkdate() prüfen.“

              Ja, aber damit kommt eben Mist zustande wenn dann ein 2001-0101 daherkommt - was bei der dafür gedachten Funktion schon abgefangen wird und einwandfrei hinhaut:

              <?php  
              	$foo = array(  
              		'2011-01-02',  
              		'2011-1-2',  
              		'2011c1-2'  
              	);  
                
              	function bar($str) {  
              		if(!$out = strptime ($str , '%Y-%m-%d')) {  
              			echo "$str: fail\n";  
              		} else {  
              			echo "$str: \n";  
              			print_r($out);  
              			  
              		}  
              	}  
                
              	echo '<pre>';  
              	bar($foo[0]);  
              	bar($foo[1]);  
              	bar($foo[2]);  
              ?>
              
              1. Hi!

                Ein einfacher \d{4}-\d{1,2}-\d{1,2} scheitert bereits, weil es ein Datum wie z.B. 2011-13-13 nicht gibt.
                „[…] und diese [Bestandteile] dann mit checkdate() prüfen.“
                Ja, aber damit kommt eben Mist zustande wenn dann ein 2001-0101 daherkommt - was bei der dafür gedachten Funktion schon abgefangen wird und einwandfrei hinhaut:

                Jetzt wechselst du aber schnell das Thema. Geht es dir nun um eine Plausibiltätsprüfung der Bestandteile? Da kommst du mit strptime() allein auch nicht weiter. Oder geht es dir um das Extrahieren der Bestandteile bei falscher/unvorhergesehener Schreibweise? Man muss da auch einfach mal aufgeben können. Wenn der Anwender Mist eingibt, muss er sich nicht wundern, wenn der nicht doch noch irgendwie interpretiert sondern abgelehnt wird. Bei blöden Schreibweisen scheitern alle drei bisher genannten Lösungen (explode(), strptime(), RegExp) - die einen früher, die anderen später.

                Lo!

                1. Jetzt wechselst du aber schnell das Thema.

                  Nein :)

                  Geht es dir nun um eine Plausibiltätsprüfung der Bestandteile?

                  Nein, dafür verwendet der OP ja checkdate() - wir reden hier aber immer noch um den Teil "String in Datum überführen".

                  Bei blöden Schreibweisen scheitern alle drei bisher genannten Lösungen (explode(), strptime(), RegExp) - die einen früher, die anderen später.

                  Ja, genau aus dem Grund schlug ich vor, dass man einen Datepicker anbietet (HTML5 kann das ja schon nativ) um eine Fehleingabe des Benutzers zu minimieren.

                  Und genau das Datumsformat welches der Datepicker liefert, zerlegt man PHP-Seitig dann nach demselben Muster mit strptime() - das liefert schon eine gewisse Fehlerkorrekturroutine mit, falls es jemand handisch eingibt und zumindest versucht sich daran zu halten. Wenn jemand völlig Blödsinn eingibt, hilft die beste Routine ohnehin nichts.

        2. @@dedlfix:

          nuqneH

          Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden

          Man könnte. Sollte man?

          Qapla'

          --
          Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
          (Mark Twain)
          1. Hi!

            Nunja, man kann ja einen Regulären Ausdruck für die Findung der Bestandteile verwenden
            Man könnte. Sollte man?

            Ja, weil das Auseinandernehmen mit Stringfunktionen aufwendiger ist, wenn man sich nicht auf ein einziges Format (genauer gesagt: Trennzeichen zwischen den Bestandteilen) beschränken will.

            Eingaben nach dem Format t.m.j kann man mit explode() trennen lassen, sollte dann aber die Bestandteile in einem Array fangen und dieses auf die Länge 3 testen. Die Verwendung von strptime() ist nicht wirklich besser, weil auch damit ein checkdate() notwendig ist und das Trennzeichen fest vorgegeben ist.

            Die Beschränkung auf den Punkt bringt aber eine eingeschränkte Benutzerfreundlichkeit mit. Wenn man <del>Kein Martin</del><ins>Schnelltipper auf dem Ziffernblock</ins> ist, hemmt es die Geschwindigkeit, wenn man für den Punkt rüber zum Haupttastaturfeld wechseln muss und wieder zurück. Auch das Hinzunehmen der zweiten Hand ist keine ideale Lösung. Besser wäre es, wenn man irgendein Trennzeichen verwenden kann. Und dafür macht sich ein Regexp besser als ein explode() oder strptime() oder selbst geschriebener Parser mit einfachen Stringfunktionen. Die Reihenfolge der Bestandteile muss allerdings weiterhin vorgegeben sein, um Aufwand und Fehlerquote beim Erraten nicht zu hoch werden zu lassen. (Vorstehende Ausführungen beziehen sich auf eine einzelne Anordnungsweise. Für Anwendungen, die mehrere Anordnungen unterstützen sollen, muss man sich noch entsprechenden Aufwand fürs Umsortieren einbauen, aber das kann einem auch keine einzelne RegExp-Lösung abnehmen.)

            Lo!

            1. @@dedlfix:

              nuqneH

              Ja, weil das Auseinandernehmen mit Stringfunktionen aufwendiger ist, wenn man sich nicht auf ein einziges Format (genauer gesagt: Trennzeichen zwischen den Bestandteilen) beschränken will.

              OK. Hm, dann kann man ja das Datum auch japanisch eingeben: 2011年6月9日 ;-)

              Die Beschränkung auf den Punkt bringt aber eine eingeschränkte Benutzerfreundlichkeit mit. Wenn man <del>Kein Martin</del><ins>Schnelltipper auf dem Ziffernblock</ins> ist […]

              *g*

              […] hemmt es die Geschwindigkeit, wenn man für den Punkt rüber zum Haupttastaturfeld wechseln muss und wieder zurück.

              Ich weiß nicht, was du für einen Ziffernblock hast, aber ich habe einen mit [-]. ;-)

              Qapla'

              --
              Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
              (Mark Twain)
              1. @@Gunnar Bittersmann:

                nuqneH

                OK. Hm, dann kann man ja das Datum auch japanisch eingeben: 2011年6月9日 ;-)

                Äh, die Rechnung ohne den Wirt (PHP) gemacht?

                Man muss natürlich Stringfunktionen einsetzten, die diesen Namen verdienen; nicht den nutzlosen Krempel, der auch unter Stringfunktionen aufgelistet ist.

                Qapla'

                --
                Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
                (Mark Twain)
              2. Hi!

                Ja, weil das Auseinandernehmen mit Stringfunktionen aufwendiger ist, wenn man sich nicht auf ein einziges Format (genauer gesagt: Trennzeichen zwischen den Bestandteilen) beschränken will.
                OK. Hm, dann kann man ja das Datum auch japanisch eingeben: 2011年6月9日 ;-)

                Kannst man. Die Frage ist allerdings, was es für Vorteile bringt. Zumindest kann man solche Angaben anderswo kopieren und ins das Feld einfügen. Zu Fuß tippen ist ja wegen des notwendigen IME noch aufwendiger als ein Zeichen der Haupttastatur aufzusuchen.

                Ich weiß nicht, was du für einen Ziffernblock hast, aber ich habe einen mit [-]. ;-)

                Ich habe nicht immer meine persönlichen Tastaturtreiber dabei.

                Lo!

  2. Moin

    Doch wenn das Datum in einem falschen Format kommt, Beispiel: 2011c1-2  statt  2011-1-2
    Bekomme ich folgende Fehlermeldung „Notice: Undefined offset“ bei der ersten Zeile, wie kann ich diese Fehlermeldung abfangen, bzw. korrekt verfahren…

    Is ja klar. list() erwartet 3 Werte. Du lieferst aber nur 2.

    Prüf doch den Unix Timestamp ob er 0 oder gültig ist. Dazu wandelst du das übergebene Datum 1:1 mittels strtotime() in einen solchen um.

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
    ### Henry L. Mencken ###
    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
    ## Viktor Frankl ###
    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
  3. strptime() ist geeigneter als dein selbst gezimmertes explode.

    Allgemein um Fehler zu vermeiden wäre es noch schlauer gleich bei der Eingabe zu verhindern, dass sowas daherkommt.

    z.B. mittels einem Datumseingabefeld oder einem JavaScript-Datepicker.

    Was ist das übrigens für ein Datumsformat?

    2011-1-2 ist nach ISO 8601 übrigens nicht der 2. Jänner 2011 sondern ungültig.

  4. @@Kasandra:

    nuqneH

    […] mit diesem Code geht es:
    list ($y, $m, $d) = explode ( '-',2011-1-2);

    ▲        ▲
    Kann ich nicht glauben.

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)