204

I need to validate a date string for the format dd/mm/yyyy with a regular expresssion.

This regex validates dd/mm/yyyy, but not the invalid dates like 31/02/4500:

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

What is a valid regex to validate dd/mm/yyyy format with leap year support?

Chris Martin
  • 28,558
  • 6
  • 66
  • 126
Nalaka526
  • 10,062
  • 20
  • 77
  • 115
  • 3
    I think it might help if you set an accurate expectation, as this regex does NOT, in fact, correctly validate leap years; e.g., there is no Feb. 29th in 2013, but this regex asserts that such is valid: http://regexr.com?346fp – TML Mar 19 '13 at 15:55
  • 9
    Why with Regex? There are easier (and more accurate) ways... – Dan Puzey Mar 19 '13 at 15:55
  • @TML You are correct... I have mistaken, It DOES NOT validate the leap year correctly... :( – Nalaka526 Mar 19 '13 at 16:00
  • 1
    @DanPuzey I'm not that familiar with Javascript, just wanted to get it validated client side... Can you suggest something more reliable and easier to maintain? – Nalaka526 Mar 19 '13 at 16:03
  • 2
    Regular expressions are for matching patterns, not checking numeric values. Find a likely string with the regex, then check its numeric value in whatever your host language is (PHP, whatever). – Andy Lester Mar 19 '13 at 16:41
  • You are using the wrong tool. regular expressions are not for validating. – Burhan Khalid Mar 21 '14 at 09:27
  • 3
    This answer has been added to the [Stack Overflow Regular Expression FAQ](http://stackoverflow.com/a/22944075/2736496), under "Common Validation Tasks". – aliteralmind Apr 10 '14 at 01:23
  • 4
    @BurhanKhalid: You are wrong. Regular expression is the best tool for validation, since HTML5 input has an attribute named `pattern` that takes a regular expression, and the browsers validate automatically against the regex without use of any javascript at all. Just by settting a regex in the pattern attribute! – awe Apr 15 '14 at 06:43
  • 2
    True dat, @DanPuzey. Any reason the original poster couldn't use something like moment#isValid? (If you haven't heard of momentjs, get on the good train: http://momentjs.com/docs/) – siege_Perilous Jun 09 '14 at 23:01
  • 1
    The linked dupe reason was for Ruby, thus, reopening this generic regex post. – Wiktor Stribiżew Feb 22 '19 at 12:15

23 Answers23

375

The regex you pasted does not validate leap years correctly, but there is one that does in the same post. I modified it to take dd/mm/yyyy, dd-mm-yyyy or 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})$

I tested it a bit in the link Arun provided in his answer and also here and it seems to work.

Edit February 14th 2019: I've removed a comma that was in the regex which allowed dates like 29-0,-11

J. Meijer
  • 21
  • 7
Ofir Luzon
  • 9,367
  • 2
  • 38
  • 47
  • Yes it does not validate the leap years, Updated the question. As you said this works fine, I'll accept this as the correct answer, thanks... :) – Nalaka526 Mar 19 '13 at 16:29
  • @Ofir: Your answer works fine for strings either I enter 27-01-2014 or 20-1-2014 but while converting 20-1-2014 to DateTime formate, It gives exception of "invalid string". Can you please do this for exact 27-01-2014 or 01-01-2001 instead of these two i.e. 27-1-2014 or 1-1-2001...?? – Sohail Jan 27 '14 at 07:42
  • @Sohail Not sure what you meant exactly, here is a regex that catches only two digits month and day: ^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0[1,3-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)02\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})$ – Ofir Luzon Jan 27 '14 at 11:30
  • 1
    @OfirLuzon Sir, can I ask for the format yyyy-mm-dd? – NightEye May 16 '14 at 04:02
  • 10
    Epic regex! How easily could this be interchanged according to format? For example yyyy-mm-dd and mm-dd-yyyy. I had a go at understanding it with that in mind, but it's beyond my regex skills. – mrswadge Oct 02 '14 at 16:13
  • 10
    Other than `DD/MM/YYYY`, this regex also accepts `DD/MM/YY` which I am not sure that it was in the initial intention of the poster. If you wish to not support 'YY', then remove all the optional `?` quantifiers. – user1485864 Nov 21 '14 at 17:24
  • i want `DD/MM/YYYY` format not `DD/MM/YY`, so for that which optional `?` quantifiers need to remove? – Purvesh Desai Jun 04 '15 at 04:59
  • 1
    @purveshdesai, remove the last occurrence of the `?` – Ofir Luzon Jun 04 '15 at 18:24
  • i need two digits month and day, also four digits year. so can u please provide regex for my requirement? – Purvesh Desai Jun 08 '15 at 06:34
  • 2
    @PurveshDesai replace each `0?` with `0`, and also remove the last occurrence of `?`. – Ofir Luzon Jun 09 '15 at 04:14
  • `29-02-20` seems to match when I removed all `0?` and the last `?`.. This shouldn't work yeah? @OfirLuzon – Marais Rossouw Jan 13 '16 at 00:33
  • 7
    @MaraisRossouw, You are correct, for 4 digit year, there are actually 3 `?` that should be removed: replace all `(?:1[6-9]|[2-9]\d)?` with `(?:1[6-9]|[2-9]\d)`. – Ofir Luzon Jan 13 '16 at 07:26
  • @OfirLuzon, Can you re-check regex **only two digits** in comment again ?, I think it something wrong – l2aelba Sep 05 '17 at 10:44
  • It seems impossible to edit it to mm-dd-yyy or mm.dd.yyyy format. Any help ? – Amogh Mishra Apr 30 '18 at 17:13
  • @OfirLuzon.. your explanation is perfect. However can you please convert the above Regex in mm/dd/yyyy, I am new to regex to unable to understand. – Md Kamran Azam Jul 26 '18 at 07:04
  • 1
    This is not working on React, " Octal literal in strict mode " because of \1 ,\2 ,\4... – Markus Ethur Oct 20 '18 at 12:00
  • 3
    Dropping by just to say this: **WOW** and of course _thank you_ – Jero Dungog Nov 06 '18 at 21:01
  • 1
    if someone want the empty string to also pass the regex than just use it like `^$|pattern` . I needed to make the text field optional – Sanket Patel Feb 27 '19 at 13:30
  • The `regex` you provided validates `12/12/13` also, which is not what the OP wants. – mishsx Aug 19 '19 at 08:48
  • It doesn't validate dates before 01/01/1600, am I right? – Pavoletto Apr 09 '20 at 12:09
  • which interval does this have? – Hilal Dec 08 '20 at 14:02
  • How do I use this masterpiece, if I want to find the date in a string? It seems to be only working if the date is the very first thing in the text. Try with something like this `test 01-02-2021`. I've tried few tweaks but without any luck. – Kamil Latosinski Feb 04 '21 at 21:22
275

I have extended the regex given by @Ofir Luzon for the formats dd-mmm-YYYY, dd/mmm/YYYY, dd.mmm.YYYY as per my requirement. Anyone else with same requirement can refer this

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

and tested for some test cases here http://regexr.com/39tr1.

For better understanding for this Regular expression refer this image: enter image description here

Alok Chaudhary
  • 3,171
  • 1
  • 14
  • 18
77

Notice:

Your regexp does not work for years that "are multiples of 4 and 100, but not of 400". Years that pass that test are not leap years. For example: 1900, 2100, 2200, 2300, 2500, etc. In other words, it puts all years with the format \d\d00 in the same class of leap years, which is incorrect. – MuchToLearn

So it works properly only for [1901 - 2099] (Whew)

dd/MM/yyyy:

Checks if leap year. Years from 1900 to 9999 are valid. Only dd/MM/yyyy

(^(((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)$)
gdZeus
  • 1,011
  • 8
  • 7
  • 11
    This answer works _only_ with dd/MM/yyyy. Therefore, is the right answer. – Rodrigo Apr 10 '15 at 14:28
  • 2
    @SylvainB I have fixed it – gdZeus Oct 07 '15 at 21:18
  • 2
    @gdZeus Thanks for delivering, even two years later! Scary to think that an incomplete solution has stood validated around here for so long though. – SylvainB Oct 08 '15 at 08:04
  • To make it quicker you can make the groups non-grouping. http://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 Dec 15 '16 at 09:17
  • 1
    I suppose I found an error: `29/02/2100` does not exist (2100 is NOT a leap year), but is still accepted by the given pattern. – KnorxThieus Jul 17 '17 at 19:54
  • Your regexp does not work for years that "are multiples of 4 and 100, but not of 400". Years that pass that test are *not* leap years. For example: 1900, 2100, 2200, 2300, 2500, etc. In other words, it puts all years with the format \d\d00 in the same class of leap years, which is incorrect. – MuchToLearn Oct 03 '17 at 15:52
22

try this.

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

you can test regular expression at http://www.regular-expressions.info/javascriptexample.html easily.

A.T.
  • 18,248
  • 7
  • 39
  • 59
  • 2
    this regex does not validate the date with the month like `30-02-2001`... anyway thanks for the answer :) – Nalaka526 Mar 19 '13 at 15:16
  • @Nalaka526, this regex works well enough for basic date validation. If you want to reliably check the validity of a date, you can always parse it. – peterchaula Jan 22 '21 at 06:17
13

I suspect that the following is as accurate as can be expected without knowing when the user's locale switched over from the Julian to the Gregorian calendars.

It accepts either '-', '/', or nothing as separators between year, month, and day, no matter the order.

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

yyyyMMdd:

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

Other than order, these all are accurate to the Julian Calendar (leap year every four years) until 1700, when the Gregorian Calendar diverges from the Julian. It has two issues:

  1. It accepts the year 0000, which doesn't exist in many, but not all, standards. Note that ISO 8601 does accept year 0000 (equivalent to 1 BCE).
  2. It doesn't skip the 10-13 days which were lost when the Gregorian Calendar came into use. This varies by locality though. For example, the Roman Catholic Church skipped 10 days, October 5th through October 14th, 1582, but Greece (the last to switch) skipped February 16th through the 28th of 1923, 13 days, having to take into account the leap years of 1700, 1800, and 1900.

This has been tested against Java's calendar implementation from the year 0001 until the year 9999 with the only discrepancy being the abovementioned 10 days in 1582.

Jason Greanya
  • 189
  • 1
  • 4
  • The YYYYMMDD regex incorrectly matches [01|02|03|05|06|07|09|10|11|13|14|15]00-02-29. Corrected 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)$`. Tested with python: https://repl.it/repls/DependentBestChapters – kpr Jan 16 '19 at 16:32
  • Note that Saudi Arabia recently (a year ago) switched from the Islamic Calendar, but Greece is still the last to switch from Julian to Gregorian. – Raymo111 Sep 26 '20 at 02:29
12

For those who look at these and get completely confused, here is an excerpt from my script. Unfortunately, all it does is match valid numbers in a date time input, and 31st Feb will be marked as valid, but as so many have said, regex really isn't the best tool to do this test.

To match a date in the format 'yyyy-MM-dd hh:mm' (Or indeed in whatever order you please)

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;
}

The above script starts off by building a regex object. It then finds all of the inputs whose id's match a certain pattern and then loops through these. I don't test the first input I find (if (e > 0)).

A bit of explanation:

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

^ means start of match, whereas $ means end of match.

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

\d+ means match a single or a contiguous sequence of integers, so myhtml_element_with_id_56_datetime and myhtml_element_with_id_2_datetime will match, but myhtml_element_with_id_5a_datetime will not

Luke Madhanga
  • 4,192
  • 1
  • 35
  • 40
9

Here is another version of regex to match any of the following date formats and allow leading zeros to be omitted:

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

Matches:

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

Debuggex Demo

Simple-Solution
  • 3,895
  • 12
  • 42
  • 63
7

Here I wrote one for dd/mm/yyyy where separator can be one of -.,/ year range 0000-9999.

It deals with leap years and is designed for regex flavors, that support lookaheads, capturing groups and backreferences. NOT valid for such as d/m/yyyy. If needed add further separators to [-.,/]

^(?=\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 at regex101; as a Java string:

"^(?=\\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}$"

explained:

(?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

Also see SO Regex FAQ; Please let me know, if it fails.

Community
  • 1
  • 1
Jonny 5
  • 11,051
  • 2
  • 20
  • 42
6

Found this reg ex here

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

This validates the format mm/dd/yyyy and valid dates correctly (but not m/d/yyyy).

Some tests

Nalaka526
  • 10,062
  • 20
  • 77
  • 115
  • 1
    Only works before 2014, have to change |20(0[0-9]|1[0-4]))) to |20(0[0-9]|1[0-9]))) to support until 2019 – Tony Dong Sep 26 '16 at 22:19
5
"^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((19|20)\\d\\d)$"

will validate any date between 1900-2099

Tushar Gupta - curioustushar
  • 54,013
  • 22
  • 95
  • 103
user3575114
  • 963
  • 7
  • 13
5

The following expression is nice and easy to manipulate:

((((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])))

It validates according to the MM/dd/YYYY format and allows for leap year support from 1960 to 2016. If you need the leap year support extended you need only manipulate this part of the expression:

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

Hope this helped you a lot

Chase
  • 51
  • 1
  • 1
3

Another answer which validates day (dd) depending upon the month (mm) and the year (yyyy) (i.e., also validates 29th Feb in leap years) and allows years ranging from 0001 to 9999 (0000 in a invalid year according to the Gregorian calendar)

^(?:(?:(?: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]))))$
Debanshu Kundu
  • 656
  • 6
  • 16
2

The best way according to me is to use the Moment.js isValid() method by specifying the format and use strict parsing.

As moment.js documentation says

As of version 2.3.0, you may specify a boolean for the last argument to make Moment use strict parsing. Strict parsing requires that the format and input match exactly, including delimiters.

value = '2020-05-25';
format = 'YYYY-MM-DD';
moment(value, format, true).isValid() // true
Sachin Kumar
  • 1,994
  • 1
  • 12
  • 30
1

I'm working with an API that only accepts MM/DD/YYYY format. I couldn't find any other post that did leap years quite as well as Ofir's answer, so I tweaked it and am re-posting it here for anyone that might need it.

/^(?:(?:(?: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})$/
Community
  • 1
  • 1
Daniel
  • 1,603
  • 15
  • 13
1

Please Following Expression

Regex regex = new Regex(@"(((0|1)[0-9]|2[0-9]|3[0-1])\/(0[1-9]|1[0-2])\/((19|20)\d\d))$");
Ghotekar Rahul
  • 262
  • 2
  • 9
1

Further extended the regex given by @AlokChaudhary to support:

1. dd mmm YYYY (in addition to dd-mmm-YYYY, dd/mmm/YYYY, dd.mmm.YYYY).

2. mmm in all CAPITAL LETTERS format (in addition to Title format)

dd mmm YYYY e.g. 30 Apr 2026 or 24 DEC 2028 are popular.

Extended regex:

(^(?:(?:(?:31(?:(?:([-.\/])(?:0?[13578]|1[02])\1)|(?:([-.\/ ])(?:Jan|JAN|Mar|MAR|May|MAY|Jul|JUL|Aug|AUG|Oct|OCT|Dec|DEC)\2)))|(?:(?:29|30)(?:(?:([-.\/])(?:0?[13-9]|1[0-2])\3)|(?:([-.\/ ])(?:Jan|JAN|Mar|MAR|Apr|APR|May|MAY|Jun|JUN|Jul|JUL|Aug|AUG|Sep|SEP|Oct|OCT|Nov|NOV|Dec|DEC)\4))))(?:(?:1[6-9]|[2-9]\d)?\d{2}))$|^(?:29(?:(?:([-.\/])(?:0?2)\5)|(?:([-.\/ ])(?:Feb|FEB)\6))(?:(?: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])))\7)|(?:([-.\/ ])(?:Jan|JAN|Feb|FEB|Mar|MAR|May|MAY|Jul|JUL|Aug|AUG|Oct|OCT|Dec|DEC)\8))(?:(?:1[6-9]|[2-9]\d)?\d{2}))$)

Test cases included in the Regex Demo

Features (retained):

  • Leap year checking (Feb 29 validation) includes the logics: (divisible by 4 but not divisible by 100) or (divisible by 400)
  • Supports years 1600 ~ 9999
  • Supports dd/mm/YYYY, dd-mm-YYYY, dd.mm.YYYY (but not dd mm YYYY)
  • Supports dd mmm YYYY, dd-mmm-YYYY, dd/mmm/YYYY, dd.mmm.YYYY (dd mmm YYYY newly added. mmm can be in CAPITAL e.g. DEC or Title format e.g. Dec)

Some additional minor touch-up as follows:

  1. Included the fix by Ofir Luzon on February 14th 2019 to remove a comma that was in the regex which allowed dates like 29-0,-11 [error replicated to Alok Chaudhary's regex]

  2. Replaced (\/|-|\.) by ([-.\/]) to minimize the use of backslash. \/ is still used in order to support some regex flavor e.g. PCRE(PHP) although some other regex flavor e.g. Python can simply use / inside the character class [ ]

  3. Added a pair of parenthesis () surrounding the whole regex to make it a capturing group for the whole matching string. This is useful for people using findAll type of functions to get a matching item list (e.g. re.findall in Python). This enable us to capture all the matching strings within a mult-line string with the following codes:

re.findall sample codes:

match_list = re.findall(regex, source_string)
for item in match_list:
    print(item[0])

Extended regex image: enter image description here

Credits should go to Ofir Luzon and Alok Chaudhary who created such excellent regexes for us all!

SeaBean
  • 6,349
  • 1
  • 3
  • 18
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])))

will validate MM/DD/YYYY format with 1960 to 2028

if you need to extend leap year support then add

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

this is also work

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

if you can change format mm-dd-yyyy than replace [/] to [-] also check online http://regexr.com/

techspider
  • 3,190
  • 11
  • 32
  • 60
mahesh
  • 9
  • 2
0

For date MM/DD/YYYY you can use

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

It verify proper days and moths.

Remeber that you can check your regular expression at

regex101

which i recommend :)

Have fun!

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])))

this regex will validate dates in format:

12-30-2016 (mm-dd-yyyy) or 12-3-2016 (mm-d-yyyy) or 1-3-2016 (m-d-yyyy) or 1-30-2016 (m-dd-yyyy)

mexekanez
  • 186
  • 1
  • 5
0

I know it is a tangential answer to the question, but if the intention of the question is 'how do I validate a date?', then why not try letting the programming language do all the hard work (if you are using a language that can)?

e.g. in php

$this_date_object = date_create($this_date);

if ($this_date_object == false )
    {

        // process the error

    }
0

For use only for the day:

<input placeholder="day" maxlength="2" minlength="1" formControlName="birthDay" 
   name="birthDay"pattern="(0[1-9]|1[0-9]|2[0-9]|3[0-1])" >/

For use only for the month:

 <input placeholder="month" maxlength="2" minlength="1" 
  formControlName="month" name="month" formControlName="month" name="month" pattern="(0[1- 
  9]|1[0-2])">/
fahimeh ahmadi
  • 469
  • 3
  • 6
0

In case you are looking for specific format, This works fine for "dd/MM/yyyy" & "dd/MMM/yyyy" date format only based on Alok answer.

function isValidDateFormatDDMMYYYY(inputDate) {
    var date_regex = /^(?:(?: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})$/;
    return date_regex.test(inputDate);
}

Few examples working thru this code -

  • isValidDateFormatDDMMYYYY("15/01/1999") // returns True
  • isValidDateFormatDDMMYYYY("15/Jan/1999") // returns True
  • isValidDateFormatDDMMYYYY("15/1/1999") // returns True
  • isValidDateFormatDDMMYYYY("1/15/1999") // returns False

Thanks

Rahul
  • 675
  • 7
  • 15
0
import re
expression = "Nov 05 20:10:09 2020"
reg_ex = r'((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-2][0-9]|(3)[0-1]) (([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])) (\d{4}))'
assert re.fullmatch(reg_ex, expression), True

Expaination with respect to given Example

  • Nov = A group of possible months i.e. (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
  • 05 = A group of valid days i.e. ([0-2][0-9]|(3)[0-1])
  • 20:10:09 = A group for getting valid Hours : ([0-1][0-9]|2[0-3]), Minutes : ([0-5][0-9]) and Seconds : ([0-5][0-9])
  • 2020 = A group for getting year i.e (\d{4}))
Shivam Bharadwaj
  • 1,130
  • 14
  • 17
  • 2
    While this code may solve the question, including an explanation of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations and give an indication of what limitations and assumptions apply – SherylHohman Nov 06 '20 at 19:44
  • @PareshMangukiya: There is not a link in this answer. – Jeremy Caney Nov 06 '20 at 21:18