web-dev-qa-db-fra.com

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

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

Cette regex valide dd/mm/yyyy, mais pas les dates non valides comme 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 format dd/mm/yyyy avec la prise en charge des années bissextiles?

143
Nalaka526

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

14 février 2019: j'ai supprimé une virgule contenue dans la regex qui autorisait des dates telles que 29-0,-11

283
Ofir Luzon

J'ai prolongé la regex donnée par @Ofir Luzon pour les formats jj-mmm-AAAA, jj/mmm/AAAA, jj.mmm.AAAA selon mes besoins. Toute autre personne ayant les mêmes exigences peut en 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: enter image description here

238
Alok Chaudhary

Remarquer:

Votre expression rationnelle ne fonctionne pas pendant des 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, toutes les années au format\d00 sont classées dans la même classe d'années bissextiles, ce qui est incorrect. - MuchToLearn

Donc, cela ne fonctionne correctement que pour [1901 - 2099] (Whew) ????

jj/mm/aaaa:

Vérifie si 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)$)
63
gdZeus

essaye ça.

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

vous pouvez tester l'expression régulière à l'adresse http://www.regular-expressions.info/javascriptexample.html facilement.

13
A.T.

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 du calendrier Julien aux calendriers grégorien.

Il accepte soit '-', '/' ou rien en tant que séparateur entre année, mois et 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))$

ddMMyyyy:

^(((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)$

Mis à part l'ordre, ceux-ci sont tous conformes au calendrier julien (année bissextile tous les quatre ans) jusqu'en 1700, lorsque le calendrier grégorien s'écarte de celui de Julien. Il a deux problèmes:

  1. Il accepte l'année 0000, qui n'existe pas dans beaucoup, mais pas dans toutes les normes. Notez que l'ISO 8601 accepte l'année 0000 (équivalent à 1 BCE).
  2. Il ne saute pas les 10-13 jours perdus lors de l’utilisation du calendrier grégorien. Cela varie par localité cependant. Par exemple, l’Église catholique romaine a sauté 10 jours, du 5 au 14 octobre 1582, mais la Grèce (la dernière à avoir basculé) a sauté du 16 février au 28 février 1923, soit 13 jours, devant tenir compte des années bissextiles de 1700, 1800 et 1900.

Cela a été testé avec l'implémentation du calendrier de Java de l'année 0001 à l'année 9999, la seule anomalie étant les 10 jours susmentionnés de 1582.

10
Jason Greanya

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 les nombres valides dans une entrée de date et 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.

Faire correspondre une date au format 'aaaa-MM-jj hh: mm' (ou 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 la construction d'un objet regex. Il trouve ensuite toutes les entrées dont l'identifiant correspond à un certain modèle, puis les parcourt en boucle. Je ne teste pas la première entrée trouvée (if (e > 0)).

Un peu d'explication:

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

^ signifie début de match, alors que $ signifie fin de match.

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

\d+ signifie correspondre à une séquence d'entiers ou à une séquence contiguë, donc myhtml_element_with_id_56_datetime et myhtml_element_with_id_2_datetime correspondent, mais myhtml_element_with_id_5a_datetime ne le sera pas.

10
Luke Madhanga

Voici une autre version de regex qui correspond à l’un des formats de date suivants et permet d’omettre les zéros de tête:

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

Correspondances:

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

Regular expression visualization

Démo Debuggex

9
Simple-Solution

J'ai trouvé ce registre 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))))$

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

Quelques tests

5
Nalaka526

Ici, j’en ai écrit un pour dd/mm/yyyy où le séparateur peut être l’un des -.,/ gamme d’années 0000-9999.

Il traite avec années bissextiles et est conçu pour les goûts de regex, qui supporte lookaheads, capture de groupes et références arrière. NON valide pour tel 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}$"

a 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 aussi FAQ de SO Regex ; S'il vous plaît faites le moi savoir, si cela échoue.

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

validera toute date comprise entre 1900-2099

4
user3575114

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 une prise en charge d'une année bissextile de 1960 à 2016. Si vous avez besoin d'une prise en charge d'une année bissextile étendue, 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é

4
Chase

Une autre réponse qui valide le jour (jj) en fonction du mois (mm) et de l’année (aaaa) (c’est-à-dire valide également le 29 février dans les années bissextiles) et permet des années comprises entre 0001 et 9999 (0000 dans une année non valide 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]))))$
3
Debanshu Kundu

Je travaille avec une API qui uniquement accepte le format MM/JJ/AAAA. Je ne pouvais trouver aucune autre publication faisant des années bissextiles aussi bien que réponse d'Ofir , alors je l'ai modifiée et je la rediffuse 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})$/
1
Daniel

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 laisser le langage de programmation faire le travail difficile ( si vous utilisez une langue qui peut)?

par exemple. en php

$this_date_object = date_create($this_date);

if ($this_date_object == false )
    {

        // process the error

    }
0
Neil Iosson
((((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 format MM/DD/YYYY avec 1960 à 2028

si vous devez prolonger l’année bissextile, 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 le format mm-dd-yyyy puis remplacer [/] par [-], vérifiez également en ligne http://regexr.com/

0
mahesh

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.

Rappelez-vous que vous pouvez vérifier votre expression régulière à

regex101

que je recommande :)

S'amuser!

^(((([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 expression régulière validera les dates au format:

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

0
mexekanez