1

The format of the regex is mm/dd/yyyy.

My current regex currently has a tiny problem, which I could not pinpoint. I could validate mm/dd/yyyy with valid months, leap year and year range. Although when the year written is '2016asdf' it still accepts the value.

The rules it should follow are:

  • Only valid dates are allowed
  • Feb 29 can be counted if it is a leap year
  • Year value ranges from 1900 - 2099

Valid values:

12/31/2016

01/15/1900

02/29/2016 (since 2016 is a leap year)

Invalid values:

1/01/1900 (since format is 'mm' not 'm')

01/32/1900 (since there's no such date)

13/22/1900 (since there's no such month)

03/01/2100 (beyond the year limit)

02/29/2017 (since 2017 is not a leap year)

9
  • Welcome to SO, please have a look at it before asking : stackoverflow.com/help Commented Feb 28, 2017 at 19:07
  • 1
    Don't parse dates with regexp. Commented Feb 28, 2017 at 19:07
  • Why dont't you use new Date(string) ? Commented Feb 28, 2017 at 19:11
  • @MaciejKozieja the instructions specified me to use regex only Commented Feb 28, 2017 at 19:13
  • @torazaburo I need to parse it with regex. Commented Feb 28, 2017 at 19:14

5 Answers 5

6

You got it incorrect. This shouldn't be done via Regex and in fact, it is not meant to do that. In order to that, you need to take the following steps:

1- Check the pattern via Regex

2- Validate the date.

The pattern you are looking for is:

var pattern = /(0\d{1}|1[0-2])\/([0-2]\d{1}|3[0-1])\/(19|20)\d{2}/

Take a look at this to see the pattern: http://regexr.com/3fe3s

Finally, if you want to check whether the date is a valid date or not (after checking in the pattern).

Here is the entire method:

    function isValidDate(dtValue2) {
    // your desired pattern
    var pattern = /(0\d{1}|1[0-2])\/([0-2]\d{1}|3[0-1])\/(19|20)(\d{2})/
    var m = dtValue2.match(pattern);
    if (!m)
        return false;
    var d = new Date(dtValue2);
    // Now let's ensure that the date is not out of index


    if (d.getMonth()+1 == parseInt(m[1], 10) && d.getDate() ==parseInt(m[2], 10)) {
        return true;
    }
    return false;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I made a minor mistake and I fixed for you.
Despite that this would be the better program flow, the problem is, I need to do it with regex ONLY, and not use any other functions except for .test(), therefore, I need to test the string directly to match the regex.
Well. You are having a good reference for any possible future projects.
1

There is a very thorough answer here. You can read the explanations and caveats of using that method.

31 day months

(0[13578]|1[02])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2}

30 day months

(0[469]|11)[\/.](0[1-9]|[12][0-9]|30)[\/.](18|19|20)[0-9]{2}

February 1-28 always valid

(02)[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2}

February 29 also valid on leap years

(02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000)

which means it would be this if you put it all together:

((0[13578]|1[02])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2})|((0[469]|11)[\/.](0[1-9]|[12][0-9]|30)[\/.](18|19|20)[0-9]{2})|((02)[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2})|((02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000))

This version is a little shorter, but a little harder to understand.

((0[13578]|1[02])[\/.]31[\/.](18|19|20)[0-9]{2})|((01|0[3-9]|1[1-2])[\/.](29|30)[\/.](18|19|20)[0-9]{2})|((0[1-9]|1[0-2])[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2})|((02)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000))

These scripts are long and unmaintainable. It should be clear that this isn't a good idea, but it is possible.

Caveats:

  • range 1800-2099 (more can be added without too much difficulty, but requires changes in 4-6 disparate places)
  • requires 2 digit months and days (the strictness could be removed from the expression in ~8 places)
  • [/.] as seperators (8 places)
  • Hasn't been tested (we could check it against all digit combinations and compare with the avascript date function? [proof that we're reinventing the wheel])

Comments

0

It needs to have ^ and $ on every | so the regex should be:

^((0[13578]|1[02])[/.]31/.[0-9]{2})$|^((01|0[3-9]|1[1-2])/./.[0-9]{2})$|^((0[1-9]|1[0-2])/./.[0-9]{2})$|^((02)[/.]29/.)$

Working expression

2 Comments

Actually, you just can set a group around the pattern in between anchors - ^(?:((0[13578]|1[02])[\/.]31[\/.](19|20)[0-9]{2})|((01|0[3-9]|1[1-2])[\/.](29|30)[\/.](19|20)[0-9]{2})|((0[1-9]|1[0-2])[\/.](0[1-9]|1[0-9]|2[0-8])[\/.](19|20)[0-9]{2})|((02)[\/.]29[\/.](((19|20)(04|08|[2468][048]|[13579][26]))|2000)))$
@torazaburo I indicated in the question above that the year limit is only 1900 - 2099
0

I would try this
^02\/(?:[01]\d|2\d)\/(?:19|20)(?:0[048]|[13579][26]|[2468][048])|(?:0[13578]|10|12)\/(?:[0-2]\d|3[01])\/(?:19|20)\d{2}|(?:0[469]|11)\/(?:[0-2]\d|30)\/(?:19|20)\d{2}|02\/(?:[0-1]\d|2[0-8])\/(?:19|20)\d{2}$
:

const regex = /^02\/(?:[01]\d|2\d)\/(?:19|20)(?:0[048]|[13579][26]|[2468][048])|(?:0[13578]|10|12)\/(?:[0-2]\d|3[01])\/(?:19|20)\d{2}|(?:0[469]|11)\/(?:[0-2]\d|30)\/(?:19|20)\d{2}|02\/(?:[0-1]\d|2[0-8])\/(?:19|20)\d{2}$/

const testData = [
  '02/02/1904',
  '02/12/2008',
  '02/29/2012',
  '02/29/2013',
  '06/31/2013',
  '01/31/2013',
  '02/02/1916',
  '02/02/2020',
  '02/02/2024',
  '02/02/2036',
  '02/02/1952',
  '02/02/2056',
  '01/01/2256',
  '02/29/2000',
  '02/29/2100',
  '02/29/1900',
  '02/29/1200',
  '02/29/2400'
]

for (let date of testData) {
  console.log(`${date} ${regex.test(date)}`)
}

1 Comment

'Year value ranges from 1900 - 2099'
0

It validates these formats:

  • YYYY-DD-MM
  • YYYY/DD/MM
  • YYYY.DD.MM
  • YYYY.0M.0D
  • YYYY/0D/0M
  • YYYY-0D-0M
  • YYYY-D-M
  • YYYY.D.M
  • YYYY/D/M and so on
/(((19\d{2}|20[0-9]{2}))(\/|\.|\-)(0?[1-9]|1[0-9]|2[0-9]|3[0-1])(\/|\.|\-))(0[0-9]$|1[0-2]$|[0-9]$)/gm

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.