Jack hardcastle
Jack hardcastle

Reputation: 2875

Regex validate correct ISO8601 date string with time

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.

Upvotes: 39

Views: 45007

Answers (8)

Ale T.
Ale T.

Reputation: 1

After struggling for a few hours I got this regex working:

^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:Z|[+-](\b(0[1-9]|1[0-7])\b:[0-5][0-9]|18:00))$

The only issue I've found so far has been that it allows for February 29th on non-leap years. Also, it only generates 4-digit years, but that is easier to change.

I've used this page to generate strings matching said regex and then tested them in this online Java compiler by trying

System.out.println(OffsetDateTime.parse(toParse[i]));

Upvotes: 0

Abdo Driowya
Abdo Driowya

Reputation: 156

if using regex is not mandatory, I think the best way to detect it in js is by doing this :

function isIso8601(value) {
    return new Date(value).toJSON() === value;
}
isIso8601('2019-08-21T16:35:05.073Z'); // true
isIso8601('2013-99-99T04:13:00+00:00'); // false

Upvotes: 1

Parth Chokshi
Parth Chokshi

Reputation: 652

^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]{3})?(Z)?$

DateTime. Also covers optional Milliseconds.

Upvotes: 1

Ranidu
Ranidu

Reputation: 511

to match with date and timezones

2019-07-01T24:15:00+19:00

\d{4}-[01]{1}\d{1}-[0-3]{1}\d{1}T[0-2]{1}\d{1}:[0-6]{1}\d{1}:[0-6]{1}\d{1}[+|-][0-1][0-9]:[0-5][0-9]$

test it here https://regexr.com/4gmi2

Upvotes: 0

Nicolas Henneaux
Nicolas Henneaux

Reputation: 12215

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

Upvotes: 22

Nick Gallimore
Nick Gallimore

Reputation: 1263

If you just want to match time zones use this:

^[+|-][0-1][0-9]:[0-5][0-9]$

The max is + or - 19:59 which is sufficient

Upvotes: 1

Shree Harsha S
Shree Harsha S

Reputation: 685

In this link we see the different ISO 8601 formats based on different values we would like to include.

For the example in the question, 2015-01-17T18:23:02+00:00, below regex should work.

[0-9]{4}-[0-9]{2}-[0-9]{2}T([0-9]{2}:){2}[0-9]{2}[+|-][0-9]{2}:[0-9]{2}

Here [+|-] is for possible time zone offsets.

Upvotes: 4

asontu
asontu

Reputation: 4659

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.

Upvotes: 79

Related Questions