There are many SO questions and answers regarding parsing of ISO8601 date/times in .NET and C#. However, there doesn't seem to be a 'definitive' answer anywhere, i.e. an answer that presents a formally correct ISO8601 parser that would correctly parse all of the possible format variants within ISO8601 and that would disallow non-ISO8601 variants.
This SO answer is the closest match so far...
Okay. Let's start with the limitations you are placing on ISO 8601 yourself:
That leaves us with less than half of the ISO 8601 formats to support, and resolves the ambiguous case as it is ambiguous between a date-only and a time-only meaning.
Let's start with those that we could handle with
DateTime.ParseExact
:It would be nice to identify those dates with time zones that matched the local time, but it gets fiddly fast.
If you don't want to support the two-digit years allowed by ISO 8601:2000 and earlier but prohibited in ISO 8601:2004 then remove all of the strings with "yy" rather than "yyyy" above:
This still leaves us with the problem of dates in the form
2009-W53-7
for the 3rd of January 2010:Finally you have to decide what to do if you receive a date and time with a greater precision than 100ns:
Now while we lose precision with a string like
2015-03-29T12:53:20.238748294819293021383+01:00
we can still parse it as well as could be feasible.Now we need to catch
24:00:00
as a valid time, and then catch valid times like2015-06-30T23:59:60
(though I don't check against2014-06-30T23:59:60
which never happened, as that would need a constantly updated database of leap-seconds):All of this is a lot of work, though kinda fun. And we still aren't touching on maintaining timezone (not a tricky change to the above, with
DateTimeOffset
) time-only strings (should return aTimeSpan
), durations (should also return aTimeSpan
), periods or repeating periods.Meanwhile, ISO 8601 is intended to be used to define one or more profiles which in turn define one or more subsets of the allowed formats, perhaps with other rules. Generally we want to program to one of these profiles rather than to ISO 8601 generally. For example, the above is useless for parsing web date-times because it accepts
2009-W53-7
for the 3rd of January 2010 which is correct ISO 8601 handling, but not allowed by the web-datetime profile of ISO 8601.