J'essaie de vérifier que les dates saisies par les utilisateurs finaux sont dans AAAA-MM-JJ. Regex n'a jamais été mon point fort, je reçois toujours une valeur de retour fausse pour le paramètre preg_match () que j'ai configuré.
Donc, je suppose que j'ai gâché la regex, détaillée ci-dessous.
$date="2012-09-12";
if (preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$date))
{
return true;
}else{
return false;
}
Des pensées?
Essaye ça.
$date="2012-09-12";
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) {
return true;
} else {
return false;
}
Il est probablement préférable d'utiliser un autre mécanisme pour cela.
La solution moderne, avec DateTime
:
$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());
Ceci valide également la saisie: $dt !== false
garantit que la date peut être analysée avec le format spécifié et l’astuce array_sum
est une manière fastidieuse de s’assurer que PHP n’a pas effectué le "décalage de mois" (par exemple, considérons que le 32 janvier est le 1er février ). Voir DateTime::getLastErrors()
pour plus d'informations.
Solution old-school avec explode
et checkdate
:
list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
return ctype_digit("$y$m$d") && checkdate($m, $d, $y);
Ceci valide que la saisie est également une date valide. Vous pouvez le faire avec une expression régulière bien sûr, mais cela va être plus compliqué - et le 29 février ne peut pas être validé avec une expression régulière.
L'inconvénient de cette approche est que vous devez faire très attention à rejeter toutes les "mauvaises" entrées possibles sans émettre d'avis, quelles que soient les circonstances. Voici comment:
explode
est limité pour renvoyer 3 jetons (de sorte que si l'entrée est "1-2-3-4", $d
deviendra "3-4")ctype_digit
est utilisé pour s'assurer que l'entrée ne contient aucun caractère non numérique (à l'exception des tirets)array_pad
est utilisé (avec une valeur par défaut provoquant l'échec de checkdate
) pour s'assurer que suffisamment d'éléments sont retournés pour que, si l'entrée est "1-2", list()
n'émette pas d'avisCritères:
Chaque année divisible par 4 est une année bissextile, sauf si elle est divisible par 100 sauf si elle est divisible par 400. Ainsi:
2004 - leap year - divisible by 4
1900 - not a leap year - divisible by 4, but also divisible by 100
2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400
Février a 29 jours dans une année bissextile et 28 quand ce n'est pas une année bissextile
30 jours en avril, juin, septembre et novembre
31 jours en janvier, mars, mai, juillet, août, octobre et décembre
Test:
Les dates suivantes doivent toutes être validées:
1976-02-29
2000-02-29
2004-02-29
1999-01-31
Les dates suivantes doivent toutes échouer la validation:
2015-02-29
2015-04-31
1900-02-29
1999-01-32
2015-02-00
Intervalle:
Nous allons tester les dates du 1er janvier 1000 au 31 décembre 2999. Techniquement, le calendrier grégorien actuellement utilisé n'a été utilisé qu'en 1753 pour l'Empire britannique et à diverses années dans les années 1600 pour les pays d'Europe, mais je ne va pas se soucier de ça.
Regex à tester pour une année bissextile:
Les années divisibles par 400:
1200|1600|2000|2400|2800
can be shortened to:
(1[26]|2[048])00
if you wanted all years from 1AD to 9999 then this would do it:
(0[48]|[13579][26]|[2468][048])00
if you're happy with accepting 0000 as a valid year then it can be shortened:
([13579][26]|[02468][048])00
Les années divisibles par 4:
[12]\d([02468][048]|[13579][26])
Les années divisibles par 100:
[12]\d00
Non divisible par 100:
[12]\d([1-9]\d|\d[1-9])
Les années divisibles par 100 mais pas par 400:
((1[1345789])|(2[1235679]))00
Divisible par 4 mais pas par 100:
[12]\d([2468][048]|[13579][26]|0[48])
Les années bissextiles:
divisible by 400 or (divisible by 4 and not divisible by 100)
((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48])
Non divisible par 4:
[12]\d([02468][1235679]|[13579][01345789])
Pas une année bissextile:
Not divisible by 4 OR is divisible by 100 but not by 400
([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)
Valable mois et jour sauf février (MM-JJ):
((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30))
shortened to:
((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30))
Février avec 28 jours:
02-(0[1-9]|1\d|2[0-8])
Février avec 29 jours:
02-(0[1-9]|[12]\d)
Date valide:
(leap year followed by (valid month-day-excluding-february OR 29-day-february))
OR
(non leap year followed by (valid month-day-excluding-february OR 28-day-february))
((((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]))))
Vous avez donc ici une regex pour les dates comprises entre le 1er janvier 1000 et le 31 décembre 2999 au format AAAA-MM-JJ.
Je suppose que cela peut être raccourci un peu, mais je laisserai cela à quelqu'un d'autre.
Cela correspondra à toutes les dates valides. Si vous voulez qu'il ne soit valide que s'il ne contient qu'une date et rien d'autre, placez-le dans ^( )$
comme suit:
^(((((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])))))$
Si vous le souhaitez pour une entrée de date facultative (c’est-à-dire qu’elle peut être vide ou valide), ajoutez ^$|
au début, comme suit:
^$|^(((((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])))))$
Vous pouvez le faire de cette façon:
if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) {
echo 'true';
} else {
echo 'false';
}
mais vous feriez mieux d'utiliser celui-ci:
$date = DateTime::createFromFormat('Y-m-d', $date);
if ($date) {
echo $date -> format('Y-m-d');
}
dans ce cas, vous obtiendrez un objet plus facile à utiliser que de simples chaînes.
Vous pouvez utiliser un preg_match avec une fonction php checkdate
$date = "2012-10-05";
$split = array();
if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split))
{
return checkdate($split[2], $split[3], $split[1]);
}
return false;
Je sais que c'est une vieille question. Mais je pense avoir une bonne solution.
$date = "2016-02-21";
$format = "Y-m-d";
if(date($format, strtotime($date)) == date($date)) {
echo "true";
} else {
echo "false";
}
Tu peux l'essayer. Si vous modifiez la date en 21.02.2016, l'écho est faux. Et si vous changez le format par la suite à d.m.Y, l'écho est vrai.
Avec ce code simple, vous devriez pouvoir vérifier quel format de date est utilisé sans le vérifier par la regex.
Peut-être qu'une personne le testera dans tous les cas. Mais je pense que mon idée est généralement valable. Pour moi, cela semble logique.
preg_match nécessite un/ou un autre caractère comme séparateur.
preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date)
vous devriez également vérifier la validité de cette date pour ne pas vous retrouver avec quelque chose comme 9999-19-38
bool checkdate ( int $month , int $day , int $year )
vous pouvez utiliser
function validateDate($date, $format = 'Y-m-d H:i:s')
{
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
$date="2012-09-12";
echo validateDate($date, 'Y-m-d'); // true or false
Vérifier et valider la date YYYY-MM-DD
en une seule ligne
function isValidDate($date) {
return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
: false;
}
La sortie sera:
var_dump(isValidDate("2018-01-01")); // bool(true)
var_dump(isValidDate("2018-1-1")); // bool(true)
var_dump(isValidDate("2018-02-28")); // bool(true)
var_dump(isValidDate("2018-02-30")); // bool(false)
Le jour et le mois sans zéro sont autorisés. Si vous ne voulez pas autoriser cela, l'expression rationnelle devrait être:
"/^(\d{4})-(\d{2})-(\d{2})$/"
Cela devrait vous dire si le format est valide et si la date de saisie est valide.
$datein = '2012-11-0';
if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){
echo 'good';
}else{
echo 'no good';
}
Si cela peut vous aider, voici une regex pour le format j-n-Y (l'année doit être supérieure à 2018):
if (preg_match('/^([1-9]|[1-2][0-9]|[3][0-1])\-([1-9]|[1][0-2])\-(?:20)([1][8-9]|[2-9][0-9])$/', $date)) {
// Do stuff
}
Vous pouvez aussi le faire comme ceci:
if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {
// date is correctly formatted and valid, execute some code
}
Cela vérifiera non seulement le format, mais aussi la validité de la date, puisque DateTime
ne créera que des dates valides et que cela doit correspondre à la saisie.
Si vous souhaitez faire correspondre ce type de date, utilisez:
preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)
Pour travailler avec des dates en php, vous devez suivre le standard php afin que la regex donnée assure que vous avez une date valide pouvant fonctionner avec PHP.
preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)
Format 1: $ format1 = "2012-12-31";
Format 2: $ format2 = "31-12-2012";
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$format1)) {
return true;
} else {
return false;
}
if (preg_match("/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/",$format2)) {
return true;
} else {
return false;
}
À partir de Laravel 5.7 et format de date c'est-à-dire: 31/12/2019
function checkDateFormat(string $date): bool
{
return preg_match("/^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/[0-9]{4}$/", $date);
}
Tout dépend de la sévérité à laquelle vous souhaitez que cette fonction soit appliquée. Par exemple, si vous ne souhaitez pas autoriser les mois au-dessus de 12 et les jours au-dessus de 31 (cela dépend du mois, cela nécessiterait d'écrire une logique de date), cela pourrait devenir assez compliqué:
function checkDate($date)
{
$regex = '/^' .
'(' .
// Allows years 0000-9999
'(?:[0-9]{4})' .
'\-' .
// Allows 01-12
'(?:' .
'(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
'(?:11)|(?:12)' .
')' .
'\-' .
// Allows 01-31
'(?:' .
'(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' .
'(?:11)|(?:12)|(?:13)|(?:14)|(?:15)|(?:16)|(?:17)|(?:18)|(?:19)|(?:20)|' .
'(?:21)|(?:22)|(?:23)|(?:24)|(?:25)|(?:26)|(?:27)|(?:28)|(?:29)|(?:30)|' .
'(?:31)' .
')' .
'$/';
if ( preg_match($regex, $date) ) {
return true;
}
return false;
}
$result = checkDate('2012-09-12');
Personnellement, je vais juste pour: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/
[Si vous utilisez Symfony 4.1.2, essayez ceci] [1]
$validDate = explode("-",$request->get('date'));
if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
$date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
}else{
return $this->redirectToRoute('YOUR_ROUTE');
}
Cette méthode peut être utile pour valider la date en PHP. La méthode actuelle est pour le format mm/jj/aaaa. Vous devez mettre à jour la séquence de paramètres dans checkdate selon votre format et votre délimiteur dans exploser .
function isValidDate($dt)
{
$dtArr = explode('/', $dt);
if (!empty($dtArr[0]) && !empty($dtArr[1]) && !empty($dtArr[2])) {
return checkdate((int) $dtArr[0], (int) $dtArr[1], (int) $dtArr[2]);
} else {
return false;
}
}