How to Convert Json Date to .Net Datetime During Deserialization

Proper Way to Convert JSON Date to .NET DateTime During Deserialization

I found a simple answer. In my javascript, I was serializing the data using the JavaScriptSerializer. After much googling, I found this article that shows how to serialize using JsonConvert that causes a more .NET-friendly DateTime to be used.

Old:

var specs = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ViewBag.JobSpecEquipment))

Dates look like this: Date(1348017917565)

New:

var specs = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.JobSpecEquipment));

Dates look like this: 2012-09-18T21:27:31.1285861-04:00

So the problem was really how I was serializing in the first place. Once I used JsonConvert, deserialization on the back end simply worked.

Deserialize JSON Date to C# Object with DateTime Returning 01/01/0001

Add [JsonProperty("Start Date")] above public DateTime StartDate { get; set; } and similar above public DateTime EndDate { get; set; }:

public class MyObject
{
public string Name { get; set; }
[JsonProperty("Start Date")]
public DateTime StartDate { get; set; }
[JsonProperty("End Date")]
public DateTime EndDate { get; set; }
}

The problem was that json property names ('Start Date') and class property names ('StartDate') were not the same so it defaulted to 01/01/0001.

This will work without the need for IsoDateTimeConverter.

JSON Date and DateTime serialisation in c# & newtonsoft

As I mentioned in a comment, there is no standard date representation in JSON. The ISO8601 is the de-facto standard, ie most people started using this some years ago. ISO8601 does not require milliseconds. If the other endpoint requires them, it's violating the defacto standard.

Json.NET uses IOS8601 since version 4.5. The current one is 10.0.3. The following code :

JsonConvert.SerializeObject(DateTime.Now)

returns

"2017-09-08T19:01:55.714942+03:00"

On my machine. Notice the timezone offset. That's also part of the standard. Z means UTC.

You can specify your own time format, provided it's the correct one. In this case, it should be yyyy-MM-ddTHH:mm:ss.fffZ. Notice the fff for milliseconds and HH for 24-hour.

The following code

var settings=new JsonSerializerSettings{DateFormatString ="yyyy-MM-ddTHH:mm:ss.fffZ"};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

returns

"2017-09-08T19:04:14.480Z"

The format string does not force a timezone translation. You can tell Json.NET to treat the time as Local or Utc through the DateTimeZoneHandling setting :

var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffZ",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

Returns :

"2017-09-08T16:08:19.290Z"

UPDATE

As Matt Johnson explains, Z is just a literal, while K generates either Z or an offset, depending on the DateTimeZoneHandling setting.

The format string yyyy-MM-ddTH:mm:ss.fffK with DateTimeZoneHandling.Utc :

var settings=new JsonSerializerSettings{
DateFormatString ="yyyy-MM-ddTH:mm:ss.fffK",
DateTimeZoneHandling=DateTimeZoneHandling.Utc};
var json=JsonConvert.SerializeObject(DateTime.Now,settings);

Will return :

2017-09-11T9:10:08.293Z

Changing to DateTimeZoneHandling.Utc will return

2017-09-11T12:15:12.862+03:00

Which, by the way is the default behaviour of Json.NET, apart from the forced millisecond precision.

Finally, .NET doesn't have a Date-only type yet. DateTime is used for both dates and date+time values. You can get the date part of a DateTime with the DateTime.Date property. You can retrieve the current date with DateTime.Today.

Time of day is represented by the Timespan type. You can extract the time of day from a DateTime value with DateTime.TimeOfDay. Timespan isn't strictly a time-of-day type as it can represent more than 24 hours.

What was that yet?

Support for explicit Date, TimeOfDay is comming through the CoreFX Lab project. This contains "experimental" features that are extremely likely to appear in the .NET Runtime like UTF8 support, Date, String, Channles. Some of these already appear as separate NuGet packages.

One can use the System.Time classes already, either by copying the code or adding them through the experimental NuGet source

Newtonsoft Json converts datetime format when deserializing to string

So it turns out the problem was with a custom converter we are using for some outer classes that first parses the whole object to a JObject, and then does further deserialization from that JObject. I don't want to make too dramatic of changes to this custom converter as it may adversely affect the behavior of other parts of the codebase. So here is what I'm doing as a workaround.

First, I moved the date/time format string to a public constant:

public const string DefaultDateFormatString = "yyyy-MM-ddTHH:mm:ss.fffffffZ";

Then I modified the constructors on the class I was having problems with to explicitly set the date strings to my required format:

public class MyData
{
public MyData(string value, string startDate, string endDate)
{
this.Value = value;
this.StartDate = startDate;
this.EndDate = endDate;
}

[JsonConstructor]
public MyData(string value, DateTimeOffset startDate, DateTimeOffset endDate)
: this(
value,
startDate.ToString(JsonUtility.DefaultDateFormatString),
endDate.ToString(JsonUtility.DefaultDateFormatString))
{
}

public string Value { get; }
public string StartDate { get; }
public string EndDate { get; }
}

Deserializing JSON string to .NET DateTime in local Timezone adds two hours

The solution to the problem proved to be a simple one. Just assume all times are UTC. This fixes all issues in the conversion.

var foo = JsonConvert.DeserializeObject<CustomTime>(json, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});

Parsing a JSON date into a C# DateTime

You need to manually wrap your string "programatically" in quotes to ensure that it properly formatted correctly:

string sa = @"""" + "/Date(1409202000000-0500 )/" + @"""";
DateTime dt = JsonConvert.DeserializeObject<DateTime>(sa);

If you need to call it multiple times (which it seems like you do), just move the wrapping responsibility to a method:

public string WrapStringInQuotes(string input)
{
return @"""" + input + @"""";
}

How to serialize JSON string containing date and time property using DataContractJsonSerializer?

In the case of having a constraint about adding third-party NuGet packages, why not trying to clone/download the package (i.e. Newtonsoft.JSON) from Github and add them directly to your project. So that you won't have any third-party dll your deployment (bin folder).

Please note that the latest versions of the Newtonsoft.JSON are implemented in .netcore and while your project is on .net framework 4, you have to download the compatible version. You can use the tags to find the best version to download.

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

/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.



Related Topics



Leave a reply



Submit