使用JSON.. NET解析json日期格式的日期(epochTime-offset)



我在c#中使用Json.net 7.0.1来使用rest API。问题在于API在其JSON响应中使用的日期格式。它看起来像这样:

/Date(1445301615000-0700)/

表示UTC时间2015-10-19 17:40:15

如果将1445301615000插入历元时间转换器,您会看到它是2015-10-2000:40:15。所以它比UTC早7小时。然后他们包括-0700大概是为了抵消回UTC。所以,为了给我一个UTC时间,他们给我发送了UTC+7-0700。我不知道他们为什么这样做,但我不能改变这一点。

我的问题是,如何最好地使Json。. NET解析该日期字符串并得出2015-10-19 17:40:15 UTC的DateTime。我可以编写一个自定义的JsonConverter来劫持值并手动操作它,但我想知道是否有一个更本机的方法。

我已经尝试将JsonSerializerSettings DateTimeZoneHandling属性更改为所有不同的值。将其设置为Utc只是忽略时区偏移,产生2015-10-20 00:40:15。将其设置为Local, Unspecified或RoundtripKind都产生2015-10-19 20:40:15,我认为这是因为我的本地时区是UTC-4,所以它试图将该调整应用于2015-10-20 00:40的主日期值。

我还考虑使用DateFormatString属性来表示预期的日期字符串格式。但是我找不到合适的格式字符串字符来表示这个epochtime-offset格式。

下面是一个简化的例子:

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有一种本地方法来处理这种类型的日期字符串。

/日期(1445301615000 - 0700)/

表示UTC时间2015-10-19 17:40:15

对不起,这是错误的。UTC时间为2015-10-20 00:45:15。您的值对应于本地时间,在该时刻具有-07:00偏移的时区。

在这种奇怪的格式中,时间戳部分仍然完全基于UTC。偏移量是额外的信息。它不会改变时间戳。你可以给出不同的偏移量,或者完全忽略它,它仍然是相同的时刻。

关于时间点,下面所有的都是等价的。

/Date(1445301615000-0700)/
/Date(1445301615000)/
2015-10-20T00:40:15Z
2015-10-19T17:40:15-07:00

注意,在ISO格式中,偏移量会改变的值,但在MS格式中不会。

最好不要使用这种格式,因为ISO8601是JSON更明智的选择。但是,如果您坚持使用它,那么最好不要将其反序列化为DateTime。请使用DateTimeOffset .

考虑:

string s = ""/Date(1445301615000-0700)/"";
DateTime dt = JsonConvert.DeserializeObject<DateTime>(s);
Console.WriteLine(dt.Kind); // Local

那不好。基本上,如果有任何偏移,它认为它是你的本地时区,它可能是,但也可能不是。

string s = ""/Date(1445301615000)/"";
DateTime dt = JsonConvert.DeserializeObject<DateTime>(s);
Console.WriteLine(dt.Kind); // Utc

可以,但是您忘记了当地时间。

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,那么:

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解释偏移量并应用默认行为,这通常不是期望的行为。

-hhmm表示本地时间被序列化,而不是UTC时间。net像许多其他平台一样,承认时区的概念。例如,在。net中,DateTime类有一个属性,指示您正在处理的日期/时间类型。您可以显式地构造不同类型的日期/时间。调试器没有指出这一点是很糟糕的,但是您可以通过下面的代码看到它。

var dt1 = new DateTime(2015, 01, 01, 00, 00, 00); // defaults to DateTimeKind.Unspecified
var dt2 = new DateTime(2015, 01, 01, 00, 00, 00, DateTimeKind.Local);
var dt3 = new DateTime(2015, 01, 01, 00, 00, 00, DateTimeKind.Utc);
var dt4 = new DateTime(2015, 01, 01, 00, 00, 00, DateTimeKind.Unspecified);
Debug.WriteLine(dt1.Kind); // writes "Unspecified"
Debug.WriteLine(dt2.Kind); // writes "Local"
Debug.WriteLine(dt3.Kind); // writes "Utc"
Debug.WriteLine(dt4.Kind); // writes "Unspecified"

你可以看到DateTimeKind对Json的影响,下面是

// local time -- default datetime handling from JSON.NET
{
    var dateTime = DateTime.Now;
    var jsonObject = new JObject {["dateTime"] = dateTime};
    var jsonString = jsonObject.ToString();
    Debug.WriteLine(jsonString); // uses "2015-10-19T18:13:53.4698565-04:00" form
}
// UTC time -- default datetime handling from JSON.NET
{
    var dateTime = DateTime.Now.ToUniversalTime();
    var jsonObject = new JObject {["dateTime"] = dateTime };
    var jsonString = jsonObject.ToString();
    Debug.WriteLine(jsonString); // uses "2015-10-19T22:13:53.5166571Z" form
}
// local time -- Microsoft-like datetime handling from JSON.NET
{
    var dateTime = DateTime.Now;
    var jsonObject = new JObject {["dateTime"] = dateTime };
    var jsonString = JsonConvert.SerializeObject(jsonObject, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat });
    Debug.WriteLine(jsonString); // uses "/Date(1445292833516-0400)/" format
}
// local time -- Microsoft-like datetime handling from JSON.NET
{
    var dateTime = DateTime.Now.ToUniversalTime();
    var jsonObject = new JObject {["dateTime"] = dateTime };
    var jsonString = JsonConvert.SerializeObject(jsonObject, new JsonSerializerSettings { DateFormatHandling = DateFormatHandling.MicrosoftDateFormat });
    Debug.WriteLine(jsonString); // uses "/Date(1445292833579)/" form
}

相关内容

  • 没有找到相关文章

最新更新