【问题标题】:How to add timezone offset to JSON.NET serialization?如何将时区偏移量添加到 JSON.NET 序列化?
【发布时间】:2014-08-03 12:15:32
【问题描述】:

我的 DateTimePicker 绑定到属性:

    picker.DataBindings.Add("Value", this, "EventDate");
    ...
    private DateTime eventDate;
    public DateTime EventDate
    {
        get
        {
            var offset = TimeZoneInfo.Local.GetUtcOffset(eventDate);
            string json = JsonConvert.SerializeObject(eventDate, Formatting.Indented);
            Console.WriteLine("get: {0} --- {1}", json, offset);
            return eventDate;
        }
        set
        {
            var offset = TimeZoneInfo.Local.GetUtcOffset(value);
            string json = JsonConvert.SerializeObject(value, Formatting.Indented);
            Console.WriteLine("set: {0} --- {1}", json, offset);
            eventDate = value;
        }
    }

每当数据绑定设置属性时,我得到以下结果:

set: "2015-08-03T16:06:59" --- 04:00:00
get: "2015-08-03T16:06:59" --- 04:00:00

get/set 中的代码仅用于调试目的。整个类与 EventDate 属性一起序列化。

如何修改 DateTime 变量和/或 json 序列化程序以包含时区偏移,例如:

"2014-08-03T16:06:59.8708232+04:00"

奇怪的是,如果我创建全新的 DateTime 对象并分配给 DateTime.Now 而不绑定,JSON.NET 将为其附加时区偏移量。不知道有什么区别。

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    您是否尝试过输入DateTimeOffset 而不是DateTime?这是带有时区信息的类型。

    var example = new
    {
        Now = DateTimeOffset.Now,
        UtcNow = DateTimeOffset.UtcNow,
        Sometime = new DateTimeOffset(2014, 10, 11, 1, 4, 9, new TimeSpan(8, 0, 0)),
        FromDateTime = new DateTimeOffset(new DateTime(2010, 1, 1)),
    };
    string json = JsonConvert.SerializeObject(example, Formatting.Indented);
    Console.WriteLine(json);
    

    给我:

    {
      "Now": "2014-08-03T22:08:47.8127753+08:00",
      "UtcNow": "2014-08-03T14:08:47.8137754+00:00",
      "Sometime": "2014-10-11T01:04:09+08:00",
      "FromDateTime": "2010-01-01T00:00:00+08:00"
    }
    

    编辑 - 替代方式

    您注意到 DateTime.Now 在 JSON 中有时区偏移,而手动创建的 DateTime 没有。这是因为DateTime.NowKind 等于DateTimeKind.Local 而另一个有DateTimeKind.Unspecified,而JSON.NET 只是以不同的方式处理它们。

    所以另一种方法是:

    var product2 = new
    {
        Now = DateTime.Now,
        Sometime = new DateTime(2014, 10, 11, 0, 0, 0),
        SometimeLocal = new DateTime(2014, 10, 11, 0, 0, 0, DateTimeKind.Local),
        SometimeUtc = new DateTime(2014, 10, 11, 0, 0, 0, DateTimeKind.Utc)
    };
    
    string json2 = JsonConvert.SerializeObject(product2, Formatting.Indented);
    
    Console.WriteLine(json2);
    

    哪些输出:

    {
      "Now": "2014-08-03T23:39:45.3319275+08:00",
      "Sometime": "2014-10-11T00:00:00",
      "SometimeLocal": "2014-10-11T00:00:00+08:00",
      "SometimeUtc": "2014-10-11T00:00:00Z"
    }
    

    EDIT2 - 用于数据绑定

    好的,你使用数据绑定。然后您可以更新您的设置器以自动转换:

    picker.DataBindings.Add("Value", this, "EventDate");
    ...
    private DateTimeOffset eventDate;
    public DateTime EventDate
    {
        get { return eventDate.LocalDateTime; }
        set { eventDate = new DateTimeOffset(value); }
    }
    

    然后就可以使用eventDate序列化成JSON了。

    或者设置Kind:

    picker.DataBindings.Add("Value", this, "EventDate");
    ...
    private DateTime eventDate;
    public DateTime EventDate
    {
        get { return eventDate; }
        set
        {
            // Create a copy of DateTime and set Kind to Local since Kind is readonly
            eventDate = new DateTime(value.Ticks, DateTimeKind.Local);
        }
    }
    

    两者都应该工作。

    【讨论】:

    • 我不确定我是否可以使用解决方案,因为DateTimePicker 不适合DateTimeOffset
    • @Pablo 你在用什么DateTimePicker?你能在回调中将DateTime 转换为DateTimeOffset 吗?
    • 使用来自 4.0 Dot Net 框架的常规 Windows 窗体 DateTimePicker。不知道你指的是什么回调..
    • 此外,我不明白为什么 DateTime.Now 会产生所需的结果,但是绑定我的 DateTime 对象不足以让 JSON.NET 指定 TZ。
    • @Pablo 关于DateTime.Now 和手动构造的DateTime 的第二个问题,区别在于DateTime.NowKind 等于DateTimeKind.Local,而另一个是DateTimeKind.Unspecified。所以这是将这些信息放在 JSON 中的另一种方法。请查看我的更新答案。
    【解决方案2】:

    我用这个。

    效果很好。

    JsonConvert.SerializeObject(object, new JsonSerializerSettings()
    {
        DateFormatHandling = DateFormatHandling.IsoDateFormat,
        DateTimeZoneHandling = DateTimeZoneHandling.Local
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多