Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex validate correct ISO8601 date string with time

Tags:

regex

For example: 2015-01-17T18:23:02+00:00

Having some trouble with the regex as certain components of the string to be considered 'valid' are speculated and may not be required.

Also the fact the string can be formatted as: 2015-01-17T18:23:02Z is throwing me slightly

Thanks in advance guys.

like image 595
Jack hardcastle Avatar asked Jan 19 '15 08:01

Jack hardcastle


Video Answer


2 Answers

Based on an earlier answer of mine, you could do this and be pretty darn strict:

^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:Z|[+-][01]\d:[0-5]\d)$ 

Regular expression visualization

Debuggex Demo

Slightly monstrous but it checks for valid dates including leap-year (Proleptic Gregorian), works for years 1000-9999, checks for invalid times like 25:30 or 21:94 and a maximum UTC offset of +/-19:59 (or a Z).

(right now more than +14:00 or -12:00 doesn't happen, but it might in the future).

For completion: This answer only supports a subset of the ISO8601 standard based on the examples OP gave. Which is the extended notation with seconds in the time section and minutes in the UTC offset. For brevity it does not support basic notation where dashes and colons are omitted, or the omitting of minutes in the UTC offset or the smallest unit. Nor is there support for ordinal dates (day-of-year) or year-week-dayofweek notations.

An extended version of the regex that supports basic notation, ordinal and the omitting of seconds / UTC-offset minutes lives here.

like image 187
asontu Avatar answered Sep 19 '22 01:09

asontu


Based on the previous answer, this regex handles the fraction of seconds.

^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d{1,9})?(?:Z|[+-][01]\d:[0-5]\d)$ 

Debuggex Demo

like image 21
Nicolas Henneaux Avatar answered Sep 21 '22 01:09

Nicolas Henneaux