JavaScript: quali browser supportano l’analisi della stringa di data ISO-8601 con Date.parse

Non sono riuscito a analizzare una data ISO-8601 “2011-04-26T13: 16: 50Z” su IE8 e Safari 5, ma ha funzionato su Chrome 10, FF4. Il supporto sembra essere abbastanza misto?

Qualcuno conosce lo stato attuale di quali browser possono analizzare questo formato? Presumo IE6, e 7 fallirà anche.

var d = Date.parse("2011-04-26T13:16:50Z"); 

Ho avuto questo problema oggi. Ho trovato momentjs era un buon modo di analizzare le date ISO 8601 in un maniero cross browser.

momentjs può anche essere usato per stampare la data in un formato diverso.

Dico shim solo se necessario tramite alcuni test,

ecco uno che ho già scritto:

 (function() { var d = window.Date, regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,3})(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/; if (d.parse('2011-11-29T15:52:30.5') !== 1322581950500 || d.parse('2011-11-29T15:52:30.52') !== 1322581950520 || d.parse('2011-11-29T15:52:18.867') !== 1322581938867 || d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 || d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 || d.parse('2011-11-29') !== 1322524800000 || d.parse('2011-11') !== 1320105600000 || d.parse('2011') !== 1293840000000) { d.__parse = d.parse; d.parse = function(v) { var m = regexIso8601.exec(v); if (m) { return Date.UTC( m[1], (m[2] || 1) - 1, m[3] || 1, m[4] - (m[8] ? m[8] + m[9] : 0) || 0, m[5] - (m[8] ? m[8] + m[10] : 0) || 0, m[6] || 0, ((m[7] || 0) + '00').substr(0, 3) ); } return d.__parse.apply(this, arguments); }; } d.__fromString = d.fromString; d.fromString = function(v) { if (!d.__fromString || regexIso8601.test(v)) { return new d(d.parse(v)); } return d.__fromString.apply(this, arguments); }; })(); 

e nel tuo codice usa sempre Date.fromString(...) invece di new Date(...)

prova un browser per vedere se lo shim sarà usato:

http://jsbin.com/efivib/1/edit

funziona in tutti i principali browser, usa questi riferimenti:

http://dev.w3.org/html5/spec/common-microsyntaxes.html

http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15

http://msdn.microsoft.com/en-us/library/windows/apps/ff743760(v=vs.94).aspx

http://msdn.microsoft.com/en-us/library/windows/apps/wz6stk2z(v=vs.94).aspx

http://msdn.microsoft.com/en-us/library/windows/apps/k4w173wk(v=vs.94).aspx

! – Microsoft connect richiede un accesso per visualizzare:

IE9 non funzionava in millisecondi con numero di cifre diverso da 3: (corretto in IE10) https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid -formats

IE10 è ancora (a partire dal 1/17/2013) in mancanza quando il fuso orario viene omesso (secondo ECMA, questo dovrebbe defaltare in Z o UTC, non in locale): https://connect.microsoft.com/IE/feedback/ dettagli / 776.783 / new-date-fail-on-valid-formati data-analizzare-e-

– Leggi questo se ti interessa il punto in cui lo standard è ora / sta andando in futuro e perché non riesco a convincere il team di IE a riconoscere che la loro implementazione di IE10 è tecnicamente errata:

ECMAScript-262 v6.0 passerà alla versione leggermente più iso8601 di “se l’indicatore del fuso orario è omesso, si assume l’ora locale” … quindi ora c’è una discrepanza, questa implementazione, chrome, mobile safari e opera tutti seguire ECMAScript-262 v5.1, mentre IE10, firefox, desktop safari sembrano seguire la specifica ECMAScript-262 v6.0 conforms alle specifiche iso8601 … questo è a dir poco complicato. Quando cromo o mobile safari spingono il grilletto e passano all’implementazione ES6, penso che questa implementazione dovrebbe andare con esso lasciando ES5.1 in minoranza. Ho letto che questo è elencato nell ‘”errata” della versione 5.1 sebbene non l’abbia trovato. Sono più dell’opinione che sia ancora un po ‘presto a tirare il grilletto su ES6, ma sono anche dell’opinione che il codice debba essere pratico, non ideale e spostarsi dove i produttori di browser si trasferiscono. Detto questo, sembra essere una decisione 50/50 in questo momento, quindi di seguito è la versione “futura” di questo codice …

Dovrei anche menzionare che entrambe le versioni del codice normalizzeranno i browser “non conformi” in modo che corrispondano al comportamento dell’altro, poiché è ciò che fanno gli shim;)

ECCO una VERSIONE ADATTATA COMPATIBILE CON ECMAScript-262 v6.0 (JavaScript Future)

vedere le sezioni pertinenti qui: (questa è l’unica versione html online delle specifiche che ho trovato) http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.9.1.15

 (function() { var d = window.Date, regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,})(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/, lOff, lHrs, lMin; if (d.parse('2011-11-29T15:52:30.5') !== 1322599950500 || d.parse('2011-11-29T15:52:30.52') !== 1322599950520 || d.parse('2011-11-29T15:52:18.867') !== 1322599938867 || d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 || d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 || d.parse('2011-11-29') !== 1322524800000 || d.parse('2011-11') !== 1320105600000 || d.parse('2011') !== 1293840000000) { d.__parse = d.parse; lOff = -(new Date().getTimezoneOffset()); lHrs = Math.floor(lOff / 60); lMin = lOff % 60; d.parse = function(v) { var m = regexIso8601.exec(v); if (m) { return Date.UTC( m[1], (m[2] || 1) - 1, m[3] || 1, m[4] - (m[8] ? m[9] ? m[9] + m[10] : 0 : lHrs) || 0, m[5] - (m[8] ? m[9] ? m[9] + m[11] : 0 : lMin) || 0, m[6] || 0, ((m[7] || 0) + '00').substr(0, 3) ); } return d.__parse.apply(this, arguments); }; } d.__fromString = d.fromString; d.fromString = function(v) { if (!d.__fromString || regexIso8601.test(v)) { return new d(d.parse(v)); } return d.__fromString.apply(this, arguments); }; })(); 

spero che questo aiuti -ck

Funzione semplice per analizzare il formato data ISO8601 in qualsiasi browser:

 function dateFromISO8601(isoDateString) { var parts = isoDateString.match(/\d+/g); var isoTime = Date.UTC(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]); var isoDate = new Date(isoTime); return isoDate; } 

Sì, Date.parse non è coerente per i diversi browser. Potresti:

  • Utilizza invece Date.UTC , che suddivide la stringa della data in input separati
  • Usa una libreria di wrapper come parseDate di jQuery

Alcuni browser più vecchi restituiscono la data errata (e non NaN) se si analizza una stringa di data ISO.

Puoi utilizzare il tuo metodo su tutti i browser o utilizzare Date.parse se è implementato correttamente- controlla un timestamp noto.

 Date.fromISO= (function(){ var diso= Date.parse('2011-04-26T13:16:50Z'); if(diso=== 1303823810000) return function(s){ return new Date(Date.parse(s)); } else return function(s){ var day, tz, rx= /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/, p= rx.exec(s) || []; if(p[1]){ day= p[1].split(/\D/).map(function(itm){ return parseInt(itm, 10) || 0; }); day[1]-= 1; day= new Date(Date.UTC.apply(Date, day)); if(!day.getDate()) return NaN; if(p[5]){ tz= parseInt(p[5], 10)*60; if(p[6]) tz += parseInt(p[6], 10); if(p[4]== "+") tz*= -1; if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz); } return day; } return NaN; } })() 

Le specifiche ES5 si discostano dalle specifiche ISO8601, specialmente per quanto riguarda il trattamento delle date senza un indicatore / offset fuso orario. C’è un bug ticket su https://bugs.ecmascript.org/show_bug.cgi?id=112 che descrive il problema e sembra che verrà risolto in ES6.

Per ora, consiglio di consultare https://github.com/csnover/js-iso8601 per un’implementazione cross-browser. Uso https://github.com/csnover/js-iso8601/tree/lax che non è conforms alle specifiche ES5 ma ha una migliore interoperabilità con altre librerie di serializzazione JSON come JSON.NET.

Ho trovato la risposta ckozl davvero utile e interessante, ma l’espressione regolare non è perfetta e non ha funzionato nel mio caso.

A parte il fatto che non vengono analizzate date senza minuti, secondi o millisecondi, la specifica ISO 8501 dice che i separatori ‘-‘ e ‘:’ sono opzionali, quindi “2013-12-27” e “20131227” sono entrambi validi. Nel mio caso, questo è importante perché sto impostando la data e l’ora del server in una variabile JavaScript da PHP:

 var serverDate = new Date(Date.parse("")); 

Questo codice genera qualcosa come questo:

  

La parte importante è la designazione del fuso orario “+0100” in cui manca “:”. Sebbene Firefox analizzi correttamente quella stringa, IE (11) non riesce (se viene aggiunto “:”, allora anche IE funziona). Il mal di testa relativo alle specifiche zonetime e ECMAScript descritte da ckozl non è importante nel mio caso, poiché PHP aggiunge sempre il designatore del fuso orario.

Il RegExp che sto usando, invece di quello di ckozl è:

 var regexIso8601 = /^(\d{4}|\+\d{6})(?:-?(\d{2})(?:-?(\d{2})(?:T(\d{2})(?::?(\d{2})(?::?(\d{2})(?:(?:\.|,)(\d{1,}))?)?)?(Z|([\-+])(\d{2})(?::?(\d{2}))?)?)?)?)?$/; 

Tieni presente che questa regexp non è perfetta neanche. ISO 8501 consente le specifiche settimanali (2007-W01-1 per lunedì, 1 gennaio 2007) o le frazioni decimali in ore e minuti (18,50 per 18:30:00 o 18: 30,25 per 18:30:15). Ma sono piuttosto inusuali.

PD Questa risposta dovrebbe essere, immagino, un commento alla risposta originale di chozl, ma non ho abbastanza reputazione 🙁

Come accennato in precedenza, le date di stile ISO 8601 sono state aggiunte in ECMAScript versione 5, in cui l’implementazione non è coerente e non è disponibile in tutti i browser. Sono disponibili numerosi stub di script, ma potresti semplicemente aggiungere il tuo metodo Date.parse *.

 (function() { //ISO-8601 Date Matching var reIsoDate = /^(\d{4})-(\d{2})-(\d{2})((T)(\d{2}):(\d{2})(:(\d{2})(\.\d*)?)?)?(Z|[+-]00(\:00)?)?$/; Date.parseISO = function(val) { var m; m = typeof val === 'string' && val.match(reIsoDate); if (m) return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[6] || 0, +m[7] || 0, +m[9] || 0, parseInt((+m[10]) * 1000) || 0)); return null; } //MS-Ajax Date Matching var reMsAjaxDate = /^\\?\/Date\((\-?\d+)\)\\?\/$/; Date.parseAjax = function(val) { var m; m = typeof val === 'string' && val.match(reMsAjaxDate); if (m) return new Date(+m[1]); return null; } }(); 

Io uso il metodo sopra per l’idratazione JSON.parse delle date …

 JSON.parse(text, function(key, val) { return Date.parseISO(val) || Date.parseAjax(val) || val; }); 

I formati di data ISO 8601 sono stati aggiunti con ECMAScript-262 v5. Quindi, se un browser non è compatibile con V5, semplicemente non puoi aspettarti di essere in grado di gestire i formati ISO 8601.

I browser che non sono compatibili con V5 possono utilizzare qualsiasi formato di data specifico per l’implementazione che desiderano. La maggior parte di questi supporta almeno i formati di data RFC822 / RFC1123 . Esempio:

 var d = Date.parse("Wed, 26 Apr 2011 13:16:50 GMT+0200"); 

Anche Microsoft Sharepoint 2013 utilizza una notazione diversa, ad esempio “2013-04-30T22: 00: 00Z”

Se si desidera utilizzare i servizi REST da SharePoint 2013 in combinazione con Internet Explorer 8 (IE8), la soluzione di ckozl NON funziona. Otterrai il NaN

cambia la linea di regex in:

 regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(\.(\d{1,3}))?(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/; 

questo renderà il bit microsecondo opzionale!

cheerio, Leo