How to Prevent a Single Object Property from Being Converted to a Datetime When It Is a String

How to prevent a single object property from being converted to a DateTime when it is a string

What one can do is to add a custom JsonConverter to the InputModel type to temporarily toggle JsonReader.DateParseHandling to None:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)]
class InputModel
{
public string Name { get; set; }
public object Value { get; set; }
}

public class DateParseHandlingConverter : JsonConverter
{
readonly DateParseHandling dateParseHandling;

public DateParseHandlingConverter(DateParseHandling dateParseHandling)
{
this.dateParseHandling = dateParseHandling;
}

public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var old = reader.DateParseHandling;
try
{
reader.DateParseHandling = dateParseHandling;
existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
}
finally
{
reader.DateParseHandling = old;
}
}

public override bool CanWrite { get { return false; } }

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

Note that, if the JSON to be deserialized contains nested arrays or objects, all recursively contained values will be parsed with DateParseHandling.None.

One might ask, why not add a converter directly to the property, like so?

class InputModel
{
public string Name { get; set; }
[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)]
public object Value { get; set; }
}

It turns out that this does not work because, at the time JsonConverter.ReadJson() is called, the reader has already advanced to the date string and tokenized it as a DateTime. Thus the converter must be applied to the containing type.

How to remove time portion of date in C# in DateTime object only?

Use the Date property:

var dateAndTime = DateTime.Now;
var date = dateAndTime.Date;

The date variable will contain the date, the time part will be 00:00:00.

Converting from string to DateTime, and then storing in list C#

The problem here is that the variable oDate only exists in the scope where you declared it.
In your case it's only usable inside your if statement.

Your function should look like this for you to access the variable when needed:

public Boolean addVisit(int[] staff, int patient, int type, string dateTime)
{
//if the number of objects in the visit list is equal to 6, clear the list to avoid repeated output in textbox
if (visit.Count == 6)
{
visit.Clear();
}

DateTime oDate = Convert.ToDateTime(dateTime);;
//converting from string to dateTime
for (int i = 0; i < visit.Count; i++)
{
//the original task was to store 6 instances so thats why is says < 7
if (visit.Count < 7)
{
//DateTime oDate = Convert.ToDateTime(dateTime);
// Because you definded oDate inside your if clause it is only accessible inside the clause
}
}


//adding all the visits, regardless of if the data is valid or not
Visit v = new Visit();
v.Staff = staff;
v.Patient = patient;
v.Type = type;
v.DateTime = oDate;

//adds instance of visit to the visit list
visit.Add(v);

return true;

Prevent TestContext data from being automagically converted

If the type of the MyDateColumn is set to datetime, then it would/should return a datetime object.

Try changing the type of MyDateColumn to be string and see if that does the trick.

UPDATE

Change dates in the CSV so that they are "mm/dd/yyyy" instead of mm/dd/yyyy.

Json.NET deserializing DateTimeOffset value fails for DateTimeOffset.MinValue without timezone

The problem seems reproducible only when the machine's time zone TimeZoneInfo.Local has a positive offset from UTC, e.g. (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna. I was unable to reproduce it in time zones with a non-positive offset such as UTC-05:00 or UTC itself.

Specifically, in JsonReader.ReadDateTimeOffsetString() a call is made to DateTimeOffset.TryParse using DateTimeStyles.RoundtripKind:

if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}

This apparently causes an underflow error in time zones with a positive UTC offset. If in the debugger I parse using DateTimeStyles.AssumeUniversal instead, the problem is avoided.

You might want to report an issue about this to Newtonsoft. The fact that deserialization of a specific DateTimeOffset string fails only when the computer's time zone has certain values seems wrong.

The workaround is to use IsoDateTimeConverter to deserialize your DateTimeOffset properties with IsoDateTimeConverter.DateTimeStyles set to DateTimeStyles.AssumeUniversal. In addition it is necessary to disable the automatic DateTime recognition built into JsonReader by setting JsonReader.DateParseHandling = DateParseHandling.None, which must be done before the reader begins to parse the value for your DateTimeOffset properties.

First, define the following JsonConverter:

public class FixedIsoDateTimeOffsetConverter : IsoDateTimeConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?);
}

public FixedIsoDateTimeOffsetConverter() : base()
{
this.DateTimeStyles = DateTimeStyles.AssumeUniversal;
}
}

Now, if you can modify the JsonSerializerSettings for your controller, use the following settings:

var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new FixedIsoDateTimeOffsetConverter() },
};

If you cannot easily modify your controller's JsonSerializerSettings you will need to grab DateParseHandlingConverter from this answer to How to prevent a single object property from being converted to a DateTime when it is a string and apply it as well as FixedIsoDateTimeOffsetConverter to your model as follows:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)]
public class RootObject
{
[JsonProperty("revisedDate", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(FixedIsoDateTimeOffsetConverter))]
public DateTimeOffset? RevisedDate { get; set; }
}

DateParseHandlingConverter must be applied to the model itself rather than the RevisedDate property because the JsonReader will already have recognized 0001-01-01T00:00:00 as a DateTime before the call to FixedIsoDateTimeOffsetConverter.ReadJson() is made.

Update

In comments, @RenéSchindhelm writes, I created an issue to let Newtonsoft know. It is Deserialization of DateTimeOffset value fails depending on system's timezone #1731.

Json.NET Disable the deserialization on DateTime

When parsing from an object to JObject you can specify a JsonSerializer which instructs how to handle dates.

JObject.FromObject(new { time = s },
new JsonSerializer {
DateParseHandling = DateParseHandling.None
});

Unfortunately Parse doesn't have this option, although it would make sense to have it. Looking at the source for Parse we can see that all it does is instantiate a JsonReader and then passes that to Load. JsonReader does have parsing options.

You can achieve your desired result like this:

  using(JsonReader reader = new JsonTextReader(new StringReader(j1.ToString()))) {
reader.DateParseHandling = DateParseHandling.None;
JObject o = JObject.Load(reader);
}

For background, see Json.NET interprets and modifies ISO dates when deserializing to JObject #862, specifically this comment from JamesNK: I have no plans to change it, and I would do it again if give the chance.



Related Topics



Leave a reply



Submit