245 votes

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 suit yyyy-mm-dd .

J'utilise actuellement une expression rationnelle pour valider le format de la chaîne, ce qui fonctionne bien, mais je vois certains cas où le format pourrait être correct selon la chaîne, mais où la date serait en fait invalide. 2013-13-01 par exemple.

Existe-t-il un meilleur moyen en PHP de prendre une chaîne de caractères telle que 2013-13-01 et dire s'il s'agit d'une date valide ou non pour le format yyyy-mm-dd ?

13voto

La façon la plus simple de vérifier si une date donnée est valide est de la convertir en unixtime à l'aide de la fonction strtotime en le formatant au format de la date donnée, puis en le comparant :

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

Bien sûr, vous pouvez utiliser une expression régulière pour vérifier la validité, mais elle sera limitée à un format donné, vous devrez à chaque fois la modifier pour satisfaire à un autre format, et ce sera également plus que nécessaire. Les fonctions intégrées sont le meilleur moyen (dans la plupart des cas) de réaliser ces tâches.

12voto

Suvash sarker Points 3072

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

Vous pouvez également 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';
    }

12voto

Barvajz Points 51

Je crains que la solution la plus votée ( https://stackoverflow.com/a/19271434/3283279 ) ne fonctionne pas correctement. Le quatrième cas de test (var_dump(validateDate('2012-2-25')) ; // false) est erroné. La date est correcte, car elle correspond au format - la balise m permet un mois avec ou sans zéro initial (voir : http://php.net/manual/en/datetime.createfromformat.php ). Par conséquent, une date 2012-2-25 est au format Y-m-d et le cas de test doit être vrai et non faux.

Je pense que la meilleure solution consiste à tester l'erreur possible de la manière suivante :

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

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

8voto

Victor Schröder Points 548

Même avec PHP, j'aime bien trouver des solutions à mes problèmes de santé. fonctionnel solutions. Ainsi, par exemple, la réponse donnée par @migli est vraiment bonne, très flexible et élégante.

Mais il y a un problème : que se passe-t-il si vous devez valider un grand nombre de chaînes DateTime ayant le même format ? Vous devriez répéter le format partout, ce qui va à l'encontre de la norme SEC principe. Nous pourrions placer le format dans une constante, mais nous devrions quand même passer la constante comme argument à chaque appel de fonction.

Mais ne craignez plus rien ! Nous pouvons utiliser curry à notre secours ! PHP ne rend pas cette tâche agréable, mais il est tout de même possible d'implémenter le curry 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 ? Nous avons enveloppé le corps de la fonction dans un anonyme et renvoyé cette fonction à la place. Nous pouvons appeler la fonction de validation comme suit :

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

Oui, il n'y a pas de grande différence... mais la vraie puissance vient de la fonction partiellement appliquée Le curry permet d'obtenir des résultats très satisfaisants :

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

7voto

sdotbertoli Points 101

En accord avec la réponse de cl-sah, mais celle-ci semble meilleure, plus courte...

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

Test

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X