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
?
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!
Déterminer si une chaîne est une date
function checkIsAValidDate($myDateString){
return (bool)strtotime($myDateString);
}
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
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');
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';
}
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;
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
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!
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.
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.
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.
/**** 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);
}
}
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";
}
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;
}