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
Related
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();
When sending date fields as objects to BigQuery tables that are typed as timestamps, the google java API library does not throw an exception but no data lands. Examining the "InsertAllResponse" response type returns includes the error "This field is not a record".
eg
Hashmap<String,Object> rowContent = new Hashmap<>();
rowContent.put("Time", new Date());
rowContent.put("Name", "Harry");
and then
BigQuery bq = BigQueryOptions.getDefaultInstance().getService();
TableId tableId = TableId.of(datasetName, tableName);
InsertAllRequest.Builder insertReqBuilder = InsertAllRequest.newBuilder(tableId);
insertReqBuilder.addRow({some string}, row);
InsertAllResponse response = bigquery.insertAll(insertReqBuilder.build());
returns a response.hasErrors() true.
Also reported for python here and firebase here and javascript here
It appears that sending dates as objects causes the client API to create a JSON record rather than a single field (and this suggests also that the datetime typing has not been explicitly mapped, so timezone issues may be introduced).
Instead, send the date/time as UTC seconds since 1970, ie modify the above:
Hashmap<String,Object> rowContent = new Hashmap<>();
rowContent.put("Time", Math.floor(new Date().getTime()/1000));
rowContent.put("Name", "Harry");
(NB: not sure how to cope with milliseconds, see eg BigQuery not dealing with timestamp in millisecond with partition column , I'll find out and get back)
Unfortunately, BigQuery's Java API does undocumented conversion of Java types to BigQuery types. In the case of BigQuery Timestamp, the Java API converts float and int into integer truncated seconds since Unix Epoch. Which is pretty silly, considering almost everyone uses milliseconds since Unix Epoch and Timestamp supports up to microsecond accuracy. If you are OK with seconds, use int as seconds.
If you need more accuracy, convert your Timestamp value into a string. The canonical string according to this documentation is:
YYYY-[M]M-[D]D[( |T)[H]H:[M]M:[S]S[.DDDDDD]][time zone]
And here's a Java code example with 'milliseconds' storing milliseconds since Unix Epoch, but you can use whatever DateTime you might happen to have:
long milliseconds = 1610399564959L;
LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneOffset.UTC);
DateTimeFormatter timestampFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
String timestampText = dateTime.format(timestampFormatter);
rowContent.put("Time", timestampText);
I really wish Google would document these conversions somewhere.
Using Retrofit I can send and receive data fine, including dates, but when I use #Multipart it stops working.
This is the log of my data being sent:
Content-Disposition: form-data; name="post_date"
Content-Type: application/json; charset=UTF-8
Content-Length: 26
Content-Transfer-Encoding: binary
"2015-08-06T19:37:14.000Z"
Here's the error I get:
{"post_date": ["Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]"]}
If I omit the date_time field all the other fields transfer properly. I'm not really sure what I'm doing wrong here, the data I'm sending matches the date format that DRF is expecting, but it doesn't seem to think so.
Edit: If I use Postman and send the values that Retrofit claims to be sending it works. I can copy and paste the date above (without quotes) and it submits just fine.
Edit 2: I figured out the problem, the quotes around the date value in my log aren't just in my log, they are added to the date when sending the value to the server. So....how do I convince Retrofit that date values don't need extra quotes around them?
Edit 3: Looks like the issue is that Gson adds quotes to a date when it gets formatted for JSON then Retrofit just sends the value that Gson provides. If you're sending a multi-part message you don't want those quotes though. Not sure how to proceed, created an issue on the Retrofit github page. I know Retrofit either strips quotes from strings before sending them as part of a multipart message, or never adds them in the first place, seems like the same strategy should be used for dates.
Extracting answer from k4yaman comment.
Got the same Problem within my js File, stil i built my Json Data by
my own and let Django handle this. Since Formating was the only cause
in my case i post the format.
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
var hh = today.getHours();
var m = today.getMinutes();
var secs = today.getSeconds();
var now = yyyy+"-"+mm+"-"+dd+"T"+hh+":"+m+":"+secs
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
I need to pass a date, that will be generated via javascript to a asp.net http handler that is services in ajax requests.
On the .net side, I will take the date passed in a cast it to DateTime.
The date has to have: yyyy, mm, dd, and minutes and seconds.
How can I format a date in javascript to this format?
Using jquery
If you're using ASP.NET AJAX already in your project, Dave Ward explains how to use ASP.NET AJAX extensions for this purpose in his blog post Work smarter: MS AJAX's JavScript type extensions:
Simplify formatting client side dates
with Date.format If you’ve spent much
time working with dates in JavaScript,
you know what a hassle it can
sometimes be. To greatly ease this,
ASP.NET AJAX extends the JavaScript
Date object with a formatting function
that closely mimics the ToString
formatting paradigm that we’ve been
using for years. Here are a few
examples:
var today = new Date('12/3/2007');
var shortDate = today.format('d');
// d formats the date as MM/dd/yyyy
// shortDate == '12/03/2007'
var longDate = today.format('D');
// D formats the date as dddd, dd MMMM yyyy
// longDate == 'Monday, 03 December 2007'
var customDate = today.format('MMMM, yyyy');
// Custom format string to format the date as MMMM, yyyy
// customDate == 'December, 2007'
Date.format accepts most of the
standard DateTime format strings, such
as d and D. If none of those suit your
needs, Date.format also provides
almost unlimited flexibility via
custom formatting strings. For a full
list of formatting string parameters,
see the Standard DateTime Format
Strings and Custom DateTime Format
Strings reference pages on MSDN.