关于c#:如何为JSON.NET序列化添加时区偏移量?

How to add timezone offset to JSON.NET serialization?

我的DateTimePicker绑定到属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    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;
        }
    }

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

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

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

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

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

奇怪的是,如果我创建全新的DateTime对象并在没有绑定的情况下分配给DateTime.Now,JSON.NET将向其附加时区偏移量。 无法弄清楚有什么区别。


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

1
2
3
4
5
6
7
8
9
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);

给我:

1
2
3
4
5
6
{
 "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.Now Kind等于DateTimeKind.Local而另一个DateTimeKind.Unspecified,而JSON.NET只是以不同的方式处理它们。

所以另一种方法是:

1
2
3
4
5
6
7
8
9
10
11
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);

哪个输出:

1
2
3
4
5
6
{
 "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 - 用于数据绑定

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

1
2
3
4
5
6
7
8
picker.DataBindings.Add("Value", this,"EventDate");
...
private DateTimeOffset eventDate;
public DateTime EventDate
{
    get { return eventDate.LocalDateTime; }
    set { eventDate = new DateTimeOffset(value); }
}

然后,您可以使用eventDate序列化为JSON。

或者设置Kind

1
2
3
4
5
6
7
8
9
10
11
12
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);
    }
}

两者都应该有效。


我用这个。

它工作得很好。

1
2
3
4
5
JsonConvert.SerializeObject(object, new JsonSerializerSettings()
{
    DateFormatHandling = DateFormatHandling.IsoDateFormat,
    DateTimeZoneHandling = DateTimeZoneHandling.Local
});