WCF error when converting datetime to json format - c#

I have a WCF service that returns JSON.
Since this morning, I started to get the following error:
DateTime values that are greater than DateTime.MaxValue or smaller than DateTime.MinValue when converted to UTC cannot be serialized to JSON
Just for the test, I passed today's date to all the DateTime variables that are being returned using JSON, but I stil get the same error.
The code is around 2k rows, so I see no value in posting it here.
Any idea how to solve it??

I suspect you have a DateTime value that is uninitialized - defaults to DateTime.MinValue local time. This can not be converted to UTC if your local timezone is ahead of UTC, because doing so would result in a negative Ticks value.
Either find the uninitialized value and correct it, or move to the USA :)
Another solution might be to use a nullable value (DateTime? in place of DateTime).
This defaults to null rather than DateTime.MinValue, so you should be able to serialize an uninitialized value.

Related

DateTime.TryParse seems to be losing the original timezone information and converting to server time

I have an ASP.Net form with a date/time control on it. If the form is posted back due to validation errors, the date/time is converted to the servers timezone and set as the value in the date/time control - causing the original timezone information to be lost.
I am using DateTime.TryParse which parses the date into the server time and seems to be losing the original timezone. I want to check if the page is a PostBack and skip the server timezone conversion if at all possible - so I keep the original value.
I tried using TryParseExact which has the timezone information however I couldn't work out what format I should be sending in.
string hiddenDateTime = "2019-09-01T18:28:00.000+0800";
DateTime dateValue;
DateTime.TryParse(hiddenDateTime, CultureInfo.CurrentCulture,
DateTimeStyles.None, out dateValue);
Is there a way to stop this conversion to local from happening and keeping the original timezone?
First of all, this is how DateTime.TryParse method works;
If s contains no time zone information, result contains a DateTime
value whose Kind property is DateTimeKind.Unspecified when the method
returns. If the string to be parsed contains time zone information,
result contains a DateTime value whose Kind property is
DateTimeKind.Local when the method returns.
DateTime object itself neither keep timezone information nor keep UTC Offset value. When you use some parsing operations on a string, it is usually normal to lost these values.
It is not clear what value you try to get exactly but I suggest a few things to get;
If you use DateTimeStyles.AdjustToUniversal instead of DateTimeStyles.None, you will get a DateTime as 9/1/2019 10:28:00 AM which has Utc as a Kind property since this enum value is exactly what this for.
Other than this, since your string has a UTC Offset value, I would parse it to DateTimeOffset instead of DateTime. With parsing to DateTimeOffset, you can keep both of them on it's Offset and DateTime properties.

How to solve DateTimeInvalidLocalFormat error: "A UTC DateTime is being converted to text in a format that is only correct for local times."?

I am getting this error while in Debug though the ToString() is executed:
A UTC DateTime is being converted to text in a format that is only
correct for local times. This can happen when calling
DateTime.ToString using the 'z' format specifier, which will include a
local time zone offset in the output. In that case, either use the 'Z'
format specifier, which designates a UTC time, or use the 'o' format
string, which is the recommended way to persist a DateTime in text.
This can also occur when passing a DateTime to be serialized by
XmlConvert or DataSet. If using XmlConvert.ToString, pass in
XmlDateTimeSerializationMode.RoundtripKind to serialize correctly. If
using DataSet, set the DateTimeMode on the DataColumn object to
DataSetDateTime.Utc.
public static string ToInterfaceString(this DateTime value)
{
return value != DateTime.MinValue ? value.ToString("yyyy-MM-ddTHH:mm:sszzz") : string.Empty;
}
In the app that I've just starting to work on it is used this format in many places. So what should I do in fact? Replace zzz with Z?
Update 1:
the DateTime that is passed to my extension is initiated to:
DateTimeCreated = DateTime.UtcNow;
Weird thing is that if I pass to this extension some other DateTime objects I don't receive any error/warning.
It's a green warning only.
So - as you seem to know what you are doing - you can just comprehend the message (which is correct) and mark the checkbox to Ignore this warning in the future.
As the DateTimeInvalidLocalFormat error explains, the conversion of the date value to string with your defined date format is not usable with DateTime which have the property Kind set to 'Utc'. Even though this error is just a warning and your code should still work, the resulting date string you will get after such operation will be incorrect. This means that if you convert your date to string and will try to parse it again to DateTime, the resulting DateTime value will be different from your original DateTime value. The difference will be as large as your time zone offset from the UTC time is. This is a serious error and should not be ignored especially if your local time does not match the UTC time.
Example:
In this example I assume that the local time zone is 2 hours ahead of UTC time.
DateTime yourLocalTime = DateTime.Now; // => 2020-05-15 08:00:00 => yourLocalTime.Kind = Local
DateTime yourTimeInUTC = DateTime.UtcNow; // => 2020-05-15 06:00:00 => yourTimeInUTC.Kind = Utc, note hours, e.g. 6 vs 8
string dateFormat = "yyyy-MM-ddTHH:mm:sszzz";
string testDateLocal = yourLocalTime.ToString( dateFormat ); // 2020-05-15T08:00:00+02:00 - This is correct date and time
string testDateUtc = yourTimeInUTC.ToString( dateFormat ); // 2020-05-15T06:00:00+02:00 - This date and time is 2 hours behind your actual date and time
To print the date and time string correctly using your date format you have to first convert your UTC date and time to the local date and time:
string testDateUtc2 = yourTimeInUTC.ToLocalTime().ToString( dateFormat ); // 2020-05-15T08:00:00+02:00 - This is correct date and time
To fix your code you should add conversion to the local time in your method:
public static string ToInterfaceString(this DateTime value)
{
return value != DateTime.MinValue ? value.ToLocalTime().ToString("yyyy-MM-ddTHH:mm:sszzz") : string.Empty;
}
You could also print UTC date and time instead of local date and time by replacing date format specifiers 'zzz' to 'Z'. However, in this case you will have a similar issue with conversion in case the DateTime passed to your method is not in UTC Kind, but e.g. in Local Kind and therefore, you have to always convert it to UTC before generating the string:
public static string ToInterfaceString(this DateTime value)
{
return value != DateTime.MinValue ? value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") : string.Empty;
}
Printing of date and time without doing conversion can also be done by using date format specifier 'o', but then the generated date string format will differ based on supplied DateTime Kind and this date format also includes the milliseconds.
public static string ToInterfaceString(this DateTime value)
{
return value != DateTime.MinValue ? value.ToString("o") : string.Empty;
}
This exception is thrown and caught internally inside of ToString() method so the application will continue to run further. It's the only debugger who shows this.
It might initially look like a warning which is visible when debugging only but in fact, this code will generate valid results only in case when your computer time zone is UTC (seems there will be no internal exception in this case too). If your local time zone offset is, for example, UTC+02 than the result of:
new DateTime(2020,7,30,11,22,33, DateTimeKind.Utc).ToString(#"yyyy-MM-dd\THH:mm:sszzz");
on your computer will be "2020-07-30T11:22:33+02:00" which doesn't make sense because the result obviously should have UTC offset as 00:00.
Also, of course, such internal exceptions is a bad thing for control flow and might affect your app performance if this occurs too often.
To avoid invalid .ToString() results and also internal exceptions you can just create DateTimeOffset from given DateTime and invoke .ToString() for it. So the code:
new DateTimeOffset(new DateTime(2020,7,30,11,22,33, DateTimeKind.Utc)).ToString(#"yyyy-MM-dd\THH:mm:sszzz");
will give expected result "2020-07-30T11:22:33+00:00" for any local time zone.
Another suggestion is to use the "K" custom format specifier which gives the correct results for both DateTime and DateTimerOffset.

Date Conversion issue from webservice

I am consuming a Web Service which will return datetime fields in response object.
My reference.cs file has,
private System.DateTime timestampField;
public System.DateTime Timestamp {
get {
return this.timestampField;
}
set {
this.timestampField = value;
}
}
In SOAP UI when I called the service I see it's returning as 2014-06-09T21:24:56+00:00 , 2014-06-17T05:42:00-04:00
I have different Offsets for Different values..
But from my .NET App when I am calling it's converting to some other value as 6/9/2014 5:24:56 PM but it should be whose actual value is 6/9/2014 9:24 pm.
How can I fix this?
When you consume a SOAP web service that uses xsd:dateTime, Visual Studio will always create the client proxy class using a DateTime.
If there is no offset in the data, the values will come across with DateTimeKind.Unspecified.
If instead of an offset, the Z specifier is sent, then the values will come through with DateTimeKind.Utc.
If there is any offset at all, then the values come through with DateTimeKind.Local. Even when the offset is zero. Whatever the offset is, it is applied, and then the value is converted to local time. Essentially, it calls .ToLocalTime() internally.
This kind of stinks, but the easiest way to deal with it is to convert back to UTC using .ToUniversalTime(), or convert to another time zone using the TimeZoneInfo object.
Thanks to the hidden "4th kind", you can safely convert from local back to UTC without ambiguity. (The offset from the original value will disambiguate.)
As far as I know, there is no way to get it to create a DateTimeOffset instead. That would be ideal. However, if you really want to dive deep, you may be able to get it to ignore the offset completely - though that's not necessarily the best idea.
Also, it's worth mentioning that if you were to try to create your own service and expose a DateTimeOffset type directly - you'd run into problems. There isn't a mapping from DateTimeOffset back to xsd:dateTime or any of the other XML Schema data types used by SOAP. Instead, you get a custom complex type in the schema, and the data doesn't get passed along at all. On the client, instead of receiving a System.DateTimeOffset, you get a YourServiceReference.DateTimeOffset object that doesn't do anything at all. It's unfortunate, because it should be great advice to use DateTimeOffset in a public-facing API, but it simply doesn't work. At least not for SOAP/XML. Things are much better in the REST/JSON world.
This is what I did, not sure if it's the efficient way..
I had different offset values for different time values and I don't know the timezone from the time field value... what I did is
I converted the time field value to string and got the offset using sub string and applied that to the UTC of time field value
TimeSpan offSetSpan = new TimeSpan();
string dt = TimestampValue;
string offset = TimestampValue.Substring(trackevent.Timestamp.Length - 6,6);
if (offset != "+00:00" && offset != "-00:00")
{
offSetSpan = TimeSpan.Parse(offset.Trim());
}
Console.WriteLine("Offset Timestamp: {0}", Convert.ToDateTime(TimestampValue).ToUniversalTime() + offSetSpan);

How to set DateTime format without converting to string

I have a Person class which has a date time property.
An object of Person type is sent back as oData response. The response being json.
"FirstName": "Tim",
"LastName": "Sam",
"EmailID": "tim#xyz.com",
"CompanyName": null,
"CreatedDate": "2014-03-18T19:24:30.847"
A lot of help on web suggest using ToString and specifying a format.
How to set the Date in mm/dd/yyyy without resorting to a change to string so that the same is seen in json?
Regards.
"How to set the Date in mm/dd/yyyy without resorting to a change to
string"
You can't do that. A DateTime value is a numeric representation of a point in time, it doesn't contain any information about the format.
The format is decided when you convert it to a string to display it. If you don't convert it to a specific format, then the default formatting is used, which depends on the culture settings for the code where the conversion is done.
Also, the JSON standard doesn't have any Date type at all, so you actually can't put a DateTime value in a JSON string. Either you need to use a non-standard solution, or convert the DateTime value into a different type.
How to set the Date in mm/dd/yyyy without resorting to a change to
string
The Date pass in jSon is a string so you can pass it as a string. Date is stored in number of tick and there is not format of data object format is just a representation. The mm for month would be MM.
string strDateForJson = dateTimeObject.ToString("MM/dd/yyyy");
Internally, all DateTime values are represented as the number of ticks
(the number of 100-nanosecond intervals) that have elapsed since
12:00:00 midnight, January 1, 0001. The actual DateTime value is
independent of the way in which that value appears when displayed in a
user interface element or when written to a file. The appearance of a
DateTime value is the result of a formatting operation. Formatting is
the process of converting a value to its string representation, MSDN.
You can't. A DateTime is a DateTime, and that's that.
If you want to represent it as something else, you have to convert it to something else - say a string, for instance. That is why converting to string with a specific format is the recommended answer.
So although it is perhaps not the answer you would prefer, your solution is basically something like:
yourDate.ToString("MM/dd/yyyy");

Retrieve format of date from date value

I am receiving some data into a variable of type object. In certain cases this data are date values. For that data, I would like to convert this to a string and return it in the same format as it was passed. In some cases, the object could be a datetime, in others a date only or time only values.
As soon as I convert the object to a date or a string, it is obviously given a time of midnight which in my scenario may be a valid time (so I cannot test to see if the time is midnight in which case I could deduce that it would have been a date only date value, nor can I use regex on it as there will always be a time element).
Intellisense shows me it correctly, ie in the format I am wishing to return the value.
Is there an easy way to achieve this (hopefully without using reflection)
Many thx
Simon
Your question is a little unclear but I think you're looking for something like this:
DateTime result;
if (DateTime.TryParse(value, out result))
{
// use result here
}
In the above code value is a string that represents the data coming in. The code will only enter the if block if the string is a valid DateTime. At which point you can do the processing you need on it.
Im not sure i understand the question but i would recommend you to take a look at this conversion example on MSDN, and see the Documentation of the DateTime Structur it contains a lot of Conversion/Formatting Methods i hope it helps.
There are many way to do formatting on the datetime and one of the simple way is fetch the data from the required table in the desired format. Like here you need to display the date and if you your format is dd/MM/yyyy then try this
select Convert(varchar(10),StartDate,103) as StartDateformat from table where filtername=#filtername
use this link to find other format Cast and Convert
From local variable to DateTime Conversion
DateTime todateformat = Convert.ToDateTime(txttodate.Text.Trim());
From DateTime to local variable Conversion in specific format
string startdate = todateformat.ToString("dd/MM/yyyy hh:mm:ss");

Categories

Resources