# Regex for date with consideration for month and days relationship

I’m doing an exercise that asks me to write a regex. Here are the details:

The regex will match a string only if it contains at least one valid date, like:
[dd-mm]
Assuming the year in question is not a leap year.
The number of days each month should have are:

January 31 days
February 28 days
So on

All text outside a valid date can be ignored, including other invalid dates.

For example:

“[01-23]” // January 23rd is a valid date
“[02-31]” // February 31st is an invalid date
“[02-16]” // valid
“[ 6-03]” // invalid format
“ignored [08-11] ignored” // valid
“[3] [12-04] [09-tenth]” // December 4th is a valid date

How should I approach this? I guess there’s no need to write one regex for each month…

I’m learning regex today. And this exercise is from a website.

1 Like

It’s going to be a complex regex!

You’ll want to group all of the months that have the same number of days, and then setup a regex that checks for a range of numbers that proceed those months.

For Feb it would look something like this:

``````/02-(0[1-9]|1[0-9]|2[0-8])/
``````

If March also had 28 days then you could match it as well like this:

``````/(02|03)-(0[1-9]|1[0-9]|2[0-8])/
``````

As an aside, here’s a really great interactive tutorial to learning regex http://tryregex.com/

1 Like

Sorry, I don’t understand the logic of the day part. The first digit for the day can only go from 0 to 2, the second digit can go from 0 to 8 if the first is a two, but from 0 to 9 if the first digit is a 0 or a 1.

I can say “or” with “|” in regex but can I say “and”?

I was thinking of this:

If the first digit is 0 or 1, the second day digit can go from 0 to 9, if the first digit is a 2, then the second digit can go from 0 to 8. *

`/02-(\d[0-1]\d[0-9])|(\d[2]\d[0-8])/

Thanks for the comments.

The first part literally matches the string “02-”

``````/02-/
``````

The second matches the range of numbers from 01 to 28 for the days in feb

``````/(0[1-9]|1[0-9]|2[0-8])/
``````

Hi Mark, we were writing at the same time, so just added something above your last comment. But it’s a dd format.

Here’s the three regexes that match valid “dd-mm” strings for the year.

``````/(01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])/
/(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)/
/02-(0[1-9]|1[0-9]|2[0-8])/
``````

You can combine them with this form

``````/(regex1|regex2|regex3)/
``````

This doesn’t do quite what you’re expecting, \d matches any digit character, [0-1] matches ‘0’ or ‘1’

``````/\d[0-1]/.test('91')
``````

Thanks a lot. What happens if I’d like to match a date with square bracket literals, like:> [mm-dd]. How do I escape the square brackets?

I tried this:

`var validDate = /(\[){1}(01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])|(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)|02-(0[1-9]|1[0-9]|2[0-8])(\]{1})/;`

And the test almost passes except for:

``````Input: [01-11d should be invalid but was found valid.
Input: [01-10s should be invalid but was found valid.
Input: [12-29e should be invalid but was found valid.
Input: [12-27d should be invalid but was found valid.
``````

Sorry, I asked so many questions. I read all the chapters in my JS books on regex and there’s nothing about this complex patterns. So thanks again.

OK, I’ll answer my own question:

`/(?:\[)(01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])(?:\]) | (?:\[)(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)(?:\]) | (?:\[)02-(0[1-9]|1[0-9]|2[0-8])(?:\])/`

Thanks a lot Mark.

None of your | are working the way you expect. They only work on the charactor or group adjacent on each side.

Even if your expression did work it would report the date for Monday after next as invalid [02-29]

Doesn’t look so good using https://regex101.com/ - only one match

EDIT
Well, maybe, much better after adding spaces and a “g”

Remove the spaces that were added to the text.

The regex just needs the spaces removed from around the pipe symbols, and it works fine.

``````(?:\[)(01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])(?:\])|(?:\[)(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)(?:\])|(?:\[)02-(0[1-9]|1[0-9]|2[0-8])(?:\])```

<img src="/community/uploads/default/original/3X/8/6/86f0307ce17930769df663a17ff3c29e57cd9132.png" width="690" height="242">``````
2 Likes

Here’s all of the pieces:

``````\[
(
(01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])
|
(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)
|
02-(0[1-9]|1[0-9]|2[0-8])
)
\]
``````

Regex

``````/\[((01|03|05|07|08|10|12)-(0[1-9]|1[0-9]|2[0-9]|3[01])|(04|06|09|11)-(0[1-9]|1[0-9]|2[0-9]|30)|02-(0[1-9]|1[0-9]|2[0-8]))\]/
``````

this last one didn’t pass all the tests, the one that worked is the one with the non capturing group with brackets for each one.

Capturing groups won’t effect the truthiness of the regex.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.