Specify datetime format for WCF Data Service - asp.net

Is there a way to specify the formatting of DateTime data returned by a WCF data service?
This question seems to say that the default format, which looks like /Date(1339515455030)/, is the number of milliseconds since midnight Januery 1, 1970 UTC. I can figure out how to parse that if I have to but I'd rather specify a more friendly format.

The OData DateTime format (assuming you haven't already formatted it out to a string) is dependent on the wire format negotiated between client and server. The format above is from JSON Verbose and corresponds to a standard JavaScript Date object. The Atom format is different, and JSON Light is different still. Of special note is that we decided to move away from the traditional JavaScript Date format in favor of ISO 8601 for JSON Light. In any of these cases, if you're using a client such as the WCF DS client or data.js, the client will take care of deserializing the value properly.
Atom formatted date: <d:OrderDate
m:type="Edm.DateTime">1996-07-04T00:00:00</d:OrderDate>
JSON verbose formatted date: "OrderDate":"\/Date(836438400000)\/"
JSON light formatted date: "ShippedDate":"1996-07-16T00:00:00"
For current client libraries on a variety of platforms, see here: http://www.odata.org/libraries

With OData V3 the JSON Verbose format uses the ISO 8601 which seems to be more friendly to some consumers. Note though that it will only be used if the payload is V3. So you will need to update your server side to supper OData V3 (if it's WCF DS, then you want to use the WCF DS 5.0 release which can be found for example on NuGet http://blogs.msdn.com/b/astoriateam/archive/2012/05/18/wcf-data-services-5-0-1-released.aspx).
Once you have that you might need to force the server to use V3 in the response payload since by default it will use the lowest possible version for the response. This can be done by sending a MinDataServiceVersion: 3.0; header with the request from the client.
After this even JSON Verbose payloads should use the ISO date time format.

I believe that you should be able to feed the string value sent back into the datetime.parse(http://msdn.microsoft.com/en-us/library/1k1skd40.aspx) and shouldn't have to worry about the rest
Here is an example usage: http://www.dotnetperls.com/datetime-parse

Related

Date parsing errors when timezone does not exist with Java OpenAPI generator client

I'm working on integrating with an API that (unfortunately) does not always append the timezone offset to their date. I know this isn't optimal but I can't change their behavior.
Example:
2022-06-08T16:07:13.96
Using the java generator and the java8 date library produces a runtime error while parsing the date:
java.time.format.DateTimeParseException: Text '2022-06-08T16:07:13.96' could not be parsed at index 22
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2052)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1954)
at java.base/java.time.OffsetDateTime.parse(OffsetDateTime.java:404)
at com.acme.openapi.JSON$OffsetDateTimeTypeAdapter.read(JSON.java:287)
From my limited understanding, I believe that ISO-8601 dates should be treated as local dates instead of offset dates if the zone offset is omitted. Im unsure if this is something that is supported in the java generator.
I ended up swapping the date library to java8-localdatetime but it gave GSON some problems:
Expected BEGIN_OBJECT but was String
I changed to a jackson based client and that cleared everything up.
I use this nasty wrapper everywhere, where I use a DateTime from the API, to "hack" it in the current timezone.
DateTime utcHack(DateTime dt) {
return DateTime.parse(dt.toLocal().toString() + "Z");
}
I am open for improvements!

How can I get SignalR to stop changing my date/time values?

I have a simple class that contains a DateTime property. When I set the value of this property using DateTime.Now() the value is correct. However, when I pass this class object as a parameter via SignalR, on the receiving end SignalR has changed the DateTime so that it no longer matches the original DateTime. How can I get SignalR to stop manipulating my DateTime values? This issue seems to have started with a recent update to the latest SignalR nuget packages.
This seems to be a problem when the hub and the client are in two different time zones. It seems Microsoft is trying to help, by adjusting the date/time to the local time zone, but I want the original value, not the value Microsoft "thinks" I want.
When you want two systems to communicate with each other I would recommend using always the DateTime in UTC for various reasons. In your case you have two options here:
1 - Send the date as string string date = DateTime.Now.ToString(CultureInfo.InvariantCulture); so on the client side you just need to parse the datetime like DateTime.Parse(date, CultureInfo.InvariantCulture);.
2 - Send the date in UTC like DateTime.UtcNow; so event if the SignalR tries to change the date, it will have the DateTime.Kind as UTC. In this case or you will get the current date correctly, or you just adjust on the client side to the local time like receivedDate.ToLocalTime();
This one was a real head scratcher as I had the exact same issue. The client was storing the correct time but by the time it hit the Hub... it had changed. I'm really glad you posted this as I wouldn't have imagined this issue being possible. #Kiril1512 posted the correct resolution. In my case I used his second option as I didn't want to change my model... although simply converting to a string would have been simpler. While I did follow his suggestion and convert everything to DateTime.UtcNow()... I am thinking this was unnecessary as I noticed even previously stored dates converted correctly. This makes me think that either this isn't necessary to do, or dates are converted to Utc when they hit the Hub automatically which may be what the issue was to begin with?
Either way I posted this as I discovered that converting this date back to Local time was a little more involved. Here is how I ended up doing the conversion which resolved this issue for me that I gathered from this resource:
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(msg.CreatedOn.ToString()),
DateTimeKind.Utc);
var kind = convertedDate.Kind;
DateTime dt = convertedDate.ToLocalTime();

MS JSON date serialization and daylight saving time

We have an Ajax web service hosted in an ASP.NET application. This service accepts a DateTime parameter which, for the purposes of this question, should receive the DateTime equivalent of /Date(1359727200000-0200)/, which is a MS-JSON literal for Feb 1, 2013 9:00 AM in Brazil time. This literal is what the browser sends within the Ajax request.
But instead of receiving that date and time, the argument passed to the service method is Feb 1, 2013 12:00 PM. To make matters worse, the argument's DateTimeKind is Local. It would be understandable if it were Utc, but even that would be incorrect since February 1st is daylight saving time in Eastern Brazil, so that 9:00 AM (local) sould be 11:00 AM (UTC). It really is a mess. By the way, the web server runs under Eastern Brazilian time zone.
Is there any ASP.NET configuration, service method annotation, specific client instructions, or any framework resource to work around this problem?
After much debugging I found the problem: I was ignorant of the way the JSON serializer works regarding the System.DateTime kind and the Date literal when (de)serializing dates back and forth between the server and the browser.
In detail, here's what happens. Suppose a service has to return a DateTime value to a client in JSON format. The DataContractJsonSerializer will produce a string in the (infamous) /Date(UTC ticks)/ format, which the client can parse into a JavaScript Date value. This serialization is sensitive to the DateTime's Kind property:
When the Kind is DateTimeKind.Utc, the string literal will contain "/Date(UTC ticks)/" and no time zone.
When the Kind is DateTimeKind.Local, the string literal will contain "/Date(UTC ticks-time zone)/".
If the Kind is DateTimeKind.Unspecified, it is assumed Local.
Conversely, if the client sends a date value to the service, the serialization process is also sensitive to the "kind" of the JSON literal:
When the literal is in the format "/Date(UTC ticks)/" with no time zone, the produced
DateTime will be of DateTimeKind.Utc kind.
When the literal is in the format "/Date(UTC ticks-time zone)/", the produced DateTime will be of DateTimeKind.Local kind.
All I had to do is make sure the client sends only UTC-formatted Date literals to the service. All is great now.

ASP.NET WebAPI XmlFormatter Missing UTC Offset for Dates

I have an ASP.NET WebAPI implementation that I am allowing clients to consume and request either XML or JSON formatting of the HTTP response. Some of the response objects include date/time values. I have been successful in getting the JSON response to include a proper ISO 8601 formatted date (including UTC time offset) by using code like:
Dim json As JsonMediaTypeFormatter = _
GlobalConfiguration.Configuration.Formatters.JsonFormatter
json.SerializerSettings.DateFormatHandling = _
Newtonsoft.Json.DateFormatHandling.IsoDateFormat
json.SerializerSettings.DateTimeZoneHandling = _
Newtonsoft.Json.DateTimeZoneHandling.Local
The JsonFormatter now gives me a date like this:
2008-11-03T14:14:00-05:00
However, the XmlFormatter gives me a date like:
2008-11-03T14:14:00
Notice the missing UTC time offset ("-05:00"). How do I get the XMLFormatter to give me the UTC time offset?
I believe I just figured this out myself.
When reading the dates from the SQL Server database (using an IDataReader) and the Enterprise Library Data Block, I need to use the Date.SpecifyKind method to tell what kind of date is being retrieved from the database.
Dim dateCreated As Date = _
Date.SpecifyKind(CDate(dbReader("DateCreated")), DateTimeKind.Local)
By doing this, I was also able to remove the JsonMediaTypeFormatter lines specified in my original question. So, now both XML and JSON send the date as:
2008-11-03T14:14:00-05:00
More information on Date.SpecifyKind can be found here:
http://msdn.microsoft.com/en-us/library/bb546101.aspx

OData Library RTM DateTime Inconsistencies

I just upgraded to the RTM version of the OData Library. I've noticed what appear to be inconsistencies in DateTime handling and would like to know if anyone can explain what I might be missing, or if there are in fact some problems. In addition to the RTM library I'm relying on the 3/30/2012 version of MS-ODATA.
MS-ODATA defines dateTimeUriLiteral in the following format (simplified for example):
YYYY-MM-DDTHH:MM:SS.NS where NS is defined as nanoSeconds=1*7DIGIT
And MS-ODATA defines VJsonDateTime as the dreaded /Date(...)/ format.
However using the Library in verbose JSON serialization we see the dateTimeUriLiteral format, not VJsonDateTime. Furthermore the deserialization accepts only the dateTimeUriLiteral format. This looks like a conflict between the spec and the implementation.
Also, dateTimeUriLiteral makes no allowance for time zone offset (such as would be the case in an ISO 8601 format). However we see that the Library emits a 'Z' terminating character (ISO 8601 for UTC) when the serialized datetime object is designated as DateTimeKind.Utc. This also looks like a conflict between the spec and the implementation.
Also, when we use the Library to deserialize a dateTimeUriLiteral that has the terminating 'Z' - the deserialized object is marked as DateTimeKind.Local. Whether or not there is a spec issue WRT support for the UTC designator, this does not look like it could be correct. Either the 'Z' should cause a deserialization failure or it should result in a time marked as UTC (not local).
Verbose JSON V3 uses the ISO DateTime format (the same one as XML uses). Verbose JSON V2 and V1 use the /Date(...)/ format. So it depends which version of the payload you're writing and reading.
The dateTimeUriLiteral is not the same thing as the Verbose JSON V3 date time format. The one in Verbose JSON V3 uses the Z (it's literaly the same thing as you get from XmlConvert.ToString(datetime, XmlDateTimeSerializationMode.RoundtripKind)).
As for reading the "Z" value. This seems to be a bug. The product team is looking into this in more detail. Possible workaround seems to be to either revert back to V2 format, or use DateTimeOffset values instead (which don't have this problem).

Resources