Déterminer correctement si la chaîne de date est une date valide dans ce format

Je reçois une chaîne de date d'une API, et elle est formatée comme yyyy-mm-dd.

J'utilise actuellement une expression rationnelle pour valider le format de chaîne, qui fonctionne bien, mais je peux voir certains cas où il pourrait être un format correct selon la chaîne mais en fait une date invalide. c'est à dire 2013-13-01, par exemple.

Est-il un meilleur moyen en PHP de prendre une chaîne telle que 2013-13-01 et dire si c'est une date valide ou pas pour le format yyyy-mm-dd?

126
demandé sur Amal Murali 2013-10-09 15:58:03

14 réponses

Vous pouvez utiliser DateTime classe et à cette fin:

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;
}

[fonctions prises à partir de cette réponse. Également sur php.net. Écrit à l'origine par Glavić.]


Cas de Test:

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

Démo!

327
répondu Amal Murali 2018-05-19 09:45:27

Déterminer si une chaîne est une date

function checkIsAValidDate($myDateString){
    return (bool)strtotime($myDateString);
}
60
répondu arsh 2014-11-24 20:56:49

Utiliser de manière simple avec la fonction php prédéfinie:

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

Essai

   checkmydate('2015-12-01'); //true
   checkmydate('2015-14-04'); //false
26
répondu vineet 2017-02-06 17:51:32

Déterminer si la chaîne est une date, même si la chaîne est un format non standard

(strtotime n'accepte aucun format personnalisé)

<?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');
14
répondu migli 2017-02-06 17:07:42

Vous pouvez également analyser la date pour la date du mois et l'année, puis vous pouvez utiliser la fonction PHP checkdate() que vous pouvez lire ici: http://php.net/manual/en/function.checkdate.php

Vous pouvez aussi essayer celui-ci:

$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';
    }
9
répondu Suvash sarker 2013-10-09 12:07:51

Cette option est non seulement simple, mais accepte également presque n'importe quel format, bien qu'avec des formats non standard, elle puisse être boguée.

$timestamp = strtotime($date);
return $timestamp ? $date : null;
9
répondu galki 2015-06-30 08:47:30

Accordling avec la réponse de cl-sah, mais cela sonne mieux, plus court...

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

Essai

checkmydate('2015-12-01');//true
checkmydate('2015-14-04');//false
7
répondu Stefano 2016-02-29 19:25:13

J'ai cette chose que, même avec PHP, j'aime trouver des solutions fonctionnelles . Ainsi, par exemple, la réponse donnée par @migli est vraiment bon, très souple et élégant.

Mais il y a un problème: que faire si vous avez besoin de valider beaucoup de chaînes DateTime avec le même format? Vous devrez répéter le format partout, ce qui va à l'encontre du principe DRY. Nous pourrions mettre le format dans une constante, mais encore, nous devrions passer la constante comme un argument à chaque appel de fonction.

Mais ne craignez plus! Nous pouvons utiliser nourrissage à notre secours! PHP ne rend pas cette tâche agréable, mais il est toujours possible d'implémenter currying avec PHP:

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

Alors, qu'est-ce qu'on vient de faire? Fondamentalement, nous avons enveloppé le corps de la fonction dans un anonyme et retourné une telle fonction à la place. Nous pouvons appeler la fonction de validation comme ceci:

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

Ouais, pas une grande différence... mais le pouvoir réel vient de la fonction partiellement appliquée , rendu possible par currying:

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

Programmation Fonctionnelle FTW!

5
répondu Victor Schröder 2017-02-06 16:32:42

Le moyen le plus simple de vérifier si la date donnée est valide est probablement de la convertir en unixtime en utilisant strtotime, en la formatant au format de la date donnée, puis en la comparant:

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

Bien sûr, vous pouvez utiliser l'expression régulière pour vérifier la validité, mais elle sera limitée au format donné, chaque fois que vous devrez l'éditer pour satisfaire d'autres formats,et ce sera plus que nécessaire. Fonctions intégrées est le meilleur moyen (dans la plupart des cas) pour atteindre les emplois.

2
répondu Nurlan Alekberov 2017-07-03 19:16:12

Et celui-ci?

Nous utilisons simplement un bloc try-catch.

$dateTime = 'an invalid datetime';

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

Cette approche n'est pas limitée à un seul format de date/heure, et vous n'avez pas besoin de définir une fonction.

2
répondu Julian 2017-09-07 10:53:53

Solution Regex Testée:

    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;
    }

Cela renverra null si la date n'est pas valide ou n'est pas au format AAAA-mm-JJ, sinon elle renverra la date.

1
répondu Akumaburn 2017-03-14 20:17:04
    /**** 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);
        }

    }
0
répondu Subham Ghorui 2017-09-01 14:18:09

Essayez ceci:

$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";
}
0
répondu Youssef Gamra 2017-11-10 19:14:52

Selon la réponse D'Amal Murali,

$d = DateTime::createFromFormat('Y-m-d g:i:s', $date);
$d2 = DateTime::createFromFormat('Y-m-d H:i:s', $date);

if(($d && $d->format('Y-m-d g:i:s') == $date) || ($d2 && $d2->format('Y-m-d H:i:s') == $date))
            {
                return true;
            }
            else 
            {
                return false;
            }
0
répondu Shiva Manhar 2017-12-06 07:28:50