问题描述
我在 C# 中使用 Json.net 7.0.1 来使用休息 API.问题在于 API 在其 JSON 响应中使用的日期格式.它看起来像这样:
I am using Json.net 7.0.1 in C# to consume a rest API. The trouble is with the date format the API uses in its JSON response. It looks like this:
/Date(1445301615000-0700)/
这意味着表示 2015-10-19 17:40:15 的 UTC 时间
That is meant to represent a UTC time of 2015-10-19 17:40:15
如果将 1445301615000 插入 纪元时间转换器,您会看到它是 2015-10-20 00:40:15 .所以比 UTC 早 7 小时.然后它们包括 -0700 大概是为了将其抵消回 UTC.因此,为了给我一个 UTC 时间,他们向我发送了 UTC+7-0700.他们为什么这样做我不知道,但我无法改变.
If you plug 1445301615000 into an epoch time converter, you see that it is 2015-10-20 00:40:15 . So it is 7 hours ahead of UTC. Then they include the -0700 presumably to offset that back to UTC. So, in an effort to give me a UTC time, they are sending me UTC+7-0700. Why they do it this way I have no idea, but I can't change that.
我的问题是,如何最好地让 Json.NET 解析该日期字符串并得出 2015-10-19 17:40:15
UTC 的 DateTime.我可以编写一个自定义的 JsonConverter 来劫持值并手动操作它,但我想知道是否有更原生的方法.
My question is, how best to make Json.NET parse that date string and come up with a DateTime of 2015-10-19 17:40:15
UTC. I can write a custom JsonConverter to hijack the value and manipulate it manually, but I was wondering if there is a more native method.
我尝试将 JsonSerializerSettings DateTimeZoneHandling
属性更改为所有不同的值.将其设置为 Utc 只会忽略时区偏移,产生 2015-10-20 00:40:15
.将其设置为 Local、Unspecified 或 RoundtripKind all yield 2015-10-19 20:40:15
,我认为这是因为我的本地时区是 UTC-4,所以它正在尝试应用该调整到 2015-10-20 00:40 的主要日期值.
I have tried changing the JsonSerializerSettings DateTimeZoneHandling
property to all its different values. Setting it to Utc just ignores the time zone offset, yielding 2015-10-20 00:40:15
. Setting it to Local, Unspecified, or RoundtripKind all yield 2015-10-19 20:40:15
, which I believe is because my local timezone is UTC-4, so it is trying to apply that adjustment to the main date value of 2015-10-20 00:40.
我还考虑使用 DateFormatString
属性来表示预期的日期字符串格式.但我找不到正确的 格式字符串字符 来表示这个时代-偏移格式.
I also considered using the DateFormatString
property to represent the expected date string format. But I could not find the right format string characters to represent this epochtime-offset format.
这是一个简化的例子:
Person person;
string json = @"{ 'Name': 'John',
'LastSeen':'/Date(1445301615000-0700)/' }"; // 1445301615000 = 2015-10-20 00:40:15
person = JsonConvert.DeserializeObject<Person>(json);
Console.WriteLine(person.LastSeen); // 10/19/2015 8:40:15 PM Kind = Local
person = JsonConvert.DeserializeObject<Person>(json, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat });
Console.WriteLine(person.LastSeen); // 10/19/2015 8:40:15 PM Kind = Local
person = JsonConvert.DeserializeObject<Person>(json, new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc });
Console.WriteLine(person.LastSeen); // 10/20/2015 00:40:15 PM Kind = Utc
// In all three, the -0700 portion is being ignored. I'd like person.LastSeen to be 10/19/2015 17:40:15.
再次,我可以知道 API 将给我 UTC+7 并自己进行调整以获得真正的 UTC.但我想知道 Json.NET 是否有本地方式来处理这种类型的日期字符串.
Again, I could just know that the API is going to give me UTC+7 and do the adjustment myself to get real UTC. But I wondered if Json.NET has a native way to handle this type of date string.
推荐答案
/日期(1445301615000-0700)/
/Date(1445301615000-0700)/
这意味着表示 2015-10-19 17:40:15 的 UTC 时间
That is meant to represent a UTC time of 2015-10-19 17:40:15
对不起,这不正确.UTC 时间为 2015-10-20 00:45:15
.您的值对应于 本地 时间,在那个时刻具有 -07:00
偏移的时区.
Sorry, that's incorrect. The UTC time is 2015-10-20 00:45:15
. Your value corresponds to the local time, in a time zone with a -07:00
offset at that instant.
在这种 screwy 格式中,时间戳部分仍然完全基于 UTC.偏移量是额外的信息.它不会更改时间戳.您可以提供不同的偏移量,或者完全省略它,它仍然是同一时刻.
In this screwy format, the timestamp portion is still based solely on UTC. The offset is extra information. It doesn't change the timestamp. You can give a different offset, or omit it entirely and it's still the same moment in time.
关于时间点,以下所有内容都是等效的.
All of the following are equivalent, with regard to point-in-time.
/Date(1445301615000-0700)/
/Date(1445301615000)/
2015-10-20T00:40:15Z
2015-10-19T17:40:15-07:00
请注意,在 ISO 格式中,偏移量会改变值,但在 MS 格式中不会.
Notice that in in the ISO format, the offset does change the value, but in the MS format it does not.
最好不要使用这种格式,因为 ISO8601 是 JSON 的明智选择.但是,如果您坚持使用它,那么最好不要将其反序列化为 DateTime
.相反,请使用 DateTimeOffset
.
It would be best if you did not use this format, as ISO8601 is a much saner choice for JSON. However if you're stuck with it, then it's best not to deserialize it to a DateTime
. Instead, use a DateTimeOffset
.
考虑:
string s = ""/Date(1445301615000-0700)/"";
DateTime dt = JsonConvert.DeserializeObject<DateTime>(s);
Console.WriteLine(dt.Kind); // Local
这样不好.基本上,如果有 any 偏移,它会认为这是您的本地时区,可能是,但可能不是.
That's no good. basically, if there is any offset, it thinks it's your local time zone, which it might be, but it might not be.
string s = ""/Date(1445301615000)/"";
DateTime dt = JsonConvert.DeserializeObject<DateTime>(s);
Console.WriteLine(dt.Kind); // Utc
这没关系,但您忘记了当地时间.
This is ok, but you've lost track of that local time.
string s = ""/Date(1445301615000-0700)/"";
DateTimeOffset dto = JsonConvert.DeserializeObject<DateTimeOffset>(s);
Console.WriteLine(dto); // 10/19/2015 5:40:15 PM -07:00
这样好多了.如果您确实需要 UTC DateTime
,那么:
That's much better. And if you do indeed want a UTC DateTime
, then:
string s = ""/Date(1445301615000-0700)/"";
DateTimeOffset dto = JsonConvert.DeserializeObject<DateTimeOffset>(s);
DateTime utc = dto.UtcDateTime;
Console.WriteLine(utc); // 10/20/2015 12:40:15 AM
所以关键的教训是,无论格式如何,如果数据中存在时区偏移信息,则反序列化为 DateTimeOffset
.虽然在某些情况下使用 DateTime
可能 有效,但您要求 .NET 解释偏移量并应用默认行为,这通常不是期望的 行为.
So the key lesson is, regardless of format, if there is time zone offset information present in the data, then deserialize to DateTimeOffset
. While using DateTime
might work in some cases, you are asking .NET to interpret the offset and apply default behavior, which often will not be the desired behavior.
这篇关于使用 JSON.NET 解析格式 Date(epochTime-offset) 的 json 日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!