Несоответствие в JSON.stringify значений даты в разных браузерах
У меня есть этот код на странице HTML:
alert(JSON.stringify(new Date()));
Я включил последнюю страницу json2.js (версия 2009-09-29) на моей странице для поддержки старых браузеров без JSON.stringify(). Я также включил jquery-1.3.2.js. Я верю в новые браузеры с поддержкой родной JSON, он просто переходит к встроенной функции JSON.
Здесь результаты, которые я получаю в разных браузерах:
IE 8 on Windows XP: "2010-02-07T21:39:32Z"
Chrome 4.0 on Windows XP: "2010-02-07T21:39:59Z"
Firefox 3.0 of Windows XP: "2010-02-07T21:40:41Z"
Chrome 4.0 on Ubuntu linux: "2010-02-07T21:41:49Z"
Firefox 3.0 on Ubuntu linux: "2010-02-07T21:42:44Z"
Chrome 4.0 on Mac OSX: "2010-02-07T21:43:56Z"
Safari on Mac OSX: "2010-02-07T21:45:21Z"
Firefox 3.5 on Mac OSX: "2010-02-07T21:44:10.101Z"
Обратите внимание на последнее? Он содержит миллисекунды, и никто из других не делает этого. У меня нет FF3.5, установленного на любых других системах, но я предполагаю, что они будут иметь одинаковые результаты.
Есть ли что-то, что я могу сделать, чтобы сделать все даты на всех платформах строгими? Мой серверный сервис REST можно настроить с помощью строки формата для десериализации дат JSON, но он не может поддерживать несколько форматов, только один.
Ответы
Ответ 1
Я получил эту работу, добавив следующий javascript:
// Added to make dates format to ISO8601
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + '.' +
f(this.getUTCMilliseconds()) + 'Z';
};
Я уверен, что это, вероятно, замедляет сериализацию, но похоже, что все согласовано между браузерами.
Ответ 2
Вы также можете немного настроить json2.js, чтобы всегда использовать свой собственный Date.prototype.toJSON
вместо возможного родного. Здесь я раскоментировал две строки и работает правильно:
// if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
// }
Ответ 3
//
Возможно, вам стоит подумать о том, чтобы усилить сервер,
для распознавания любого действительного формата времени ISO 8601:
'2010-02-08T03: 37: 34.327Z
'2010-02-08T03: 38: 06Z
'2010-02-08T03: 38 + 01: 00
'2010-02-08T03: 34: 18-05: 00
'2010-02-08T03: 34Z
'2010-02-08'
Это метод преобразования любой строки iso в объект даты javascript.
Его можно использовать на сервере с небольшим переводом:
Date.from_iso= function(s){
var D, M= [], hm, min= 0, d2,
Rx= /([\d:]+)(\.\d+)?(Z|(([+\-])(\d\d):(\d\d))?)?$/;
D= s.substring(0, 10).split('-');
if(s.length> 11){
M= s.substring(11).match(Rx) || [];
if(M[1]) D= D.concat(M[1].split(':'));
if(M[2]) D.push(Math.round(M[2]*1000));// msec
}
for(var i= 0, L= D.length; i<L; i++){
D[i]= parseInt(D[i], 10);
}
D[1]-= 1;
while(D.length< 6) D.push(0);
if(M[4]){
min= parseInt(M[6])*60+ parseInt(M[7], 10);// timezone not UTC
if(M[5]== '+') min*= -1;
}
try{
d2= Date.fromUTCArray(D);
if(min) d2.setUTCMinutes(d2.getUTCMinutes()+ min);
}
catch(er){
// bad input
}
return d2;
}
Date.fromUTCArray= function(A){
var D= new Date;
while(A.length < 7) A.push(0);
var T= A.splice(3, A.length);
D.setUTCFullYear.apply(D, A);
D.setUTCHours.apply(D, T);
return D;
}
Ответ 4
Почему бы не использовать функцию formatDate в плагине jQuery-UI Datepicker для jQuery для создания формата, который требуется для вашей серверной части?