Reputation: 1225
I am developing a simple web API client. On of my models has a ExpiresOn
property that I have specified as a DateTimeOffset
.
public class Model {
public DateTimeOffset ExpiresOn { get; set; }
}
I deserialise the API reponse from a JSON string using JsonConvert.DeserializeObject<T>()
. I have noticed that since the JSON I retrieve doesn't specify any time zone information, JSON.Net will assume it's in local time and return me a DateTimeOffset
adjusted to UTC, as per my settings. I have tried different combinations but I cannot seem to 'force' JsonConvert
to read the string as if it were UTC.
Preferably, there would be an option to set that setting globally using JsonConvert.DefaultSettings
as I have similar parsing to be done in several locations.
Also, I am coding for ASP.Net Core 2.1, and my host's tz is set to CEST (+02:00). Setting a different time zone on the host is not an options.
Addendum:
An example of string
to parse would be "2018-07-09T11:22:33.45678"
. I've tried permutations of DateParseHandling
and DateTimeZoneHandling
but all return a date: 2018-07-09T11:22:33.45768+02:00
.
Obviously the deserialiser assumes that the string is in local time. Hence, is there a way to have it treat it as AssumeUniversal
would in DateTimeOffset.TryParse
?
Upvotes: 2
Views: 1529
Reputation: 1066
It seems like DateTimeZoneHandling
doesn't work for DateTimeOffset
.
As a workaround you would have to define a JsonConverter
that circumvents this problem:
public class DateTimeOffsetConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTimeOffset);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null) return null;
DateTime dateTime = (DateTime)reader.Value;
return new DateTimeOffset(dateTime);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
}
Then use it like this:
public class Model
{
[JsonConverter(typeof(DateTimeOffsetConverter))]
public DateTimeOffset ExpiresOn { get; set; }
}
And then call it like this:
var str = "{\"ExpiresOn\":\"2018-07-09T11:22:33.45678\"}";
Model test = JsonConvert.DeserializeObject<Model>(str, new JsonSerializerSettings()
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
DateParseHandling = DateParseHandling.DateTime
});
Assert(test.ExpiresOn.Offset.Ticks == 0);
You can also define the JsonSerializerSettings
in JsonConvert.DefaultSettings
instead of every conversion call.
Upvotes: 1
Reputation: 4024
According to the documentation, you can pass DateTimeZoneHandling
through JsonSerializerSettings
Here is the example for that though example here is for serializing but you can pass same settings for deserializing also have a look at this
Example:-
string jsonWithUtcTimeZone = JsonConvert.SerializeObject(flight, Formatting.Indented, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});
Deserialization Example:
JsonSerializerSettings settings = new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
};
var json = JsonConvert.SerializeObject(a, settings);
var newA = JsonConvert.DeserializeObject<A>(json, settings);
Upvotes: 0