是否可以为日期时间偏移量的反序列化指定偏移量 JSON.NET

本文关键字:偏移量 反序列化 JSON NET 是否 日期 时间 | 更新日期: 2023-09-27 17:56:23

以下语句打印"1/1/0001 4:00:00 PM -05:00"

Console.WriteLine(JsonConvert.DeserializeObject<DateTimeOffset>("'"0001-01-01T16:00:00'""));

这是因为当 json.net 将 DateTime 字符串(没有偏移量)反序列化为 DateTimeOffset 对象时,它会分配本地偏移量,在本例中为 -05:00。

如果我不想使用本地偏移量怎么办?有什么方法可以指定用于此反序列化的偏移量吗?

(用例是数据库服务器和 Web 服务器位于不同的时区,我需要具有区域未指定时间的传入请求在反序列化后具有数据库服务器的偏移量。

更新:我无法控制传入时间字符串的格式。我有一个数据传输对象类,该类具有 DateTimeOffset 属性,我需要将传入的时间数据存储到此属性。

是否可以为日期时间偏移量的反序列化指定偏移量 JSON.NET

要反序列化为的类型应与所需的数据匹配。 如果您不希望包含偏移量,请不要反序列化为DateTimeOffset。 相反,反序列化为DateTime。 它将为其.Kind财产提供DateTimeKind.Unspecified

您对 Web 服务器时区的了解与反序列化任务无关。 因此,事后单独应用。

// deserialize the json
DateTime dt = JsonConvert.DeserializeObject<DateTime>("'"2014-01-01T00:00:00'"");
// find your target time zone
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
// apply the time zone to determine the offset, and create the DateTimeOffset
DateTimeOffset dto = new DateTimeOffset(dt, tz.GetUtcOffset(dt));

更新

根据评论,如果您需要按照请求的方式进行此转换,则需要自定义 json 转换器。 这应该可以解决问题:

public class CustomDateTimeConverter : IsoDateTimeConverter
{
    private readonly string defaultTimeZoneId;
    public CustomDateTimeConverter(string defaultTimeZoneId)
    {
        this.defaultTimeZoneId = defaultTimeZoneId;
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (objectType != typeof (DateTimeOffset) && objectType != typeof (DateTimeOffset?))
            return base.ReadJson(reader, objectType, existingValue, serializer);
        var dateText = reader.Value.ToString();
        if (objectType == typeof(DateTimeOffset?) && string.IsNullOrEmpty(dateText))
            return null;
        if (dateText.IndexOfAny(new[] { 'Z', 'z', '+'}) == -1 && dateText.Count(c => c == '-') == 2)
        {
            var dt = DateTime.Parse(dateText);
            var tz = TimeZoneInfo.FindSystemTimeZoneById(this.defaultTimeZoneId);
            var offset = tz.GetUtcOffset(dt);
            return new DateTimeOffset(dt, offset);
        }
        return DateTimeOffset.Parse(dateText);
    }
}

然后,您可以在转换过程中将其连接起来:

var settings = new JsonSerializerSettings();
settings.DateParseHandling = DateParseHandling.None;
settings.Converters.Add(new CustomDateTimeConverter(defaultTimeZoneId: "Eastern Standard Time"));
DateTimeOffset dto = JsonConvert.DeserializeObject<DateTimeOffset>("'"2014-01-01T00:00:00'"", settings);

请务必使用有效的时区 ID。 不要使用固定偏移。

此外,如果您试图在没有日期的情况下打发时间,这将不是正确的方法。 这是一个完全不同的问题,传递0001-01-01日期不是一个好方法。 我很乐意在聊天中与您讨论。

如果原始字符串中有偏移量 (-8:00):

Console.WriteLine(JsonConvert.DeserializeObject<DateTimeOffset>("'"0001-01-01T16:00:00-08:00'""));

如果没有,请尝试此操作

var dateTime = JsonConvert.DeserializeObject<DateTime>("'"0001-01-01T16:00:00'"");
DateTimeOffset dto = new DateTimeOffset(dateTime, TimeSpan.FromHours(-8));