Use JSON.NET to parse json date of format Date(epochTime-offset)

后端 未结 2 1971
既然无缘
既然无缘 2020-12-20 23:40

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(14453         


        
相关标签:
2条回答
  • 2020-12-21 00:26

    /Date(1445301615000-0700)/

    That is meant to represent a UTC time of 2015-10-19 17:40:15

    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.

    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
    

    Notice that in in the ISO format, the offset does change the value, but in the MS format it does not.

    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.

    Consider:

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

    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
    

    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
    

    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.

    0 讨论(0)
  • 2020-12-21 00:39

    The -hhmm indicates that a local time was serialized, not a UTC time. .NET, like many other platforms, recognizes the concept of time zones. In .NET, for example, the DateTime class has a property indicating what kind of date/time you're dealing with. You can explicitly construct date/times of different kinds. The debugger is terrible for not pointing this out, but you can see it with the following code.

    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"
    

    You can then see the effect the DateTimeKind has on the Json with the following

    // 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
    }
    
    0 讨论(0)
提交回复
热议问题