web-dev-qa-db-fra.com

Vérifiez si la variable est une date valide avec PHP

Je travaille sur un script qui importera certaines données d'un fichier CSV. Pendant que je fais cela, je veux pouvoir vérifier une variable pour voir si c'est une chaîne de date valide.

J'ai vu plusieurs façons de vérifier si une piqûre est une date, mais la plupart d'entre elles vous obligent à maintenant le format. Je ne connais pas le format de la date.

en ce moment j'utilise strtotime (), mais cela échoue facilement

$field ="May";
if(strtotime($field)){
    echo "This is a date";
}

Dans ce cas, "mai" était le prénom de la personne et non une date.

Quelqu'un peut-il recommander une fonction plus fiable?

Modifier en fonction des questions de certains d'entre vous.

Pour qu'une variable passe comme une "date" dans mon cas, il faudrait qu'elle soit spécifique à un jour/mois/année, donc juste "mai" serait trop vague pour compter.

Sur la base de cela et du bon point de Paul ci-dessous, nous pouvons également tester pour voir si la chaîne contient un nombre, tel que

$field ="May";
if(strtotime($field) && 1 === preg_match('~[0-9]~', $field)){
    echo "This is a date";
}else{
    echo "Nope not a date";
}

Cela semble couvrir mes besoins immédiats, mais peut-on détecter des problèmes ou suggérer des améliorations?

39
Alex

Utilisez date_parse et vérifiez les valeurs du tableau retourné

$date = date_parse("May")

// ["year"] == FALSE
// ["month"] == 5
// ["day"] == FALSE

Vous pouvez également les passer dans checkdate .

$date = date_parse($someString);
if ($date["error_count"] == 0 && checkdate($date["month"], $date["day"], $date["year"]))
    echo "Valid date";
else
    echo "Invalid date";
56
saluce

Je ne pense pas qu'il y ait une réponse tout-en-un à ce problème. Vous pouvez avoir une stratégie différente selon votre cas d'utilisation.

Votre strtotime() est une solution parfaite, mais comme vous le dites, vous pouvez vous retrouver avec un faux positif. Pourquoi? Parce que peut être un mot ou un nom. Cependant, quel est le résultat de strtotime('May')?

echo date(DateTime::ISO8601, strtotime('May'));
2012-05-21T00:00:00+0200

Donc, donner uniquement le mois renverra une date de l'année en cours et le jour en cours commençant à minuit avec le mois donné. Une solution possible serait de vérifier si votre chaîne contient le jour en cours et/ou l'année en cours, de cette façon, vous pouvez vérifier pour vous assurer que votre date est une date complète et valide.

echo date(DateTime::ISO8601, strtotime('May Day')); // (strtotime() returns false)
1970-01-01T01:00:00+0100

echo date(DateTime::ISO8601, strtotime('May 21'));
2012-05-21T00:00:00+0200

Une simple strpos() ou même une expression régulière devrait faire l'affaire.

Cependant c'est un peu étrange et ne doit être utilisé que si vous n'avez pas d'autre moyen de le faire.

Je crois qu'une meilleure solution serait de définir un ensemble de format valide et d'interpoler le résultat pour vous assurer que la date est valide.

$validDateFormatPatterns = array(
 '[0-9]{1,2}-[0-9]{1,2}-[0-9]{4}', // 21-05-2012, obviously this pattern is simple and would accept 05-21-2012,
 'the [0-9]{1,2}(th|st|nd|rd) (January|February|...|May|...|December) [0,9]{4}', // The 21st May 2012
);

Vous devriez essayer de couvrir la plupart des cas et je suis sûr que vous pourrez trouver des expressions rationnelles qui vérifient le format de date le plus récent.

Dans tous les cas, vous devrez peut-être adapter votre fonction de temps en temps car il n'y a pas de moyen facile de la rendre pare-balles.

5
Boris Guéry

Je sais que cela a été demandé il y a longtemps, mais en cherchant cela et en essayant d'éviter les regex, j'ai trouvé ceci:

function checkInputIsDate($date) {
    return (bool)strpbrk($date,1234567890) && strtotime($date);
}

Cela fonctionne car il supprime les problèmes publiés ci-dessus où seul un mois est passé dans strtotime en s'assurant qu'il y a des nombres dans la chaîne avec strpbrk ainsi qu'en vérifiant strtotime affiche une date.

Et appris une fonction que je ne connaissais pas.

J'espère que cela aide quelqu'un.

0
Bryan