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

Parse String as UTC DateTimeOffset When No TZ Specified

我正在开发一个简单的网络 API 客户端。我的模型中有一个 ExpiresOn 属性,我指定为 DateTimeOffset

public class Model {
    public DateTimeOffset ExpiresOn { get; set; }
}

我使用 JsonConvert.DeserializeObject<T>() 从 JSON 字符串反序列化 API 响应。我注意到,由于我检索的 JSON 没有指定任何时区信息,JSON.Net 将假定它是当地时间,而 return 我将 DateTimeOffset 调整为 UTC,根据我的设置。我尝试了不同的组合,但我似乎无法 'force' JsonConvert 读取字符串,就好像它是 UTC 一样。

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

此外,我正在为 ASP.Net Core 2.1 编码,我的主机的 tz 设置为 CEST (+02:00)。在主机上设置不同的时区不是一个选项。

附录:

要解析的 string 的示例是 "2018-07-09T11:22:33.45678"。我已经尝试了 DateParseHandlingDateTimeZoneHandling 的排列,但所有 return 都是一个日期:2018-07-09T11:22:33.45768+02:00

显然反序列化器假设字符串是本地时间。因此,有没有办法让它像 AssumeUniversalDateTimeOffset.TryParse 中那样对待它?

根据文档,您可以通过 JsonSerializerSettings

传递 DateTimeZoneHandling

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

示例:-

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

DateTimeZoneHandling 似乎不适用于 DateTimeOffset

作为解决方法,您必须定义一个 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);

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