Regex date américaine (MM/DD/YYYY)
Le format américain place le mois avant le jour : « 02/29/2024 ». Une regex peut vérifier les jours par mois (30 ou 31 jours, 28 en février) et la règle grégorienne des bissextiles (années divisibles par 4, sauf siècles non divisibles par 400). Les tentatives relues sont moins strictes sur la forme ou sur les jours : regular-expressions.info n'écrit que la forme « 31 jours partout » avec séparateurs au choix (« 02/31/2024 » passe), le motif de l'OWASP gère les bissextiles mais accepte des années à 2 chiffres, un séparateur à choisir parmi trois et la virgule dans une classe, et celui de jQuery Validation Engine gère bien jours et bissextiles mais mélange yyyy-mm-dd et mm/dd/yyyy sans exiger le zéro initial. Voici un motif strict à 4 chiffres, comparé à ces tentatives.
/^(?:(?:0[13578]|1[02])/31/[1-9][0-9]{3}|(?:0[13-9]|1[0-2])/(?:29|30)/[1-9][0-9]{3}|(?:0[1-9]|1[0-2])/(?:0[1-9]|1[0-9]|2[0-8])/[1-9][0-9]{3}|02/29/(?:[1-9][0-9](?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00))$/Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| OWASP Validation Regex Repository (« date ») — bissextiles gérés, mais années à 2 chiffres, jours/mois sans zéro initial, séparateurs « / - . » au choix et virgule dans « [1,3-9] » : « 4/5/25 » et « 02-29-2024 » passent | ^(?:(?:(?:0?[13578]|1[02])(\/|-|\.)31)\1|(?:(?:0?[1,3-9]|1[0-2])(\/|-|\.)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:0?2(\/|-|\.)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/|-|\.)(?:0?[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$ | 26 / 30 | sûr |
| regular-expressions.info (variante mm/dd/yyyy) — 31 jours partout et aucun contrôle des bissextiles : « 02/31/2024 » et « 04/31/2025 » passent ; séparateurs « - », espace, « / » ou « . » au choix ; années 1900-2099 seulement | ^(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d$ | 21 / 30 | sûr |
| jQuery-Validation-Engine (dateFormat) — gère bien jours par mois et bissextiles, mais accepte aussi yyyy-mm-dd, « / » ou « - » au choix et mois/jour sans zéro initial (« 1/5/2025 », « 01-01-2025 ») | ^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$ | 27 / 30 | sûr |
Implémentation
const re = new RegExp("^(?:(?:0[13578]|1[02])/31/[1-9][0-9]{3}|(?:0[13-9]|1[0-2])/(?:29|30)/[1-9][0-9]{3}|(?:0[1-9]|1[0-2])/(?:0[1-9]|1[0-9]|2[0-8])/[1-9][0-9]{3}|02/29/(?:[1-9][0-9](?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00))$", "");
re.test(input);Limites
- Valide la FORME et la cohérence calendaire (jours par mois, bissextiles), mais pas la plausibilité : « 01/01/9999 » passe. Le zéro initial est obligatoire (« 1/5/2025 » refusé) et seul le séparateur « / » est accepté : normalisez avant.
- Ambiguïté : « 03/04/2025 » est le 4 mars en format américain et le 3 avril en format européen ; la regex ne peut pas le deviner. Voir date-fr pour le format JJ/MM/AAAA.
- Années 1000 à 9999 seulement ; calendrier grégorien appliqué à toutes les années (« 02/29/1500 » est refusé alors qu'il existait dans le calendrier julien).