Stellen Sie richtig fest, ob die Datumszeichenfolge ein gültiges Datum in diesem Format ist


183

Ich erhalte eine Datumszeichenfolge von einer API, die wie folgt formatiert ist yyyy-mm-dd.

Ich verwende derzeit einen regulären Ausdruck, um das Zeichenfolgenformat zu überprüfen. Dies funktioniert einwandfrei. In einigen Fällen kann es sich jedoch um ein korrektes Format gemäß der Zeichenfolge handeln, es handelt sich jedoch um ein ungültiges Datum. dh 2013-13-01zum Beispiel.

Gibt es in PHP eine bessere Möglichkeit, eine Zeichenfolge wie z. B. 2013-13-01festzustellen, ob es sich um ein gültiges Datum für das Format handelt oder nicht yyyy-mm-dd?


Mögliches Duplikat der PHP-
Datumsvalidierung

1
Die Antwort hier ist sowieso viel besser.
Sebastien

Antworten:


450

Sie können DateTimeclass für diesen Zweck verwenden:

function validateDate($date, $format = 'Y-m-d')
{
    $d = DateTime::createFromFormat($format, $date);
    // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
    return $d && $d->format($format) === $date;
}

[ Funktion aus dieser Antwort entnommen . Auch auf php.net . Ursprünglich geschrieben von Glavić . ]]


Testfälle:

var_dump(validateDate('2013-13-01'));  // false
var_dump(validateDate('20132-13-01')); // false
var_dump(validateDate('2013-11-32'));  // false
var_dump(validateDate('2012-2-25'));   // false
var_dump(validateDate('2013-12-01'));  // true
var_dump(validateDate('1970-12-01'));  // true
var_dump(validateDate('2012-02-29'));  // true
var_dump(validateDate('2012', 'Y'));   // true
var_dump(validateDate('12012', 'Y'));  // false

Demo!


14
Wenn Sie PHP 5.2.x verwenden, sollten strtotimeSie den Unix-Zeitstempel und dann date('Y-m-d', $t)das Zeichenfolgendatum abrufen . Dann vergleichen Sie sie genau wie diese Antwort.
Pedromanoel

2
@pedromanoel: Für Standard-Datetime-Eingaben, die Sie verwenden können strtotime, benötigen Sie für nicht standardmäßige Formate, strtotimedie nicht erkannt werden, eine andere Lösung. Und für PHP Version 5.2 wurde die Unterstützung im Januar 2011 eingestellt, für 5.3 wurde die Unterstützung im August 2014 eingestellt.
Glavić

2
Betrachten Sie dieses Datumvar_dump( validateDate('2012-2-9'));
regiert

4
Die Funktion funktioniert korrekt. Es wurde false zurückgegeben, da das von Ihnen angegebene Format falsch war. Wenn Sie Tag und Monat ohne führende Nullen verwenden möchten, sollte das Format 'Y-n-j'@reignsly lauten.
Amal Murali

1
@ AntonyD'Andrea: Nein, ohne diesen Teil geht es nicht. Weil $des nicht falsch sein wird, geben Sie ihm das Datum an, an dem Teile wie der 13. Monat (2013-13-01) übergelaufen sind. Aber es kommt wirklich darauf an, was Sie wollen. Wenn Sie zum Beispiel validateDate('2015-55-66')gültig sein müssen, müssen Sie nur prüfen, ob $des sich um ein Objekt handelt oder nicht.
Glavić

80

Bestimmen Sie, ob eine Zeichenfolge ein Datum ist

function checkIsAValidDate($myDateString){
    return (bool)strtotime($myDateString);
}

2
Dies validiert nicht nur eine ganze Reihe gültiger Datumsformate yyyy-mm-dd.
EWit

10
@MichelAyres Dies liegt daran, dass PHP 2015-02-30als gültiges Datum angesehen wird, da PHP auf den nächsten Monat übertragen wird, wenn der angegebene Tag größer ist als die Anzahl der Tage im angegebenen Monat (oder negativ). Da das Datum garantiert das Format yyyy-mm-ddhat, kann dies durch Ändern der Rückgabe in behoben werden return (bool)strtotime($myDateString) && date("Y-m-d", strtotime($myDateString)) == $myDateString;.
Elitechief21

2
Warum kommt (bool)strtotime('s')es als wahr heraus?
Peon

dies gibt auch 1 checkIsAValidDate ("F") zurück;
Vaibhav Bhanushali

Wir können $myDateString = str_replace("/", '-', $myDateString);vor der Rückgabe verwenden, wenn die Datumszeichenfolge Schrägstriche (/) enthält, wie: - TT / MM / JJJJ
Yashrajsinh Jadeja

37

Verwenden Sie auf einfache Weise mit PHP vorgefertigten Funktion:

function checkmydate($date) {
  $tempDate = explode('-', $date);
  // checkdate(month, day, year)
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}

Prüfung

   checkmydate('2015-12-01'); //true
   checkmydate('2015-14-04'); //false

1
Schöne unkomplizierte Lösung, hat beim ersten Mal funktioniert, danke :)
David Bell

Wenn Sie einen Test verwenden , geben Sie den Test selbst ifeinfach in trueoder falsezurück.
Victor Schröder

4
Dies setzt voraus, dass das Array $ tempDate mindestens 3 Elemente enthält.
Person27

2
@ Person27:return sizeof($tmpDate) == 3 && checkdate($tmpDate[1]...
Neurino

@vineet - das schlägt fehl. Wenn das Jahr ist 2,20 , 202, 2020oder auch wenn das Jahr 20201- gibt es jedes Mal wahr.
Rolinger

16

Stellen Sie fest, ob die Zeichenfolge ein Datum ist, auch wenn die Zeichenfolge kein Standardformat ist

(strtotime akzeptiert kein benutzerdefiniertes Format)

<?php
function validateDateTime($dateStr, $format)
{
    date_default_timezone_set('UTC');
    $date = DateTime::createFromFormat($format, $dateStr);
    return $date && ($date->format($format) === $dateStr);
}

// These return true
validateDateTime('2001-03-10 17:16:18', 'Y-m-d H:i:s');
validateDateTime('2001-03-10', 'Y-m-d');
validateDateTime('2001', 'Y');
validateDateTime('Mon', 'D');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('March 10, 2001, 5:16 pm', 'F j, Y, g:i a');
validateDateTime('03.10.01', 'm.d.y');
validateDateTime('10, 3, 2001', 'j, n, Y');
validateDateTime('20010310', 'Ymd');
validateDateTime('05-16-18, 10-03-01', 'h-i-s, j-m-y');
validateDateTime('Monday 8th of August 2005 03:12:46 PM', 'l jS \of F Y h:i:s A');
validateDateTime('Wed, 25 Sep 2013 15:28:57', 'D, d M Y H:i:s');
validateDateTime('17:03:18 is the time', 'H:m:s \i\s \t\h\e \t\i\m\e');
validateDateTime('17:16:18', 'H:i:s');

// These return false
validateDateTime('2001-03-10 17:16:18', 'Y-m-D H:i:s');
validateDateTime('2001', 'm');
validateDateTime('Mon', 'D-m-y');
validateDateTime('Mon', 'D-m-y');
validateDateTime('2001-13-04', 'Y-m-d');

Wenn Sie einen Test verwenden, ifgeben Sie ihn einfach in trueoder zurück false, geben Sie den Test selbst zurück.
Victor Schröder

Aber 2018-3-24 gibt false zurück, die Methode empfängt 2018-3-24, wenn das Format angewendet wird, return 2018-03-24; Wie kann ich auf zwei Arten wahr zurückgeben?
Aquiles Perez

12

Diese Option ist nicht nur einfach, sondern akzeptiert auch fast jedes Format, obwohl sie bei nicht standardmäßigen Formaten fehlerhaft sein kann.

$timestamp = strtotime($date);
return $timestamp ? $date : null;

Dies sollte die akzeptierte Antwort gewesen sein! Viel, viel einfacher.
Webmaster G

2
Es ist wichtig zu beachten, dass dies mit einem britischen Format (d / m / Y) nicht funktioniert, da davon ausgegangen wird, dass das amerikanische Format (m / d / Y) konvertiert wird. Es scheint nur zu funktionieren, wenn der Tag niedriger als 12 ist!
Sylvester Saracevas

@ Galki - Ich habe dies getestet und es schlägt bestimmte Werte fehl. Wenn $ date = '202-03-31', wird true zurückgegeben. Aber das ist kein gültiges Datum. Ich habe festgestellt, dass wenn Sie das Jahr in ein ungültiges Jahr ändern, es immer true zurückgibt.
Rolinger

@rolinger seltsam ... vielleicht sieht es 202AD? Welchen Jahreszeitstempel gibt 'strtotime'?
Galki

@galki - nicht sicher, gibt aber 202eine negative Zahl zurück - die den Test noch besteht.
Rolinger

9

Sie können auch das Datum für Monat, Datum und Jahr analysieren und dann die PHP-Funktion verwenden, über checkdate()die Sie hier lesen können: http://php.net/manual/en/function.checkdate.php

Sie können auch dieses ausprobieren:

$date="2013-13-01";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date))
    {
        echo 'Date is valid';
    }else{
        echo 'Date is invalid';
    }

im Februar (wie von Elitechief21 kommentiert) ist die Funktion isValidDate ($ date) {return preg_match ("/ ^ [0-9] {4} - (0 [1-9] | 1 [0-2]) - (0 [1-9] | [1-2] [0-9] | 3 [0-1]) $ / ", $ date) && date (" Ymd ", strtotime ($ date)) == $ date; }
abdulwadood

4
Diese Lösung ist sehr schlecht, da sie die Gültigkeit des Datums in keiner Weise überprüft. Jeder Monat kann 31 Tage haben, einschließlich Februar. Jedes Jahr kann den 29. Februar haben. Die Validierung von Daten mit RegExp würde etwas viel Komplexeres erfordern, mit Rückverweisen und negativen Voraussichten.
Victor Schröder

9

Der einfachste Weg, um zu überprüfen, ob das angegebene Datum gültig ist, besteht wahrscheinlich darin, es in Unixtime zu konvertieren strtotime, es in das Format des angegebenen Datums zu formatieren und es dann zu vergleichen:

function isValidDate($date) { return date('Y-m-d', strtotime($date)) === $date; }

Natürlich können Sie reguläre Ausdrücke verwenden, um die Gültigkeit zu überprüfen, aber sie sind auf das angegebene Format beschränkt, jedes Mal, wenn Sie sie bearbeiten müssen, um andere Formate zu erfüllen, und sie sind mehr als erforderlich. Eingebaute Funktionen sind (in den meisten Fällen) der beste Weg, um Jobs zu erreichen.


1
Ich bin der Meinung, dass diese Antwort von ziemlich geringer Qualität ist, insbesondere wenn man bedenkt, dass es bereits zeitnahe Antworten gibt.
GrumpyCrouton

4
Dies ist die kürzeste Antwort und es funktioniert. Es ist ein bisschen hart zu sagen, dass es von geringer Qualität ist.
Tim Rogers

@ user4600953 - Dies ist die einfachste, die funktioniert. Viele andere sagen, dass sie verwenden sollen checkdate()- aber ich finde, dass das Checkdate fehlschlägt, wenn das Jahr einen beliebigen Wert hat: 2, 20, 202, 2020, 20201- Alle geben true zurück. Ich gehe mit Ihrer Lösung!
Rolinger

7

Entsprechend der Antwort von cl-sah, aber das klingt besser, kürzer ...

function checkmydate($date) {
  $tempDate = explode('-', $date);
  return checkdate($tempDate[1], $tempDate[2], $tempDate[0]);
}

Prüfung

checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false

Sie werden prüfen müssen , wenn count($tempDate) === 3obwohl
VDarricau

@VDarricau nein, tust du nicht, checkdate wird bombardieren, wenn sie fehlen, du könntest isset () für jeden einzelnen schreiben, aber ich würde einfach die Warnungen unterdrücken
Mr Heelis

7

Ich habe dieses Ding, das ich selbst mit PHP gerne funktionsfähig finde Lösungen . So ist zum Beispiel die Antwort von @migli wirklich gut, sehr flexibel und elegant.

Es gibt jedoch ein Problem: Was ist, wenn Sie viele DateTime-Zeichenfolgen mit demselben Format überprüfen müssen? Sie müssten das Format überall wiederholen, was gegen den DRY geht Prinzip . Wir könnten das Format in eine Konstante setzen, müssten aber dennoch die Konstante als Argument an jeden Funktionsaufruf übergeben.

Aber keine Angst mehr! Wir können Currying zu unserer Rettung verwenden! PHP macht diese Aufgabe nicht angenehm, aber es ist immer noch möglich, Currying mit PHP zu implementieren:

<?php
function validateDateTime($format)
{
    return function($dateStr) use ($format) {
        $date = DateTime::createFromFormat($format, $dateStr);
        return $date && $date->format($format) === $dateStr;
    };
}

Also, was haben wir gerade gemacht? Grundsätzlich haben wir den Funktionskörper in eine anonyme Funktion eingeschlossen und stattdessen eine solche Funktion zurückgegeben. Wir können die Validierungsfunktion folgendermaßen aufrufen:

validateDateTime('Y-m-d H:i:s')('2017-02-06 17:07:11'); // true

Ja, kein großer Unterschied ... aber die wahre Kraft kommt von der teilweise angewendeten Funktion , die durch Curry möglich wird:

// Get a partially applied function
$validate = validateDateTime('Y-m-d H:i:s');

// Now you can use it everywhere, without repeating the format!
$validate('2017-02-06 17:09:31'); // true
$validate('1999-03-31 07:07:07'); // true
$validate('13-2-4 3:2:45'); // false

Funktionsprogrammierung FTW!


2
Die beste Antwort durch einen Erdrutsch IMHO (löst das spezifische Problem des OP mit größerer Flexibilität und so ziemlich der gleichen Menge an Code wie die restlichen Antworten)
StubbornShowaGuy

IMHO das ist wirklich hässliche Programmierung, setzen Sie einfach Ihre Werte in ein Array und durchlaufen Sie sie zur Validierung, aber bitte tun Sie dies nicht!
Tim

Ich bin neugierig @Tim, können Sie uns ein Beispiel für Ihre Array / Loop-Validierung geben?
Victor Schröder

5

Ich befürchte, dass die am häufigsten gewählte Lösung ( https://stackoverflow.com/a/19271434/3283279 ) nicht ordnungsgemäß funktioniert. Der vierte Testfall (var_dump (validateDate ('2012-2-25')); // false) ist falsch. Das Datum ist korrekt, da es dem Format entspricht - das m erlaubt einen Monat mit oder ohne führende Null (siehe: http://php.net/manual/en/datetime.createfromformat.php ). Daher hat ein Datum 2012-2-25 das Format Ymd und der Testfall muss wahr und nicht falsch sein.

Ich glaube, dass eine bessere Lösung darin besteht, mögliche Fehler wie folgt zu testen:

function validateDate($date, $format = 'Y-m-d') {
    DateTime::createFromFormat($format, $date);
    $errors = DateTime::getLastErrors();

    return $errors['warning_count'] === 0 && $errors['error_count'] === 0;
}

3

Wie wäre es mit diesem?

Wir verwenden einfach einen Try-Catch-Block.

$dateTime = 'an invalid datetime';

try {
    $dateTimeObject = new DateTime($dateTime);
} catch (Exception $exc) {
    echo 'Do something with an invalid DateTime';
}

Dieser Ansatz ist nicht nur auf ein Datums- / Zeitformat beschränkt, und Sie müssen keine Funktion definieren.


Dies wird nicht funktionieren für Datum / Uhrzeit Wert 0000-00-00 00:00:00
Naseeruddin VN

@NaseeruddinVN '0000-00-00 00:00:00'ist ein gültiger Datum / Uhrzeit-Wert. Es ist nur der erste Wert. Die Datumseigenschaft des datetime-Objekts ist jedoch '-0001-11-30 00:00:00'.
Julian

1

Getestete Regex-Lösung:

    function isValidDate($date)
    {
            if (preg_match("/^(((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8])))))$/", $date)) {
                    return $date;
            }
            return null;
    }

Dies gibt null zurück, wenn das Datum ungültig ist oder nicht das Format JJJJ-MM-TT hat, andernfalls wird das Datum zurückgegeben.



0
/*********************************************************************************
Returns TRUE if the input parameter is a valid date string in "YYYY-MM-DD" format (aka "MySQL date format")
The date separator can be only the '-' character.
*********************************************************************************/
function isMysqlDate($yyyymmdd)
{
    return checkdate(substr($yyyymmdd, 5, 2), substr($yyyymmdd, 8), substr($yyyymmdd, 0, 4)) 
        && (substr($yyyymmdd, 4, 1) === '-') 
        && (substr($yyyymmdd, 7, 1) === '-');
}

-1
    /**** date check is a recursive function. it's need 3 argument 
    MONTH,DAY,YEAR. ******/

    $always_valid_date = $this->date_check($month,$day,$year);

    private function date_check($month,$day,$year){

        /** checkdate() is a php function that check a date is valid 
        or not. if valid date it's return true else false.   **/

        $status = checkdate($month,$day,$year);

        if($status == true){

            $always_valid_date = $year . '-' . $month . '-' . $day;

            return $always_valid_date;

        }else{
            $day = ($day - 1);

            /**recursive call**/

            return $this->date_check($month,$day,$year);
        }

    }

1
Code ohne Erklärung ist nicht sehr nützlich.
Gert Arnold

-2

Probieren Sie es aus:

$date = "2017-10-01";


function date_checker($input,$devider){
  $output = false;

  $input = explode($devider, $input);
  $year = $input[0];
  $month = $input[1];
  $day = $input[2];

  if (is_numeric($year) && is_numeric($month) && is_numeric($day)) {
    if (strlen($year) == 4 && strlen($month) == 2 && strlen($day) == 2) {
      $output = true;
    }
  }
  return $output;
}

if (date_checker($date, '-')) {
  echo "The function is working";
}else {
  echo "The function isNOT working";
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.