Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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")
like image 746
Stephen H. Anderson Avatar asked Mar 30 '16 15:03

Stephen H. Anderson


2 Answers

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.

like image 179
Nate Barbettini Avatar answered Oct 20 '22 08:10

Nate Barbettini


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");
like image 21
Mikal Schacht Jensen Avatar answered Oct 20 '22 06:10

Mikal Schacht Jensen