2010-02-07 18 views
17

que tengo este código en una página HTML:Discrepancia en JSON.stringify de valores de fecha en distintos navegadores

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

estoy incluyendo la más reciente (versión 2009-09-29) json2.js en mi página a apoyar navegadores más antiguos sin JSON.stringify(). También tengo jquery-1.3.2.js incluido. Creo en los navegadores más nuevos con compatibilidad nativa con JSON, simplemente pasa a la función JSON nativa.

Aquí están los resultados que obtengo en diferentes navegadores:

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" 

Aviso el último? Contiene milisegundos, y ninguno de los otros lo hace. No tengo FF3.5 instalado en ningún otro sistema, pero supongo que tendrían los mismos resultados.

¿Hay algo que pueda hacer para que todas las fechas en todas las plataformas se vinculen de la misma manera? Mi servicio back-end REST se puede configurar con una cadena de formato para deserializar las fechas JSON, pero no admite múltiples formatos, solo uno.

+1

Fwiw, Acabo de prueba FF 3.6 en Win7 y también da milisegundos. –

+2

Publicación relevante en la lista de correo de Mozilla: https://mail.mozilla.org/pipermail/es5-discuss/2008-October/001989.html –

+0

Guau, ¿lo implementaron de esta manera hace unos años? Me sorprende que esto no haya causado más problemas. Aprecio tratar de ser conforme a las normas, pero si todo lo demás lo hace de otra manera, al menos da una opción de configuración para la recuperación. – Tauren

Respuesta

9

Tengo este trabajo añadiendo el siguiente 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'; 
}; 

Estoy seguro de que esto probablemente se ralentiza la serialización, pero parece que las cosas coherente en todos los navegadores.

0

¿Por qué no utilizar la función formatDate en el plugin Datepicker jQuery-UI para que jQuery genere el formato que requiere su servidor?

+0

Estoy pasando una serie de objetos que contienen fechas.Esto significaría pasar por toda la matriz y reemplazar los objetos de fecha con representaciones de cadena de ellos. Esperaba no tener que copiar una matriz existente (generada por una herramienta de terceros) en mi propia versión con cadenas de fechas. Sin embargo, esto podría ser lo que tengo que hacer. ¡Gracias por la sugerencia! – Tauren

+3

'formatoFecha' no es una función jQuery. Parece ser parte de un control datepicker. –

4

También puede ajustar json2.js un poco para usar siempre su propio Date.prototype.toJSON en lugar de uno nativo posible. Aquí estoy sin comentar dos líneas y funciona correctamente:

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

¡Jaja! Acabo de publicar exactamente lo mismo solo 5 segundos después de que ... No creo que deba agregar los prototipos de cadena, número y booleano si solo desea personalizar las fechas. – Tauren

3

// Es posible que desee considerar reforzando el servidor, para reconocer cualquier formato ISO 8601 de tiempo válido:

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

Este es un método para convertir cualquier cadena iso a un objeto de fecha javascript. Podría ser utilizado en el servidor con un poco de traducción:

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

Gracias por el código, puede ser útil en el cliente. Creo que puedo usar Joda Time para analizar los diferentes formatos ISO del lado del servidor. Estoy usando Jersey con el manejo de Jackson JSON para hacer REST en un servidor de Java. Por defecto, intenta convertir desde varios formatos diferentes, pero desafortunadamente solo uno de los que necesito. Tiene una forma de anular el formato, pero con una sola cadena de formato. Estoy seguro de que hay una manera de profundizar y anularlo mejor, pero tendría que dedicarle más tiempo para hacerlo. – Tauren

Cuestiones relacionadas