未指定TZ时将字符串解析为UTC DateTimeOffset

时间:2018-07-09 06:41:29

标签: c# json.net datetimeoffset

我正在开发一个简单的Web API客户端。我的模型中有一个show属性,我已将其指定为ExpiresOn

DateTimeOffset

我使用public class Model { public DateTimeOffset ExpiresOn { get; set; } } 从JSON字符串反序列化API响应。我注意到,由于我检索的JSON没有指定任何时区信息,因此JSON.Net将假定它是本地时间,并根据我的设置返回一个调整为UTC的JsonConvert.DeserializeObject<T>()。我尝试了不同的组合,但是似乎无法“强制” DateTimeOffset来读取字符串,就好像它是UTC一样。

最好有一个选项可以使用JsonConvert全局设置该设置,因为我要在多个位置进行类似的解析。

此外,我正在为ASP.Net Core 2.1进行编码,并且主机的tz设置为CEST(+02:00)。不能在主机上设置其他时区。

附录:

要解析的JsonConvert.DefaultSettings的示例为string。我尝试过"2018-07-09T11:22:33.45678"DateParseHandling的排列,但是都返回一个日期:DateTimeZoneHandling

很明显,反序列化器假定该字符串位于本地时间。因此,是否有一种方法可以像对待2018-07-09T11:22:33.45768+02:00中的AssumeUniversal一样对待它?

2 个答案:

答案 0 :(得分:1)

似乎DateTimeZoneHandlingDateTimeOffset不起作用。

作为解决方法,您必须定义一个JsonConverter来解决此问题:

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);
    }
}

然后像这样使用它:

public class Model
{
    [JsonConverter(typeof(DateTimeOffsetConverter))]
    public DateTimeOffset ExpiresOn { get; set; }
}

然后这样称呼它:

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);

您也可以在JsonSerializerSettings中定义JsonConvert.DefaultSettings,而不是每个转换调用。

答案 1 :(得分:0)

根据文档,您可以通过DateTimeZoneHandling传递JsonSerializerSettings

Here是该示例,尽管此处的示例用于序列化,但是您可以通过相同的设置进行反序列化,也可以查看this

示例:-

string jsonWithUtcTimeZone = JsonConvert.SerializeObject(flight, Formatting.Indented, new JsonSerializerSettings
{
    DateTimeZoneHandling = DateTimeZoneHandling.Utc
});

反序列化示例:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
};

var json = JsonConvert.SerializeObject(a, settings);

var newA = JsonConvert.DeserializeObject<A>(json, settings);