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.
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.
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.
"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.
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.
using System.Globalization;
DateTime d;
DateTime.TryParseExact(
"2010-08-20T15:00:00",
"s",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal, out d);
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
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...
AssumeUniversal
to AdjustToUniversal
.
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"));
DateTime.ParseExact(...)
allows you to tell the parser what each character represents.
Success story sharing
DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);
seems to work nicely.DateTimeStyles.RoundtripKind?
MSDN description is blank.2018-06-19T14:56:14.123Z
is parsed as local time, not UTC. I useCultureInfo.InvariantCulture
instead of null.DateTimeStyles.RoundTripKind
, see stackoverflow.com/q/39572395/2014893