未指定 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"
。我已经尝试了 DateParseHandling
和 DateTimeZoneHandling
的排列,但所有 return 都是一个日期:2018-07-09T11:22:33.45768+02:00
。
显然反序列化器假设字符串是本地时间。因此,有没有办法让它像 AssumeUniversal
在 DateTimeOffset.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
而不是每次转换调用。
我正在开发一个简单的网络 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"
。我已经尝试了 DateParseHandling
和 DateTimeZoneHandling
的排列,但所有 return 都是一个日期:2018-07-09T11:22:33.45768+02:00
。
显然反序列化器假设字符串是本地时间。因此,有没有办法让它像 AssumeUniversal
在 DateTimeOffset.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
而不是每次转换调用。