Regex pour valider le format de date jj / mm / aaaa


172

J'ai besoin de valider une chaîne de date pour le format dd/mm/yyyyavec une expression régulière.

Cette expression régulière valide dd/mm/yyyy, mais pas les dates invalides telles que 31/02/4500:

^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}$

Qu'est-ce qu'une expression régulière valide pour valider le dd/mm/yyyyformat avec le support des années bissextiles?


3
Je pense que cela pourrait aider si vous définissez une attente précise, car cette expression régulière ne valide PAS, en fait, correctement les années bissextiles; par exemple, il n'y a pas de 29 février 2013, mais cette expression régulière affirme que tel est valide: regexr.com?346fp
TML

7
Pourquoi avec Regex? Il existe des moyens plus faciles (et plus précis) ...
Dan Puzey

2
Les expressions régulières servent à faire correspondre les modèles, et non à vérifier les valeurs numériques. Trouvez une chaîne probable avec l'expression régulière, puis vérifiez sa valeur numérique quel que soit votre langage hôte (PHP, peu importe).
Andy Lester

3
Cette réponse a été ajoutée à la FAQ sur les expressions régulières Stack Overflow , sous "Tâches de validation courantes".
aliteralmind

4
@BurhanKhalid: Vous vous trompez. L'expression régulière est le meilleur outil de validation, car l'entrée HTML5 a un attribut nommé patternqui prend une expression régulière, et les navigateurs valident automatiquement par rapport à l'expression régulière sans utiliser du tout de JavaScript. Juste en définissant une regex dans l'attribut pattern!
awe

Réponses:


329

La regex que vous avez collée ne valide pas correctement les années bissextiles, mais il y en a une qui le fait dans le même message . Je l'ai modifié pour prendre dd/mm/yyyy, dd-mm-yyyyou dd.mm.yyyy.

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

Je l'ai testé un peu dans le lien fourni par Arun dans sa réponse et aussi ici et cela semble fonctionner.

Modifier le 14 février 2019: j'ai supprimé une virgule qui était dans l'expression régulière qui permettait des dates comme 29-0,-11


9
Regex épique! Avec quelle facilité cela pourrait-il être interchangé selon le format? Par exemple, aaaa-mm-jj et mm-jj-aaaa. J'ai essayé de le comprendre dans cet esprit, mais cela dépasse mes compétences en regex.
mrswadge

7
En dehors de DD/MM/YYYYcela, cette expression régulière accepte également DD/MM/YYce que je ne suis pas sûr que ce soit dans l'intention initiale de l'affiche. Si vous ne souhaitez pas prendre en charge «YY», supprimez tous les ?quantificateurs facultatifs .
user1485864

2
@PurveshDesai remplace chacun 0?par 0, et supprime également la dernière occurrence de ?.
Ofir Luzon

4
@MaraisRossouw, Vous avez raison, pour une année à 4 chiffres, il y en a en fait 3 ?qui devraient être supprimés: remplacez tout (?:1[6-9]|[2-9]\d)?par (?:1[6-9]|[2-9]\d).
Ofir Luzon

2
Je passe juste pour dire ceci: WOW et bien sûr merci
Jero Dungog

266

J'ai étendu le regex donné par @Ofir Luzon pour les formats jj-mmm-AAAA, jj / mmm / AAAA, jj.mmm.YYYY selon mes besoins. Toute autre personne ayant la même exigence peut le référer

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

et testé pour certains cas de test ici http://regexr.com/39tr1 .

Pour une meilleure compréhension de cette expression régulière, reportez-vous à cette image: entrez la description de l'image ici


1
Oui, comment l'avez-vous généré? :)
Razor

Je l'ai généré en ligne en utilisant un site Web et maintenant je ne me souviens pas non plus du site Web à partir duquel j'ai généré cette image. J'ajouterai la référence une fois que je me souviendrai :)
Alok Chaudhary

4
@ user3733831 8888est une année possible. J'espère vivre jusqu'à cet âge.
Dan Nissenbaum

1
Fonctionne très bien même pendant les années bissextiles. J'ai également ajouté un support pour les noms de mois espagnols courts.
Fer R

2
@AlokChaudhary, le diagramme a été généré à l'aide de debuggex.com
Taha BASRI

69

Remarquer:

Votre expression régulière ne fonctionne pas pendant les années qui "sont des multiples de 4 et 100, mais pas de 400". Les années qui passent ce test ne sont pas des années bissextiles. Par exemple: 1900, 2100, 2200, 2300, 2500, etc. En d'autres termes, il met toutes les années au format \ d \ d00 dans la même classe d'années bissextiles, ce qui est incorrect. - MuchToLearn

Donc ça ne fonctionne correctement que pour [1901 - 2099] (Ouf) 😊

jj / MM / aaaa:

Vérifie si l'année bissextile. Les années 1900 à 9999 sont valables. Seulement jj / MM / aaaa

(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)

7
Cette réponse fonctionne uniquement avec jj / MM / aaaa. Par conséquent, est la bonne réponse.
Rodrigo

2
@SylvainB Je l'ai corrigé
gdZeus

2
@gdZeus Merci d'avoir livré, même deux ans plus tard! Effrayant de penser qu'une solution incomplète a été validée ici pendant si longtemps.
SylvainB

Pour accélérer les choses, vous pouvez rendre les groupes non groupés. regexr.com/3esom ^ (? :(? :(? :( ?: 0 [1-9] | 1 [0-9] | 2 [0-8]) [\ /] (?: 0 [1- 9] | 1 [012])) | (? :( ?: 29 | 30 | 31) [\ /] (?: 0 [13578] | 1 [02])) | (? :( ?: 29 | 30 ) [\ /] (?: 0 [4,6,9] | 11))) [\ /] (?: 19 | [2-9] [0-9]) \ d \ d) | (?: 29 [\ /] 02 [\ /] (?: 19 | [2-9] [0-9]) (?: 00 | 04 | 08 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96)) $
Matt Vukomanovic

Je suppose que j'ai trouvé une erreur: 29/02/2100n'existe pas (2100 n'est PAS une année bissextile), mais est toujours acceptée par le modèle donné.
KnorxThieus


12

Je soupçonne que ce qui suit est aussi précis que possible sans savoir quand les paramètres régionaux de l'utilisateur sont passés des calendriers julien aux calendriers grégoriens.

Il accepte soit «-», «/», ou rien comme séparateurs entre l'année, le mois et le jour, quel que soit l'ordre.

MMddyyyy:

^(((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))[-/]?[0-9]{4}|02[-/]?29[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

jjMMaaaa:

^(((0[1-9]|[12][0-9]|30)[-/]?(0[13-9]|1[012])|31[-/]?(0[13578]|1[02])|(0[1-9]|1[0-9]|2[0-8])[-/]?02)[-/]?[0-9]{4}|29[-/]?02[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

aaaaMMjj:

^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-/]?02[-/]?29)$

Autre que l'ordre, ceux-ci sont tous fidèles au calendrier julien (année bissextile tous les quatre ans) jusqu'en 1700, lorsque le calendrier grégorien diverge du calendrier julien. Il a deux problèmes:

  1. Il accepte l'année 0000, qui n'existe pas dans de nombreuses normes, mais pas toutes. Notez que ISO 8601 accepte l'année 0000 (équivalent à 1 BCE).
  2. Il n'ignore pas les 10 à 13 jours qui ont été perdus lorsque le calendrier grégorien est entré en vigueur. Cela varie cependant selon la localité. Par exemple, l'Église catholique romaine a sauté 10 jours, du 5 octobre au 14 octobre 1582, mais la Grèce (la dernière à changer) a sauté le 16 février au 28 février 1923, 13 jours, devant prendre en compte les années bissextiles de 1700, 1800 et 1900.

Cela a été testé par rapport à la mise en œuvre du calendrier de Java de l'année 0001 à l'année 9999, le seul écart étant les 10 jours susmentionnés en 1582.


L'expression régulière AAAAMMJJ correspond incorrectement à [01 | 02 | 03 | 05 | 06 | 07 | 09 | 10 | 11 | 13 | 14 | 15] 00-02-29. Correction regex: ^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048])00)[-/]?02[-/]?29)$. Testé avec python: repl.it/repls/DependentBestChapters
kpr

10

Pour ceux qui les regardent et sont complètement confus, voici un extrait de mon script. Malheureusement, tout ce qu'il fait est de faire correspondre des nombres valides dans une entrée de date et d'heure, et le 31 février sera marqué comme valide, mais comme beaucoup l'ont dit, regex n'est vraiment pas le meilleur outil pour faire ce test.

Pour faire correspondre une date au format 'aaaa-MM-jj hh: mm' (Ou bien dans l'ordre de votre choix)

var dateerrors = false;
var yearReg = '(201[4-9]|202[0-9])';            ///< Allows a number between 2014 and 2029
var monthReg = '(0[1-9]|1[0-2])';               ///< Allows a number between 00 and 12
var dayReg = '(0[1-9]|1[0-9]|2[0-9]|3[0-1])';   ///< Allows a number between 00 and 31
var hourReg = '([0-1][0-9]|2[0-3])';            ///< Allows a number between 00 and 24
var minReg = '([0-5][0-9])';                    ///< Allows a number between 00 and 59
var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');
$('input').filter(function () {return this.id.match(/myhtml_element_with_id_\d+_datetime/);}).each(function (e) {
    if (e > 0) {
        // Don't test the first input. This will use the default
        var val = $(this).val();
        if (val && !val.trim().match(reg)) {
            dateerrors = true;
            return false;
        }
    }
});
if (dateerrors) {
    alert('You must enter a validate date in the format "yyyy-mm-dd HH:MM", e.g. 2019-12-31 19:30');
    return false;
}

Le script ci-dessus commence par créer un objet regex. Il trouve ensuite toutes les entrées dont les identifiants correspondent à un certain modèle, puis les boucle. Je ne teste pas la première entrée que je trouve ( if (e > 0)).

Un peu d'explication:

var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');

^signifie le début du match, alors que $signifie la fin du match.

return this.id.match(/myhtml_element_with_id_\d+_datetime/);

\d+signifie correspondre à une séquence entière ou contiguë d'entiers, donc myhtml_element_with_id_56_datetimeet myhtml_element_with_id_2_datetimecorrespondra, mais myhtml_element_with_id_5a_datetimene sera pas


8

Voici une autre version de regex pour correspondre à l'un des formats de date suivants et autoriser l'omission des zéros non significatifs:

Regex: ^[0-3]?[0-9].[0-3]?[0-9].(?:[0-9]{2})?[0-9]{2}$

Allumettes:

1/1/11 or 1.1.11 or 1-1-11 : true 01/01/11 or 01.01.11 or 01-01-11 : true 01/01/2011 or 01.01.2011 or 01-01-2011 : true 01/1/2011 or 01.1.2011 or 01-1-2011 : true 1/11/2011 or 1.11.2011 or 1-11-2011 : true 1/11/11 or 1.11.11 or 1-11-11 : true 11/1/11 or 11.1.11 or 11-1-11 : true

Visualisation des expressions régulières

Démo Debuggex


4
ne fonctionne pas si vous avez 13/13/2000= Correspondances est vrai
Andrei Krasutski

3
39/39/39 n'est pas une date. Veuillez arrêter de voter pour cette réponse.
Warren Sergent

6

Ici, j'en ai écrit un pour dd/mm/yyyylequel le séparateur peut être un de l' -.,/année 0000-9999.

Il traite des années bissextiles et est conçu pour les saveurs regex, qui prennent en charge les lookaheads, la capture de groupes et les références arrière. NON valable pour tels que d/m/yyyy. Si nécessaire, ajoutez des séparateurs supplémentaires[-.,/]

^(?=\d{2}([-.,\/])\d{2}\1\d{4}$)(?:0[1-9]|1\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\d{4}$

Test à regex101 ; en tant que chaîne Java:

"^(?=\\d{2}([-.,\\/])\\d{2}\\1\\d{4}$)(?:0[1-9]|1\\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\\d{4}$"

expliqué:

(?x) # modifier x: free spacing mode (for comments)
     # verify date dd/mm/yyyy; possible separators: -.,/
     # valid year range: 0000-9999

^    # start anchor

# precheck xx-xx-xxxx,... add new separators here
(?=\d{2}([-.,\/])\d{2}\1\d{4}$)

(?:  # day-check: non caturing group

  # days 01-28
  0[1-9]|1\d|[2][0-8]| 

  # february 29d check for leap year: all 4y / 00 years: only each 400
  # 0400,0800,1200,1600,2000,...
  29
  (?!.02. # not if feb: if not ...
    (?!
      # 00 years: exclude !0 %400 years
      (?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)

      # 00,04,08,12,... 
      \d{2}(?:[02468][048]|[13579][26])
    )
  )|

  # d30 negative lookahead: february cannot have 30 days
  30(?!.02)|

  # d31 positive lookahead: month up to 31 days
  31(?=.(?:0[13578]|10|12))

) # eof day-check

# month 01-12
.(?:0[1-9]|1[012])

# year 0000-9999
.\d{4}

$ # end anchor

Voir également la FAQ SO Regex ; S'il vous plaît laissez-moi savoir, si cela échoue.


5

J'ai trouvé ce reg ex ici

^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[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))))$

Cela valide mm/dd/yyyycorrectement le format et les dates valides (mais pas m/d/yyyy).

Quelques tests


1
Fonctionne uniquement avant 2014, il faut changer | 20 (0 [0-9] | 1 [0-4]))) en | 20 (0 [0-9] | 1 [0-9]))) pour prendre en charge jusqu'à 2019
Tony Dong

5
"^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((19|20)\\d\\d)$"

validera toute date entre 1900-2099


5

L'expression suivante est agréable et facile à manipuler:

((((0[13578]|1[02])(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)((\/|-|.)(0[1-9]|1[0-9]|2[0-8]))))(\/|-|.)(19([6-9][0-9])|20(0[0-9]|1[0-4])))|((02)(\/|-|.)(29)(\/|-|.)(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26])))

Il valide selon le format MM / jj / AAAA et permet le support des années bissextiles de 1960 à 2016. Si vous avez besoin du support des années bissextiles étendu, il vous suffit de manipuler cette partie de l'expression:

(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]))

J'espère que cela vous a beaucoup aidé


3

Une autre réponse qui valide le jour (jj) en fonction du mois (mm) et de l'année (aaaa) (ie, valide également le 29 février en années bissextiles) et autorise des années allant de 0001 à 9999 (0000 dans une année invalide selon le grégorien calendrier)

^(?:(?:(?:0[1-9]|[12]\d|3[01])/(?:0[13578]|1[02])|(?:0[1-9]|[12]\d|30)/(?:0[469]|11)|(?:0[1-9]|1\d|2[0-8])/02)/(?!0000)\d{4}|(?:(?:0[1-9]|[12]\d)/02/(?:(?!0000)(?:[02468][048]|[13579][26])00|(?!..00)\d{2}(?:[02468][048]|[13579][26]))))$

1
ne valide pas le 18/05/0017

1

Je travaille avec une API qui n'accepte que le format MM / JJ / AAAA. Je n'ai trouvé aucun autre article qui fasse des années bissextiles aussi bien que la réponse d'Ofir , alors je l'ai peaufiné et je le publie à nouveau ici pour tous ceux qui pourraient en avoir besoin.

/^(?:(?:(?:0[13578]|1[02])(\/)31)\1|(?:(?:0[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:02(\/)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})$/

0
((((0[13578]|1[02])\/(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)\/(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)(\/(0[1-9]|1[0-9]|2[0-8]))))\/(19([6-9][0-9])|20([0-9][0-9])))|((02)\/(29)\/(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

validera le MM/DD/YYYYformat avec 1960à2028

si vous avez besoin d'étendre le support des années bissextiles, ajoutez

19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048]|3[26]|4[048])))

c'est aussi du travail

^((((0[13578]|1[02])[/](0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)[/](0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)([/](0[1-9]|1[0-9]|2[0-8]))))[/](19([6-9][0-9])|20([0-9][0-9])))|((02)[/](29)[/](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

si vous pouvez changer de format mm-dd-yyyyque de remplacer [/]pour [-] vérifier également en ligne http://regexr.com/


0

Pour la date MM / JJ / AAAA, vous pouvez utiliser

^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$

Il vérifie les jours et les mites appropriés.

N'oubliez pas que vous pouvez vérifier votre expression régulière à

regex101

ce que je recommande :)

S'amuser!


0
^(((([13578]|0[13578]|1[02])[-](0[1-9]|[1-9]|1[0-9]|2[0-9]|3[01]))|(([469]|0[469]|11)[-]([1-9]|1[0-9]|2[0-9]|3[0]))|((2|02)([-](0[1-9]|1[0-9]|2[0-8]))))[-](19([6-9][0-9])|20([0-9][0-9])))|((02)[-](29)[-](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

cette regex validera les dates au format:

30-12-2016 (mm-jj-aaaa) ou 12-3-2016 (mm-j-aaaa) ou 1-3-2016 (md-aaaa) ou 1-30-2016 (m-jj-aaaa)


0

Je sais que c'est une réponse tangentielle à la question, mais si l' intention de la question est `` comment valider une date? '', Alors pourquoi ne pas essayer de laisser le langage de programmation faire tout le travail (si vous utilisez un langage qui pouvez)?

par exemple en php

$this_date_object = date_create($this_date);

if ($this_date_object == false )
    {

        // process the error

    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.