Stephen H. Anderson
Stephen H. Anderson

Reputation: 1068

How to parse and generate DateTime objects in ISO 8601 format

There is this SOAP web service that sends me datetime objects in the following format

2016-03-29T12:20:35.093-05:00

That is day 29 of March of year 2016. Hour: 12:20:35.093 (GMT-5).

I want to be able to create a DateTime object, like this:

DateTime.Now

and get the string representation in the format described above and also the inverse operation, create a DateTime from a string like the one given above.

I've tried the following in order to create the date:

new DateTime(2016, 3, 29, 12, 20, 35, 093, DateTimeKind.Utc)

However, I can't not see how to specifie GMT-5 there...

I don't know how to convert a DateTime to the specified string format, either.

Using Nate's code I'm doing the following:

var d = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-3));

FormatIso8601(d)

However this call is returning: "2016-03-29T15:20:35Z" instead of :

"2016-03-29T12:20:35.093-03:00"

which is what I actually need.

I think this works:

        d.ToString("yyyy-MM-ddTHH:mm:ss.fffzzz")

Upvotes: 18

Views: 33900

Answers (3)

Tim P.
Tim P.

Reputation: 2942

Simple answer: DateTime.UtcNow.ToString("o")

Upvotes: 1

Mikal Schacht Jensen
Mikal Schacht Jensen

Reputation: 547

A simpler way is to use the ToString method on DateTimeOffset with the "o" argument. This automatically prints the date in ISO8601 format

DateTimeOffset.Now.ToString("o");

The static parse method is also capable of correctly parsing a date in ISO8601 format.

DateTimeOffset.Parse("2016-25-12T20:45:30.3124+01:00");
DateTimeOffset.Parse("2016-25-12T20:45:30.3124Z");

Upvotes: 25

Nate Barbettini
Nate Barbettini

Reputation: 53600

The format you're describing is ISO 8601.

Since you're working with timestamps that inclulde a time zone component, I'd strongly recommend using DateTimeOffset instead of DateTime. It makes things so much easier!

To create a DateTimeOffset for a given date, time, and time zone offset, use this syntax:

var date = new DateTimeOffset(2016, 3, 29, 12, 20, 35, 93, TimeSpan.FromHours(-5));
// March 29, 2016 at 12:20:35.93 GMT-5

This code will format a DateTimeOffset as ISO 8601:

public static string FormatIso8601(DateTimeOffset dto)
{
    string format = dto.Offset == TimeSpan.Zero
        ? "yyyy-MM-ddTHH:mm:ss.fffZ"
        : "yyyy-MM-ddTHH:mm:ss.fffzzz";

    return dto.ToString(format, CultureInfo.InvariantCulture);
}

And, to parse a string back to a DateTimeOffset:

public static DateTimeOffset ParseIso8601(string iso8601String)
{
    return DateTimeOffset.ParseExact(
        iso8601String,
        new string[] { "yyyy-MM-dd'T'HH:mm:ss.FFFK" },
        CultureInfo.InvariantCulture,
        DateTimeStyles.None);
}

If you must get back to a DateTime you can get this from the DateTimeOffset.UtcDateTime property.

Upvotes: 30

Related Questions