PDA

View Full Version : datetime and Microsoft AJAX



pau
7 Jan 2010, 2:24 AM
I don't know if the question should be posted in a Microsoft forum instead, but here it is:

I'm using ado.net data services, which implement some kind of REST interface for certain tables in a DB. Some of the fields are .NET DateTime objects, which are automatically serialized to JSON in a format like: "\/Date(1260881125327)\/".

This format is properly handled by ExtJS with the parser "M$". The problem is that when I post a record back to the server with exactly the same formater, actually even using the same string, the server is unable to deserialize the JSON as a DateTime.

I was wondering if someone else has had this trouble before.

Thank you very much in advance,

Pau

fabio.parra
7 Jan 2010, 2:56 AM
Problem is that the year is espected to be 4 characters, and sometimes Ext sends only 2 caracters (Ext 3.0.3):


this.encodeDate = function(o){
return '"' + o.getFullYear() + "-" +
pad(o.getMonth() + 1) + "-" +
pad(o.getDate()) + "T" +
pad(o.getHours()) + ":" +
pad(o.getMinutes()) + ":" +
pad(o.getSeconds()) + '"';
};

So I did a dirty override to corret this problem in my application:


Ext.util.JSON.formatYear = function(year){
year = year.toString();
switch(year.length){
case 1 :
year = "000" + year
break;
case 2 :
year = "00" + year
break;
case 3 :
year = "0" + year
break;
}
return year;
}
Ext.util.JSON.pad = function(n) {
return n < 10 ? "0" + n : n;
}
//override necessário para formatar o ano com 4 digitos sempre!
Ext.util.JSON.encodeDate = function(o){
return '"' +
this.formatYear(o.getFullYear()) + "-" +
this.pad(o.getMonth() + 1) + "-" +
this.pad(o.getDate()) + "T" +
this.pad(o.getHours()) + ":" +
this.pad(o.getMinutes()) + ":" +
this.pad(o.getSeconds()) + '"';
}

pau
7 Jan 2010, 7:35 AM
What I've seen is that the problem resides in the encogind. If the object is a date, the function Ext.util.JSON.encodeDate gets called, which results in the format you mentioned. But if you want to send the date in the Microsoft format, then it is considered as string and the function Ext.util.JSON.encodeString is called.

I've just patched encodeString with something (surely, it needs depuration) like this:


encodeString = function(s){ //debugger;
var re = new RegExp('Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)');
if (s.match(re)) { return '"' + s + '"';}
else if (/["\\\x00-\x1f]/.test(s)) {
return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
var c = m[b];
if(c){
return c;
}
c = b.charCodeAt();
return "\\u00" +
Math.floor(c / 16).toString(16) +
(c % 16).toString(16);
}) + '"';
}
return '"' + s + '"';
}


My question now is, is this the right way to do it, or it is preferably to patch encodeDate? I don't think in the date object I have access to the format definition of the field.

Or maybe I am doing something wrong in an earlier stage in the request.

Mike Robinson
7 Jan 2010, 7:40 AM
I have observed similar problems with date/time formats in particular, and I solved them in this way with a company-custom JsonStore object. In the constructor there's code like this:



// Supply a conversion-function for Date fields, based on what we know ColdFusion will supply.
// There is actually a slight-but-important twist here.
// For "update" requests, we send the values back to the client as ColdFusion would send them.
// But for "create" requests we sent the values back to the client as the client sent them.
// The two are not the same. JavaScript uses the "c" (ISO 8601) date format.
// Therefore, we simply try: first one, then the other.
// FYI: Other parts of ExtJS, such as the "datecolumn" xtype, are already pretty smart about handling
// date-values intelligently, so you might not need to explicitly specify the data-type in many
// practical (i.e. read-only) cases.

if (Ext.isDefined(field.type) && (field.type == 'date')
&& (!Ext.isDefined(field.dateFormat))
&& (!Ext.isFunction(field.convert)))
{
field.convert = function(v){
if (!v) {
return '';
}
if (Ext.isDate(v)) {
return v;
}
var r = Date.parseDate(v, 'F, d Y H:i:s'); // usual
if (Ext.isEmpty(r)) {
r = Date.parseDate(v, 'c'); // exception
}
return r;
};
}

pau
7 Jan 2010, 8:33 AM
Your option is the right way to go for obtaining the right date from the server to the ExtJS side, but as far as I understand, it does not change the way serialization from JavaScript to JSON is performed in the browser side (when ExtJS performs the AJAX request).

Actually, the serialization is performed in the private function doEncode, which only knows if a given object is the null or an undefined object, an array, an ExtJS Date, a string, a number or a boolean, but I think it has no access at all to the convert and format attributes of a field, so encode passes control to encodeDate which serializes the ISO date format.

But, as I said, maybe I'm doing something wrong up in the request. (This happens when posting via jsonData.)

I also find changing encoding functions to intrusive, so I'm still looking for another way to do things.