198

I've found how to turn a DateTime into an ISO 8601 format, but nothing on how to do the reverse in C#.

I have 2010-08-20T15:00:00Z, and I want to turn it into a DateTime object.

I could separate the parts of the string myself, but that seems like a lot of work for something that is already an international standard.

3
  • 1
    possible duplicate of Convert String to Date in .NET Commented Aug 24, 2010 at 12:02
  • 9
    @abatishchev, and that is why it is not a duplicate. The answer in the "duplicate" does not handle 8601. Commented Nov 3, 2016 at 15:30
  • 4
    Yes this is not a duplicate. This question is specific to parsing the ISO 8601 format. Commented Feb 13, 2020 at 4:59

7 Answers 7

222

This solution makes use of the DateTimeStyles enumeration, and it also works with Z.

DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);

This prints the solution perfectly.

Sign up to request clarification or add additional context in comments.

12 Comments

The edited solution of DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind); seems to work nicely.
Anyone wish to elaborate on this DateTimeStyles.RoundtripKind? MSDN description is blank.
it seems this question was edited to reflect a better answer but since @MamtaD overwrote the original answer, the comments become very misleading. At the beginning I was not sure that the answer is correct due to the comments on top but then I realized that incorrect answer was latter replaced with correct one
Doesn't work for me with fractional digits. 2018-06-19T14:56:14.123Z is parsed as local time, not UTC. I use CultureInfo.InvariantCulture instead of null.
For more info on DateTimeStyles.RoundTripKind, see stackoverflow.com/q/39572395/2014893
|
50

Although MSDN says that "s" and "o" formats reflect the standard, they seem to be able to parse only a limited subset of it. Especially it is a problem if the string contains time zone specification. (Neither it does for basic ISO8601 formats, or reduced precision formats - however this is not exactly your case.) That is why I make use of custom format strings when it comes to parsing ISO8601. Currently my preferred snippet is:

static readonly string[] formats = { 
    // Basic formats
    "yyyyMMddTHHmmsszzz",
    "yyyyMMddTHHmmsszz",
    "yyyyMMddTHHmmssZ",
    // Extended formats
    "yyyy-MM-ddTHH:mm:sszzz",
    "yyyy-MM-ddTHH:mm:sszz",
    "yyyy-MM-ddTHH:mm:ssZ",
    // All of the above with reduced accuracy
    "yyyyMMddTHHmmzzz",
    "yyyyMMddTHHmmzz",
    "yyyyMMddTHHmmZ",
    "yyyy-MM-ddTHH:mmzzz",
    "yyyy-MM-ddTHH:mmzz",
    "yyyy-MM-ddTHH:mmZ",
    // Accuracy reduced to hours
    "yyyyMMddTHHzzz",
    "yyyyMMddTHHzz",
    "yyyyMMddTHHZ",
    "yyyy-MM-ddTHHzzz",
    "yyyy-MM-ddTHHzz",
    "yyyy-MM-ddTHHZ"
    };

public static DateTime ParseISO8601String ( string str )
{
    return DateTime.ParseExact ( str, formats, 
        CultureInfo.InvariantCulture, DateTimeStyles.None );
}

If you don't mind parsing TZ-less strings (I do), you can add an "s" line to greatly extend the number of covered format alterations.

2 Comments

I would add "yyyyMMdd" in the formats array for accuracy reduced to days, as this is sometimes the case when an RFC 5545 RRULE will rely on a DTSTART to provide the time.
Using K allows you to roll your different time-zone handlings together. I've a more extensive variant at stackoverflow.com/a/31246449/400547 but it's if anything too extensive (accepts stuff that's valid ISO 8601 but not used in the more common profiles) but it does show how K can reduce the size by a third.
26
using System.Globalization;

DateTime d;
DateTime.TryParseExact(
    "2010-08-20T15:00:00",
    "s",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeUniversal, out d);

7 Comments

produces False and d ~~> "1/1/0001 12:00:00 AM" in LinqPad :(
@Reb: "2010-08-20T15:00:00" and "s", if no "Z" on the end
corrected :) the Z shows up in all my samples (which happen to come from various GPS units and GPX files)
found out in another ISO 8601 reference that the "Z" stands for Zone -- as in Time Zone.
Z actually stands for Zulu time or UTC. en.wikipedia.org/wiki/ISO_8601#UTC
|
24

Here is one that works better for me (LINQPad version):

DateTime d;
DateTime.TryParseExact(
    "2010-08-20T15:00:00Z",
    @"yyyy-MM-dd\THH:mm:ss\Z",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeUniversal, 
    out d);
d.ToString()

produces

true
8/20/2010 8:00:00 AM

2 Comments

Currently using this to verify in my unit tests that all strings I expect to be dates are of Iso8601 format. Thanks!
Why does this return a timestamp not in UTC?! Quite a large violation of the Principle of Least Astonishment since "Invariant culture" with "AssumeUniversal" should not be doing this because DST differs so wildly across the world, so returning in your local prevailing time zone might introduce bugs if you start running the code on a server with different settings!
11

It seems important to exactly match the format of the ISO string for TryParseExact to work. I guess Exact is Exact and this answer is obvious to most but anyway...

In my case, Reb.Cabin's answer doesn't work as I have a slightly different input as per my "value" below.

Value: 2012-08-10T14:00:00.000Z

There are some extra 000's in there for milliseconds and there may be more.

However if I add some .fff to the format as shown below, all is fine.

Format String: @"yyyy-MM-dd\THH:mm:ss.fff\Z"

In VS2010 Immediate Window:

DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d);

true

You may have to use DateTimeStyles.AssumeLocal as well depending upon what zone your time is for...

2 Comments

This worked for me, but I also had to change AssumeUniversal to AdjustToUniversal.
This is what works in my situation: 1. DateTime dateTime //my Datetime value is something like 2023-11-11T22:56:45.245; 2. I used XmlConvert classs to convert my dateTime to string in a specified format as shown below: string dates = XmlConvert.ToString(dateTime , "yyyy-MM-dd HH:mm:ss.fffZ"); 3. Then this last step to convert it to ISO 8601 DateTime date = DateTime.Parse(dates, null, DateTimeStyles.RoundtripKind). I hope this helps someone.
11

This works fine in LINQPad4:

Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z"));
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00"));
Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00"));

Comments

-1

DateTime.ParseExact(...) allows you to tell the parser what each character represents.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.