Test si une date au format français est valide

Soyez le premier à donner votre avis sur cette source.

Snippet vu 11 037 fois - Téléchargée 17 fois

Contenu du snippet

Bon, c'est un cas extrême d'utilisation d'expression régulière. Plus un cas d'école, assez instructif, que quelque chose que j'utiliserai vraiment.
Je prêche plutôt de scinder une chaîne complexe en parties plus simples et d'utiliser du code pour vérifier les parties (avec ou sans expression régulière !).

Le but ici est de tester si une date du style jj/mm/aaaa est valide. Facile ? Pas si vous voulez rejeter les dates 29/02/2001 ou 31/11/2008... La validité se "limite" de 1600 à 2999.

Pour être honnête, la base a été écrite par un certain dany.lauener(at)b-i.com. Elle faisait 281 caractères de long. Je l'ai améliorée un peu : analysée en code étendu commenté ci-dessous, puis simplifié à 233 caractères, pour la même fonctionnalité.

J'espère qu'elle vous amusera, voire vous apprendra quelques astuces.

Source / Exemple :


L'expression brute :

^((0[1-9]|1\d|2[0-8])/(0\d|1[012])/(1[6-9]|[2-9]\d)\d{2}|(29|30)/(0[13-9]|1[012])/(1[6-9]|[2-9]\d)\d{2}|31/(0[13578]|1[02])/(1[6-9]|[2-9]\d)\d{2}|29/02/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|(16|[2468][048]|[3579][26])00))$

La même, décortiquée (option PCRE_EXTENDED par exemple : espaces non significatifs, le texte après # est du commentaire) :

^(
   # Jours 01 à 28, tous mois, toutes années : prend en compte rapidement les cas les plus courants
   ( # Jours 01 à 28
      0[1-9]
      |
      1\d
      |
      2[0-8]
   )
   /
   ( # Mois (quelconques)
      0\d
      |
      1[012]
   )
   /
   ( # Années (n'importe lesquelles)
      1[6-9] # 1600 à 1999
      |
      [2-9]\d # 2000 à 9999
   )\d{2} # N'importe quelle paire de chiffres

   |

   # Cas des mois avec 30 jours (ou moins)
   ( # 29 ou 30
      29
      |
      30
   )
   /
   ( # Mois avec 30 jours
      0[13-9]
      |
      1[012]
   )
   /
   (1[6-9]|[2-9]\d)\d{2} # Années comme ci-dessus

   |

   # Cas des mois avec 31 jours
   31
   /
   ( # Mois où le 31 est valide
      0[13578]
      |
      1[02]
   )
   /
   (1[6-9]|[2-9]\d)\d{2} # Années comme ci-dessus

   |

   # Cas du 29 février
   29/02/
   ( # Années
      (
         1[6-9] # 1600 à 1999
         |
         [2-9]\d # 2000 à 9999
      )
      ( # Les deux derniers chiffres sont divisibles par 4
         0[48]
         |
         [2468][048]
         |
         [13579][26]
      )
      |
      ( # Années valides finissant par un double zéro
         16
         |
         [2468][048]
         |
         [3579][26]
      )00
   )
)$

Conclusion :


Ça montre bien ce qu'il ne faut pas faire avec les expressions régulières ! En l'occurrence, écrire des expressions illisibles, trop complexes et difficilement maintenables...
D'un autre côté, cela montre aussi qu'avec un peu d'analyse et de structuration, on peut quand même comprendre de telles expressions.

A voir également

Ajouter un commentaire

Commentaires

cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
Ah si, un autre regret : pourquoi obliger la saisie du caractère "0" pour le jour ou le mois ?
Pour rendre la saisie facultative, il suffit de mettre un point d'interrogation juste derrière les zéros concernés.
Ainsi, 1/1/2009 sera reconnu tout comme 01/1/2009, 1/01/2009 ou encore 01/01/2009.
Voici le début de la regex à modifier :
Avant :
^((0[1-9]|1\d|2[0-8])/(0\d|1[012])/
Suggestion :
^((0?[1-9]|1\d|2[0-8])/(0?\d|1[012])/
cs_Delphiprog
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Statut
Modérateur
Dernière intervention
9 janvier 2013
24 -
Très intéressant et fort bien "décortiqué". Je regrette seulement que seul le caractère "/" soit autorisé. Mais c'est un problème simple à résoudre à côté du reste :)
Félicitations : 10/10

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.