Parse custom date format using JSON.Net - c#

I'm receiving a JSON date in the following format:
"launch_date": 1250553600
How should I modify the following to include a custom DateTime parser that allows me to convert that number into a DateTime object?
JsonConvert.DeserializeObject<NTask>(json);
public sealed class NTask
{
public DateTime launch_date { get; set; }
}
Alternatively I could use long and then parse it in another field but I'd rather avoid doing that, and have JsonConvert automatically parse it to DateTime through some converter.

You're going to want to use a JSONConverter to help manage the translation. See this stackapps answer for more detail.

Here is some code to do that:
// This is an example of a UNIX timestamp for the date/time 11-04-2005 09:25.
double timestamp = 1113211532;
// First make a System.DateTime equivalent to the UNIX Epoch.
System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
// Add the number of seconds in UNIX timestamp to be converted.
dateTime = dateTime.AddSeconds(timestamp);
For your code:
JsonConvert.DeserializeObject<NTask>(json);
public sealed class NTask
{
public DateTime launch_date { get; set; }
public void SetLaunchDate(int timestamp)
{
// First make a System.DateTime equivalent to the UNIX Epoch.
var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
// Add the number of seconds in UNIX timestamp to be converted.
launch_date = dateTime.AddSeconds(timestamp);
}
}
Then when you are Deserializing the JSON, check to see if the launch_date is of type int or DateTime and switch how you set the object based on the type!

Related

Parse custom JSON string to DateTime Convert in API

My Question is similar to this one (The JSON value could not be converted to System.DateTime), where I am trying to convert an input string to an DateTime. The difference, however, is that the input string cannot be changed. I have no choice in it.
[HttpPut("PutBodyToFoodChain")]
public async Task<IActionResult> PutBodyToFoodChain([FromBody] TxMSAGrading body)
{ ... }
What I've tried:
[JsonConverter(typeof(DateFormatConverter), "MM/dd/yyyy hh:mm:ss")]
public DateTime KillDate { get; set; }
Error:
The JSON value could not be converted to System.DateTime
Input String:
{"GradeDate": "08/24/2020 01:36:00", "KillDate" : "08/24/2020 00:00:00", ... }
Additional Information:
I cannot change the model. So it will always be parsed in to be converted to a Date-Time.
There are 500+ fields in the model. I can't explicitly convert every Date-time field.
DateTime fields will always have the same format.
One idea is to defer parsing until after the raw string is captured in your model. This allows deserialization to succeed more reliably and for you to have control over the parsing. For example, an updated model:
public string KillDate { get; set; }
public DateTime KillDateValue => DateTime.TryParse(KillDate, out DateTime parsed) ? parsed : DateTime.MinValue;
public bool KillDateParsed => KillDateValue != DateTime.MinValue;
If parsing succeeds, KillDateParsed will be true and you'll have the parsed value in KillDateValue. DateTime.TryParse can also be provided a specific pattern to match.

Storing Utc Time in Getter/Setter Property

Currently, I am storing theDateTime with the DeliveryDate getter/setter. However, I'm having issues storing this in UTC time. I've done some research on this and tried DateTimeKind.Utc but can't get that to work correctly. How can I get DeliveryDate to store the DateTime in UTC time?
My Code:
public partial class shippingInfo
{
public System.Guid EmailConfirmationId {get; set; }
public Nullable<System.DateTime> DeliveryDate {get; set; }
}
Update: Added Implementation:
DeliveryExpirationRepository.Add(new DeliveryPendingConfirmation
{
EmailConfirmationId = newGuid,
DeliveryDate = DateTime.Now.AddHours(48),
});
To make a DateTime store a UTC value, you must assign it a UTC value. Note the use of DateTime.UtcNow instead of DateTime.Now:
DeliveryExpirationRepository.Add(new DeliveryPendingConfirmation
{
EmailConfirmationId = newGuid,
DeliveryDate = DateTime.UtcNow.AddHours(48),
});
The DateTime.UtcNow documentation says:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC).
The DateTime.Now documentation says:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.
You might want to use DateTimeOffset instead. It always stores an absolute point in time, unambiguously.
You can add a code to the setter method to check if value is not in UTC and convert this value to UTC:
public class shippingInfo {
public System.Guid EmailConfirmationId { get; set; }
private Nullable<System.DateTime> fDeliveryDate;
public Nullable<System.DateTime> DeliveryDate {
get { return fDeliveryDate; }
set {
if (value.HasValue && value.Value.Kind != DateTimeKind.Utc) {
fDeliveryDate = value.Value.ToUniversalTime();
}
else {
fDeliveryDate = value;
}
}
}
}
In this case, you don't need to care how a value of this property is set. Or you can use the DateTime.ToUniversalTime method to convert any date to UTC where you set a value of the property.

Convert Date into JSON object in c#

I've created a C# class with a static method that convert's any object to a JSON object. I've used JavaScriptSerializar for this. Here is my code
public class JS
{
public static string GetJSON(object obj)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string retJSON = js.Serialize(obj);
return retJSON;
}
}
I've another class that have only two property, Date & Remark. Here is my class
public class RemarkData
{
public DateTime Date { set; get; }
public string Remark { set; get; }
}
Now, I'm converting a object of the RemarkData class into JSON using following code
JS.GetJSON(objRemarkData);
Here is the output I'm getting
{"Date":"/Date(1389403352042)/","Remark":"Sme Remarks"}
Here is the output that I need
{"Date":1389403352042,"Remark":"Some Remarks"}
What should I do tho get that kind of output? Any help ?
double ticks = Math.Floor(objRemarkData.Date.ToUniversalTime()
.Subtract(new DateTime(1970, 1, 1))
.TotalMilliseconds);
var newob = new { Date =ticks, Remark = objRemarkData.Remark};
JS.GetJSON(newob);
You could try JSON.NET, it serializes Date into ISO string.
public class JS
{
public static string GetJSON(object obj)
{
string retJSON = JsonConvert.SerializeObject(obj);
return retJSON;
}
}
Actually, you can use it directly, don't need to wrap inside another function.
This is also how asp.net web api serializes date objects. For more information why ISO string is a good choice, check out this link http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx
This long number is "milliseconds since epoch". We can convert this to normal javascript date by using the following snippet as explained in another so post Converting .NET DateTime to JSON
var d = new Date();
d.setTime(1245398693390);
document.write(d);
One can also use a nice library from http://blog.stevenlevithan.com/archives/date-time-format with the following snippet ..
var newDate = dateFormat(jsonDate, "dd/mm/yyyy h:MM TT");

JSON.NET Serialize Date

I would like to serialize my date to be in a specific format but I can't get my act together.
I tried building a nice little class but the output gets wrapped in quotes, which doesn't work.
I'd like the JSON to look like this...
{
date : new Date(2013, 8, 30)
}
but I get this...
{
date: "new Date(2013, 8, 30)"
}
my class
public class DateCell : ChartCell
{
[JsonIgnore]
public DateTime Value { get; set; }
[JsonProperty(PropertyName = "date")]
public override object DataValue
{
get
{
return string.Format("new Date({0}, {1}, {2})", this.Value.Year, this.Value.Month - 1, this.Value.Day);
}
}
}
There's a difference between a JavaScript Object and JSON. What you described might be valid in a JavaScript object, but it is not valid JSON. JSON does not allow the representation that you are asking for.
In JSON a value can only be one of the following:
A string, such as "abc"
A number, such as 123 or -12.34
A literal value of true, false, or null
An array of other valid values, such as [1,"a",true]
Another JSON object, such as { a: 1, b: "abc" }
It cannot just be a JavaScript Object, or any other arbitrary JavaScript. See the spec at json.org.
Passing a Date object constructor would not make any sense, as JSON is a general purposed serialization format, and Date is a JavaScript native class. How would you expect non-JavaScript code to interpret this?
While there is no specific date or time format defined by the JSON standard, the de facto standard is the ISO 8601 format. Your DateTime would look something like "2013-09-30T00:00:00". There are other ways to serialize a date, but they are not as uniform or popular.
In JSON.Net, the ISO 8601 format is the default. So you don't need to do anything special other than just to serialize your object with its original properties.
public class DateCell : ChartCell
{
public DateTime Value { get; set; }
}
UPDATE
Since you said in comments that you are passing this to Google Charts, it appears from their reference that they are using a nonstandard format that looks like the Date constructor, but has omitted the new keyword. Why they do this, I'm not sure, but you should be able to modify your original code as follows:
public class DateCell : ChartCell
{
[JsonIgnore]
public DateTime Value { get; set; }
[JsonProperty(PropertyName = "date")]
public override object DataValue
{
get
{
return string.Format("Date({0},{1},{2})", this.Value.Year, this.Value.Month - 1, this.Value.Day);
}
}
}

How to handle vague dates in .Net

I have a system that takes information from an external source and then stores it to be displayed later.
One of the data items is a date. On the source system they have the concept of a fuzzy date i.e. not accurate to a specific day or sometimes not to a month as well. So I get dates in the format:
dd/mm/yyyy
mm/yyyy
yyyy
I can parse these to DateTime objects and work with these but when rendering later I need to be able to determine the accuracy of the date since parsing "2010" will result in a date of "01/01/2010". I want to show just the year so need to know it's original accuracy.
I've mocked up a quick class to deal with this:
public class FuzzyDate
{
public DateTime Date { get; set; }
public DateType Type { get; set; }
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
This will do the job for me and I can do something on the parse to handle it but I feel like this is probably quite a common problem and there is probably an existing cleaner solution.
Is there something built into .Net to do this? I had a look at the culture stuff but that didn't quite seem right.
Any help would be appreciated.
To answer your question: There is nothing built into .NET to handle this gracefully.
Your solution is as valid as any I've seen. You will probably wish to embellish your class with overrides to the ToString() method that will render your date appropriately based on the DateType.
Here are a couple other threads that attempt to address this question:
Strategy for Incomplete Dates
Implementing a "Partial Date" object
Good luck!
If your data type will always handle specific periods of time (i.e. the year 1972 is a specific period of time, but the 4th of July is not specific), you can store your data as a start time and time span.
If your date was "1972", the start date would be 19720101 and the time span would be 366 days.
If your date was "07/1972", the start date would be 19720701 and the time span would be 31 days.
If your date was "04/07/1972", the start date would be 19720704 and the time span would be 1 day.
Here's a possible implementation:
public struct VagueDate
{
DateTime start, end;
public DateTime Start { get { return start; } }
public DateTime End { get { return end; } }
public TimeSpan Span { get { return end - start; } }
public VagueDate(string Date)
{
if (DateTime.TryParseExact(Date, "yyyy", null, 0, out start))
end = start.AddYears(1);
else if (DateTime.TryParseExact(Date, "MM/yyyy", null, 0, out start))
end = start.AddMonths(1);
else if (DateTime.TryParseExact(Date, "dd/MM/yyyy", null, 0, out start))
end = start.AddDays(1);
else
throw new ArgumentException("Invalid format", "Date");
}
public override string ToString()
{
return Start.ToString("dd/MM/yyyy") + " plus " + Span.TotalDays + " days";
}
}
As I started to read your problem, I rapidly came to the conclusion that the answer was to implement your own FuzzyDate class. Lo and behold, that's exactly what you've done.
I can imagine that you might want to add functionality to this over time (such as comparisons that take into account the DateType).
I don't believe there's anything that will inherently help you in the .NET Framework, so I think you're doing the right thing.
I think you're going down the right route. There is no concept of a 'fuzzy' date or partial date, you will need to build your own.
You will likely need more constructor methods, for example
public FuzzyDate(int year)
{
Date = new DateTime(year,1,1); // 1 Jan yy
Type = DateType.Year;
}
public FuzzyDate(int year, int month)
{
Date = new DateTime(year, month, 1); // 1 mm yy
Type = DateType.MonthYear;
}
public FuzzyDate(int year, int month, int day)
{
Date = new DateTime(year, month, day); // dd mm yy
Type = DateType.DayMonthYear;
}
Hope this helps,
Kevin
It seems to me that your approach is right. Its true that .NET DateTime support multiple formats but I guess that given that all of them are supported with a concept of steps (nanoseconds), then will be related to specific date AND time.
One thing I would do differently is use null-able values (or use -1 for null semantics) for month and day to indicate what data was collected. Then I would have a factory method that would take a DateType param and return a DateTime. This method would throw and exception if only the year was available and the client code tried to create a DateType.DayMonthYear.
public class FuzzyDate
{
int _year;
int? _month;
int? _day;
public DateTime Date { get; set; }
public DateType Type { get; set; }
public DateTime GetDateTime(DateType dateType) { // ...
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
This might seem a bit over the top but the approach would explicitly store the original data and only represent "faked" DateTime objects when requested. If you were to persist a DateTime object internally along with a DateType enum you would lose some resolution.
As far as I am aware there is nothing built into .NET for this, the solution I'd go for is one based upon nullable values, something like this.
public class FuzzyDate
{
private int Year;
private int? Month;
private int? Day;
public FuzzyDate(int Year, int? Month, int? Day)
{
this.Year = Year;
this.Month = Month;
this.Day = Day;
}
public DateType DateType
{
get
{
if(Day.HasValue && Month.HasValue)
{
return DateType.DayMonthYear;
}
else if(Month.HasValue)
{
return DateType.MonthYear;
}
else
{
return DateType.Year;
}
}
}
public DateTime Date
{
get
{
return new DateTime(Year, Month.GetValueOrDefault(1), Day.GetValueOrDefault(1));
}
}
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
You could create your own structure (user-defined type) based on the datetime that would allow 00 for month, and 00 for day... And then also implement icomparable, so you can do math/comparrisons on it.
http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.icomparable.aspx

Categories