ChatGPT解决这个技术问题 Extra ChatGPT

How to create a .NET DateTime from ISO 8601 format

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.

possible duplicate of Convert String to Date in .NET
@abatishchev, and that is why it is not a duplicate. The answer in the "duplicate" does not handle 8601.
Yes this is not a duplicate. This question is specific to parsing the ISO 8601 format.

P
Peter Mortensen

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.


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
A
Alexey Biryukov

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.


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.
a
abatishchev
using System.Globalization;

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

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
P
Peter Mortensen

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

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!
A
AlexB

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...


This worked for me, but I also had to change AssumeUniversal to AdjustToUniversal.
Z
Zar Shardan

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"));

a
abatishchev

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


Anyone down-voting this, please say why you do so. Even bad answers are good for learning.