How to create a .NET DateTime from ISO 8601 format

2019-01-01 13:53发布

问题:

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.

回答1:

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.



回答2:

using System.Globalization;

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


回答3:

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.



回答4:

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


回答5:

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



回答6:

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


回答7:

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