Расхождение в JSON.stringify значений даты в разных браузерах - PullRequest
17 голосов
/ 08 февраля 2010

У меня есть этот код на странице 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, но она не может поддерживать несколько форматов, только один.

Ответы [ 4 ]

9 голосов
/ 08 февраля 2010

Я получил эту работу, добавив следующий 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';
};

Я уверен, что это, вероятно, замедляет сериализацию, но, похоже, все согласовано в браузерах.

4 голосов
/ 08 февраля 2010

Вы также можете настроить 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 голосов
/ 08 февраля 2010

// Возможно, вы захотите увеличить нагрузку на сервер, распознать любой действительный формат времени 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;
}
0 голосов
/ 08 февраля 2010

Почему бы не использовать функцию formatDate в плагине DatePicker jQuery-UI для jQuery для генерации формата, который требуется на стороне сервера?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...