17 Stimmen

Diskrepanz bei JSON.stringify von Datumswerten in verschiedenen Browsern

Ich habe diesen Code in einer HTML-Seite:

alert(JSON.stringify(new Date()));

Ich füge die neuesten json2.js (Version 2009-09-29) in meiner Seite, um ältere Browser ohne JSON.stringify() zu unterstützen. Ich habe auch jquery-1.3.2.js enthalten. Ich glaube, in neueren Browsern mit nativer JSON-Unterstützung, es geht nur durch die native JSON-Funktion.

Hier sind die Ergebnisse, die ich in verschiedenen Browsern erhalte:

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"

Haben Sie den letzten Punkt bemerkt? Sie enthält Millisekunden, aber keine der anderen. Ich habe FF3.5 nicht auf anderen Systemen installiert, aber ich gehe davon aus, dass sie die gleichen Ergebnisse liefern würden.

Gibt es etwas, das ich tun kann, damit alle Daten auf allen Plattformen gleich sind? Mein Backend-REST-Dienst kann mit einem Format-String konfiguriert werden, um JSON-Daten zu deserialisieren, aber es kann nicht mehrere Formate unterstützen, nur ein.

9voto

Tauren Punkte 26017

Ich habe dies funktioniert Hinzufügen der folgenden 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';
};

Ich bin sicher, dass dies die Serialisierung verlangsamt, aber es scheint die Konsistenz zwischen den Browsern zu gewährleisten.

4voto

Marcel Korpel Punkte 21267

Sie könnten auch json2.js ein wenig anpassen, um immer seine eigene Date.prototype.toJSON anstelle einer möglichen einheimischen Version. Hier habe ich zwei Zeilen auskommentiert und es funktioniert korrekt:

// 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();
    };
// }

3voto

kennebec Punkte 98551

// Sie sollten vielleicht in Betracht ziehen, den Server zu verstärken, um jedes gültige ISO 8601-Zeitformat zu erkennen:

'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'

Dies ist eine Methode zur Konvertierung eines beliebigen Iso-Strings in ein Javascript-Datumsobjekt. Es könnte auf dem Server mit einer kleinen Übersetzung verwendet werden:

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;
}

0voto

Suppressingfire Punkte 3168

Warum nicht die formatDate Funktion im Datepicker jQuery-UI-Plugin für jQuery, um das von Ihnen benötigte Format serverseitig zu generieren?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X