How parse String to JObject ignoring Time Zone
Asked Answered
S

3

8

I have a String of json and need convert to JObject.

Example:

String result = ""{"totalSize":1,"done":true,"records":[{"attributes":{"type":"Municipio__c","url":"/services/data/v37.0/sobjects/Municipio__c/a0V2C000000gIgzUAE"},"Id":"a0V2C000000gIgzUAE","LastModifiedDate":"2017-08-01T18:12:04.000+0000"}]}";"

var json = JObject.Parse(result);

But in the moment of the convertion, the LastModifiedDate has changed the value to my Time Zone.

Like that:

{{
  "totalSize": 1,
  "done": true,
  "records": [
    {
      "attributes": {
        "type": "Municipio__c",
        "url": "/services/data/v37.0/sobjects/Municipio__c/a0V2C000000gIgzUAE"
      },
      "Id": "a0V2C000000gIgzUAE",
      "LastModifiedDate": "2017-08-01T15:12:04-03:00"
    }
  ]
}}

The hour was changed: 18:12:04 (hh:MM:ss) to 15:12:04 (hh:MM:ss).

Is there a way to ignore the Time Zone on the parse?

Sporophyte answered 19/10, 2017 at 12:28 Comment(9)
this looks strange to me, are you sure that's all?Michalmichalak
Yes. That is a feature @MarcoSalernoManchu
JObject.Parse doesn't modify strings. It can't. Strings are immutable. Where did the modified string come from? Besides - the time hasn't changed. It's EXACTLY the same.Malaise
It is the string representation in the debugger when you hover over the JObject @PanagiotisKanavosManchu
@PatrickHofman which is the same instance in both cases. Besides, the string representation doesn't mean the underlying value has changed. The debugger may be displaying the value using the user's locale, because parsing return a local or undefined datetime. It's no different that the questions about replacing nonexistend newlinesMalaise
@PanagiotisKanavos They are not the same at my end. It appears the parser converts it to local time and then JSON.NET shows it as the local time in the debugger.Manchu
@PatrickHofman 18:12:04+00:00 is the same time value as 15:12:04-03:00. How this is formatted into a string, depends into the object's type (is it DateTime?) and if it's DateTime, on its Kind. What is the value's DateTimeKind?Malaise
@PanagiotisKanavos: i.sstatic.net/Zmzbi.png. Kind = LocalManchu
@Sporophyte an even better option is to parse the date value as a DateTimeOffset instead of DateTimeMalaise
M
7

You have to use JsonConvert with the appropriate DateTimeZoneHandling:

var json = JsonConvert.DeserializeObject
                       ( result
                       , new JsonSerializerSettings()
                         { DateTimeZoneHandling = DateTimeZoneHandling.Utc
                         }
                       );
Manchu answered 19/10, 2017 at 12:34 Comment(0)
M
2

The time instances are the same. 18:12:04+00:00 is the same as 15:12:04-03:00 and 21:12:04+03:00 (the current offset in Greece).

The default behaviour when parsing date values is to generate a local DateTime value, ie its Kind property will be DatTimeKind.Local`. The other DateTimeKind values are UTC and Unspecified.

That doesn't mean that the value changed. Local is a relative term though - without knowing the actual offset, it's easy to misinterpret it.

As Patrick Hofman explained, you can specify that UTC is used by setting the DateTimeZoneHandling setting.

An even better way is to specify that DateTimeOffset will be used instead of DateTime by using the DateParseHandling = DateParseHandling.DateTimeOffset property. This will return preserve the original timezone information :

var settings=new JsonSerializerSettings{ 
    DateParseHandling = DateParseHandling.DateTimeOffset
};
var json = JsonConvert.DeserializeObject( result, settings);

In this case, the value will be a DateTimeOffset with the original time and an offset of 00:00.

I'm using dynamic here to reduce casting noise:

var settings=new JsonSerializerSettings{ 
    DateParseHandling = DateParseHandling.DateTimeOffset
};

dynamic json = JsonConvert.DeserializeObject( result, settings);
var value=(DateTimeOffset)(json.records[0].LastModifiedDate.Value);

Console.WriteLine("{0:o}",value);

This will return :

2017-08-01T18:12:04.0000000+00:00
Malaise answered 19/10, 2017 at 13:4 Comment(0)
A
0

You can use the JObject.Load() method by passing into it a JsonReader configured for DateTimeOffset parsing. Here, for example, is a corrected version of the Parse method:

static JObject ParseWithDateTimeOffset(string json, JsonLoadSettings? settings)
{
    using (JsonReader reader = new JsonTextReader(new StringReader(json)))
    {
        reader.DateParseHandling = DateParseHandling.DateTimeOffset;
        JObject o = JObject.Load(reader, settings);

        while (reader.Read())
        {
            // Any content encountered here other than a comment will throw in the reader.
        }

        return o;
    }
}
Actinouranium answered 6/2 at 7:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.