8

I am receiving a JSON string that contains a date that looks like this: 2015-07-09T08:38:49-07:00 where the last part is the timezone. Is there a standard way to convert this to a DateTimeOffset?

Here is what I have so far:

var olu = JsonConvert.DeserializeObject<OneLoginUser>(jToken.ToString(), new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd'T'HH:mm:sszzz" });

This doesn't deserialize any of the dates. I've tried using -Z and hh:mm for the timezone data, but I can't seem to deserialize any of the dates.

For reference, this is from OneLogin, a SSO provider. Here's a link to the user documentation. Notice the bit about the dates at the top.

joelforsyth
  • 836
  • 1
  • 11
  • 28
  • 3
    convert to a string then use DateTimeOffset rather than DateTime http://stackoverflow.com/questions/10293362/c-sharp-string-to-datetime-with-timezone – C. Knight Nov 23 '15 at 19:33
  • Why do you have single quotes in your format string? – Ben Nov 23 '15 at 19:39
  • @C.Knight - Is it possible to use a JsonSerializerSetting for that? I see that DateTimeOffsetConverter but I'm not sure how to set the formatting. – joelforsyth Nov 23 '15 at 19:46
  • @Ben I'm pretty sure that's how you specify a literal character in a format string. Also, this format string is very very close to the "O" general string, but is missing the fractions of a second, hence the need for a custom format string. – CodeMonkey1313 Nov 23 '15 at 19:50
  • 1
    @joelforsyth Not sure I'm afraid. My gut feeling is that you'll need to deserialise it a string and then convert it to DateTime. – C. Knight Nov 23 '15 at 19:55
  • 3
    Works fine for me. You don't need to bother with the converter, Json.Net already knows how to deserialize this date format. Fiddle: https://dotnetfiddle.net/wtTIup – Brian Rogers Nov 23 '15 at 22:26
  • @BrianRogers - It was ultimately your fiddle that helped me solve the issue, thanks. – joelforsyth Nov 24 '15 at 14:30
  • @joelforsyth Glad you got it working. – Brian Rogers Nov 24 '15 at 16:37

2 Answers2

13

That is a standard ISO 8601 extended format timestamp with offset, also covered by RFC 3339. There's nothing special about it.

DateTimeOffset.Parse("2015-07-09T08:38:49-07:00")

Or

DateTimeOffset.ParseExact("2015-07-09T08:38:49-07:00", "yyyy-MM-dd'T'HH:mm:sszzz",
                                                       CultureInfo.InvariantCulture)

With JSON.Net, the defaults should work well. No need to specify anything special.

JsonConvert.DeserializeObject<DateTimeOffset>("\"2015-07-09T08:38:49-07:00\"")

The fiddle Brian posted in the question comments shows that it works when deserializing a larger object. If you're still not getting it to work, perhaps you could edit your question to show the specific JSON you're trying to deserialize and the object structure you're putting it into.

One thing I noticed about your code, you show the json coming from jToken.ToString(), so somewhere you must have previously parsed using JObject.Parse. It's a little strange to do that, just to convert back to json and deserialize. Either go directly from the json string to the entity using JsonConvert.DeserializeObject, or use jToken.ToObject<OneLoginUser>() if you're already starting with jToken for some other reason. No need to mix both APIs, and it's possible you're loosing the date/time information in the process depending on what your settings are.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
1

Try a format string like this:

"yyyy-MM-dd'T'hh:mm:ss%K"

As you can see from the example, this parses better than what you specified (the duplicate hh:mm is probably screwing things up).

string input = "2015-07-09T08:38:49-07:00";
DateTime dt = DateTime.ParseExact(input, "yyyy-MM-dd'T'hh:mm:ss%K", System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine(input);
Console.WriteLine(dt.ToString());
CodeMonkey1313
  • 15,717
  • 17
  • 76
  • 109
  • This may work when parsing, but I have to deserialize it. As @C.Knight noted I may have to make it a string and parse after. – joelforsyth Nov 23 '15 at 20:01
  • @joelforsyth my point was that you could use the updated format string in your deserialization method (assuming the method works otherwise). Having the second "hh:mm" is likely causing the deserialization and parsing of the data to error out. – CodeMonkey1313 Nov 23 '15 at 20:29
  • It looks like `zzz` is the format used for timezone, but I can't get it to work. Ref: http://stackoverflow.com/questions/7003373/how-to-get-datetime-now-in-yyyy-mm-ddthhmmsstzd-format-using-c-sharp – joelforsyth Nov 23 '15 at 21:15
  • I did try your format, along with just about every combination I could think of. – joelforsyth Nov 23 '15 at 21:16
  • It wouldn't be `%K`, it would just be `K`, but that's when deserializing to a `DateTime`. The OP asked for deserialization to `DateTimeOffset` - which would be best match for this type of input anyway. – Matt Johnson-Pint Nov 23 '15 at 23:45