2013-02-17 5 views
8

Esegui il jsfiddle: http://jsfiddle.net/E9gq9/7/ su Chrome, FF, e IE e si ottiene:Chrome interpreta l'ora ISO senza Z come UTC; C# problema

Chrome:

Chrome http://images.devs-on.net/Image/vBTz86J0f4o8zlL3-Region.png

Firefox:

Firefox http://images.devs-on.net/Image/aNPxNPUpltyjVpSX-Region.png

IE:

IE http://images.devs-on.net/Image/WXLM5Ev1Viq4ecFq-Region.png

Safari:

Safari http://images.devs-on.net/Image/AEcyUouX04k2yIPo-Region.png

ISO 8601 non sembra dire come una stringa senza Z posteriore dovrebbe essere interpretato.

Il nostro server (ASP.NET MVC4) trascina le ore UTC dal nostro database come DateTime s e li inserisce semplicemente in JSON. Come puoi vedere per questo stiamo ottenendo risultati incoerenti sul browser.

Dovremmo semplicemente aggiungere Z a loro sul lato server?

+0

Opera ci piace Chrome btw. – Bergi

risposta

10

Chrome interpreta l'ora ISO senza Z come UTC; C# issue

Quale è corretto, sono Firefox e IE che si sbagliano.

Mentre l'articolo si è collegato in effetti dire che cosa significa quando non c'è Z ("In assenza di informazioni UTC relazione viene dato con una rappresentazione del tempo, il tempo si presume essere in tempo locale".), tanto più cosa importante è che il ECMAScript5 specification dice chiaramente che nessuna informazione fuso orario significa Z:

il valore di una differenza di fuso orario è assente “Z”.

Sì, probabilmente mi assicuro che la stringa abbia un Z su di esso, in quanto sembra dare risultati coerenti.

+0

Tuttavia, si dovrebbe notare anche che [IE precedenti non riescono ad analizzare interamente ISO 8601] (http://msdn.microsoft.com/en-us/library/ie/ff743760 (v = vs.94) .aspx). Niente nell'analisi della data di JS è coerente :-( – Bergi

+5

Wow. Questo è sicuramente quello che dice la specifica ECMAScript - ma è molto rotto, IMO - e direttamente contro ISO-8601, che afferma: "La designazione della zona è vuota se l'uso è fatto di locale tempo in accordo con il 4.2.2.2 al 4.2.2.4. "Sigh." Ti prego, dato che verrà analizzato come un istante nel tempo, direi che l'intera API è rotta. Doppio sospiro. –

+0

@Berg: Questo è perché questo è nuovo come da ECMAScript5. Incredibilmente, anche ECMAScript3 non dettava ** alcuna ** stringa data/ora che un motore doveva analizzare, se non per dire che doveva analizzare qualunque cosa 'Date # toString' sputava - - ma non dettava ciò che era. La buona notizia è che non esiste un browser principale che non analizzerà 'yyyy/MM/dd' (deve essere'/', non' -'), anche se non è mai stato standardizzato. La cattiva notizia è che i diversi browser fanno chiamate diverse sul fatto che debba essere locale o UTC –

5

Alla fine della giornata, il problema che sto affrontando in questa app può essere risolto se il mio server invia sempre gli oggetti client DateTime in un formato che tutti i browser gestiscono correttamente.

Ciò significa che deve esserci quella "Z" alla fine. Risulta che il serializzatore ASP.NET MVC4 Json è basato su Json.NET, ma non ha Utc attivato per impostazione predefinita. L'impostazione predefinita per DateTimeZoneHandling sembra essere RoundtripKind e questo non restituisce i valori con Z su di essi, anche se DateTime.Kind == Utc, che è piuttosto fastidioso.

Quindi la correzione sembra essere, impostare come Json.NET gestisce i fusi orari per DateTimeZoneHandling.Utc:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter; 
// Force Utc formatting ('Z' at end). 
json.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; 

Ora, tutto ciò che scende il filo dal mio server al browser è formattato come ISO-8601 con una 'Z' alla fine. E tutti i browser che ho provato fanno la cosa giusta con questo.

+0

+1 Questo era esattamente quello che stavo cercando. –

2

Mi sono imbattuto in questo problema e interpretare la data con il fuso orario locale ha molto più senso che passare a "Z", almeno per la mia applicazione. Ho creato questa funzione per aggiungere le informazioni sul fuso orario locale quando manca nella data ISO. Questo può essere usato al posto di una nuova data(). Parzialmente derivato da questa risposta: How to ISO 8601 format a Date with Timezone Offset in JavaScript?

parseDate = function (/*String*/ d) { 
    if (d.search(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/) == 0) { 
     var pad = function (num) { 
      norm = Math.abs(Math.floor(num)); 
      return (norm < 10 ? '0' : '') + norm; 
     }, 
     tzo = -(new Date(d)).getTimezoneOffset(), 
     sign = tzo >= 0 ? '+' : '-'; 
     return new Date(d + sign + pad(tzo/60) + ':' + pad(tzo % 60)); 
    } else { 
     return new Date(d); 
    } 
} 
0

David Hammond answer è grande, ma non gioca tutti i trucchi; ecco una versione modificata:

  • consente una parte frazionaria nella stringa data/ora
  • permette di secondi facoltative stringa di data/ora
  • ritiene che attraversano più ora legale
appendTimezone = function (/*String*/ d) { 
    // check for ISO 8601 date-time string (seconds and fractional part are optional) 
    if (d.search(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1-3})?)?$/) == 0) { 
     var pad = function (num) { 
      norm = Math.abs(Math.floor(num)); 
      return (norm < 10 ? '0' : '') + norm; 
     }, 
     tzo = -new Date(d).getTimezoneOffset(), 
     sign = tzo >= 0 ? '+' : '-'; 

     var adjusted = d + sign + pad(tzo/60) + ':' + pad(tzo % 60); 

     // check whether timezone offsets are equal; 
     // if not then the specified date is just within the hour when the clock 
     // has been turned forward or back 
     if (-new Date(adjusted).getTimezoneOffset() != tzo) { 
      // re-adjust 
      tzo -= 60; 
      adjusted = d + sign + pad(tzo/60) + ':' + pad(tzo % 60); 
     } 

     return adjusted; 
    } else { 
     return d; 
    } 
} 

parseDate = function (/*String*/ d) { 
    return new Date(appendTimezone(d)); 
}