Tuesday, November 22, 2011

RegEx for Dates including leap year with locale support

First of all when you are playing with regex it helps to have a tool that will let you see what is happening. For this I have found Expresso (http://www.ultrapico.com/Expresso.htm found here in 2011 and is a free tool).

While working on the localization of our entire suite of systems & applications we needed a regular expression that would validate user input for a date. So depending on the user locale/language the date format changes. We needed three: Day first(Europe) DD.MM.YYYY, Month first MM/DD/YYYY (US) and year first YYYY/MM/DD (chinese).

So we set the value of the Threads current context and used the DateFormatInfo class from there to determine which format to use.
Then we found a regEx that worked for US (ref.1) and modified it for out use.

^(?

(?

(?0?[1-9]|1[012])

[- /.]{1} #seperator

(?0?[1-9]|1\d|2[0-8])

|

(?0?[13456789]|1[012])

[- /.]{1} #seperator

(?29|30)

|

(?0?[13578]|1[02])

[- /.]{1} #seperator

(?31))

[- /.]{1} #seperator

(?19|[2-9]\d)

(?\d{2})

|

(?0?2)

[- /.]{1} #seperator

(?29)

[- /.]{1} #seperator

(?(?19|[2-9]\d)(?0[48]|[2468][048]|[13579][26])|(?(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

)$

|

#German

^(?

(?

(?0?[1-9]|1\d|2[0-8])

[- /.]{1} #seperator

(?0?[1-9]|1[012])

|

(?29|30)

[- /.]{1} #seperator

(?0?[13456789]|1[012])

|

(?31)

[- /.]{1} #seperator

(?0?[13578]|1[02])

)

[- /.]{1} #seperator

(?19|[2-9]\d)

(?\d{2})

|

(?29)

[- /.]{1} #seperator

(?0?2)

[- /.]{1} #seperator

(?

(?19|[2-9]\d)

(?0[48]|[2468][048]|[13579][26])

|

(?

(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

)$

|

#CHN

^(?

(?19|[2-9]\d)

(?\d{2})

[- /.]{1} #seperator

(?

(?0?[1-9]|1[012])

[- /.]{1} #seperator

(?0?[1-9]|1\d|2[0-8])

|

(?0?[13456789]|1[012])

[- /.]{1} #seperator

(?29|30)

|

(?0?[13578]|1[02])

[- /.]{1} #seperator

(?31))

|

(?(?19|[2-9]\d)(?0[48]|[2468][048]|[13579][26])|(?(?[2468][048]|[3579][26])00)) # leap year 02 or 2 / 29

[- /.]{1} #seperator

(?0?2)

[- /.]{1} #seperator

(?29)

)$



-------------------------------
Ref.1 - by Dany Lauener; http://regexlib.com/UserPatterns.aspx?authorId=81355952-f53d-4142-bc5c-aab2beae19f3; search for "MM/dd/yyyy with 100% leap years. Valid since year 1900"