I am having trouble deserialising datetimes with Json.Net 6.0.3 (I can replicate the issue on 6.0.6). The code is run in .Net 4.5 on Windows 8.1, and the culture is en-GB.
This demonstrates the problem:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var d1 = new DateTimeOffset(2014, 12, 15, 18, 0, 0, TimeSpan.FromHours(1));
var obj = new {
time = d1
};
var json = JsonConvert.SerializeObject(obj, Formatting.Indented);
Console.WriteLine(json);
var jo = JObject.Parse(json);
Console.WriteLine(jo.Value<string>("time") + " // jo.Value<string>(\"time\")");
Console.WriteLine(jo["time"] + " // jo[\"time\"]");
the output:
{
"time": "2014-12-15T18:00:00+01:00"
}
12/15/2014 17:00:00 // jo.Value<string>("time")
15/12/2014 17:00:00 // jo["time"]
The date times are different depending on how the JObject is accessed - one is MM/DD/YYYY DD/MM/YYYY. Why is this?
I don't need them to be in a specific format: the problem is that the format changes. I have a lot of legacy code that parses the datetime string sourced from Json.Net. The code will also run on different computers around the world, maybe with different cultures.
Is there a way to make Json.Net always return datetimes in the same format?
The issue is that the two lines do different things:
jo["time"]
Is (ultimately) writing an actual DateTime
value to the console. As @JonSkeet points out, you're actually writing a JValue
to the console--JValue.ToString
just calls the wrapped value's ToString
method though, which in your case is DateTime.ToString()
.
In other words:
Console.WriteLine
and passing an instance of JValue
uses the overload of Console.WriteLine
that takes an object
..ToString()
on the JValue
.ToString()
on the underlying type (in your case a DateTime
)So you're going to get whatever format is the default for your current culture. More specifically, you're going to get the DateTime
formatted with the "G" specifier in your current culture.
The more interesting bit is the jo.Value<string>("time")
line. Under the hood, JSON.NET is converting the underlying DateTime
to a string using the following:
Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture);
This, of course, produces an entirely different string, since it's explicitly using CultureInfo.InvariantCulture
.
The takeaway from this is that your best bet is probably to retrieve the date as a DateTime
, and then format it the exact way you want it, to avoid any ambiguity:
DateTime dt = jo.Value<DateTime>("time");
string dateTimeSTring = dt.ToString(/* whatever format you always want */);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With