flashy
flashy

Reputation: 41

Ignoring timezone offset when deserializing datetime

I have a datetime in my json formatted like so:

"EventDate": "2017-05-05T11:35:44-07:00",

This file was created in Pacific time, while my server is in eastern time. When I deserialize this file back into my object, the time is converted to a datetime of 2017-05-05 2:35:44PM. The problem is that I need the ORIGINAL time, 11:35:44AM.

I have already fixed the problem at the source, but I still need a way to handle all these files that I have. Is there a way to just deserialize this field to the exact datetime specified without the offset? I checked DateTimeZoneHandling settings but none of them produced the effect I want.

Upvotes: 2

Views: 4629

Answers (1)

Mark Embling
Mark Embling

Reputation: 12841

I agree with AWinkle in the comments above - the best way would be to deserialise as a DateTimeOffset instead of a DateTime - that way, you can display it however you wish.

That said, I used that idea for a possible approach which could be to use a custom JSON type converter to get the timezone-stripping behaviour you're afer. Here's a quick sample I knocked up which seems to do as you ask.

/// <summary>
/// Custom converter for returning a DateTime which has been stripped of any time zone information
/// </summary>
public class TimezonelessDateTimeConverter : DateTimeConverterBase {
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        throw new NotImplementedException("An exercise for the reader...");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        // We'll make use of Json.NET's own IsoDateTimeConverter so 
        // we don't have to re-implement everything ourselves.
        var isoConverter = new IsoDateTimeConverter();

        // Deserialise into a DateTimeOffset which will hold the 
        // time and the timezone from the JSON.
        var withTz = (DateTimeOffset)isoConverter.ReadJson(reader, typeof(DateTimeOffset), existingValue, serializer);

        // Return the DateTime component. This will be the original 
        // datetime WITHOUT timezone information.
        return withTz.DateTime;
    }
}

This can then be used like this:

/// <summary>
/// Nonsense class just to represent your data. You'd implement the JsonConverter
/// attribute on your own model class.
/// </summary>
public class Sample {
    [JsonConverter(typeof(TimezonelessDateTimeConverter))]
    public DateTime EventDate { get; set; }
}

//
// And a sample of the actual deserialisation...
///

var json = "{ \"EventDate\": \"2017-05-05T11:35:44-07:00\" }";
var settings = new JsonSerializerSettings {
    DateParseHandling = DateParseHandling.DateTimeOffset
};
var deserialised = JsonConvert.DeserializeObject<Sample>(json, settings);
Console.WriteLine(deserialised.EventDate);

This will output 05/05/2017 11:35:44.

This is definitely not the most robust approach and I'm almost certain there are things I've not accounted for - and it probably ought to be bit more thoroughly tested to make sure there isn't some horrible side effect. However hopefully it's a starting point of a possible solution and points you in the right direction.

P.S. if you also serialise back to JSON, you'll need to implement the WriteJson method too. I didn't do that one, so right now it only goes one direction.

Upvotes: 4

Related Questions