JavaScript: Quais navegadores suportam a análise de Data String ISO-8601 com Data.parse

Eu não consegui analisar uma data ISO-8601 “2011-04-26T13: 16: 50Z” no IE8 e Safari 5, mas funcionou no Chrome 10, FF4. O suporte parece estar bastante misturado?

Alguém sabe o status real de quais navegadores podem analisar esse formato? Eu assumo IE6, e 7 irá falhar também.

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

Eu tive esse problema hoje. Eu achei que o momentjs era uma boa maneira de analisar datas ISO 8601 em uma mansão cross-browser.

momentjs também pode ser usado para produzir a data em um formato diferente.

Eu digo calço apenas se necessário através de alguns testes,

aqui está uma que eu já escrevi:

 (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 no seu código, use sempre Date.fromString(...) vez de new Date(...)

teste um navegador para ver se o shim será usado:

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

funciona em todos os principais navegadores, usou estas referências:

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/pt-br/library/windows/apps/ff743760(v=vs.94).aspx

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

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

! – microsoft connect requer um login para visualizar:

O IE9 falhava em milissegundos com contagens de dígitos diferentes de 3: (corrigido no IE10) https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid -formatos

O IE10 ainda está (a partir de 1/17/2013) com falha quando o fuso horário é omitido (de acordo com a ECMA, isso deve defchar para Z ou UTC, não local): https://connect.microsoft.com/IE/feedback/ detalhes / 776783 / data-parse-and-new-date-fail-on-format

– Leia isto se você se preocupa com o padrão atual / futuro e por que não consigo fazer com que a equipe do IE reconheça que a implementação do IE10 está tecnicamente incorreta:

ECMAScript-262 v6.0 vai passar para a versão ligeiramente mais compatível com iso8601 de “se o indicador de fuso horário for omitido, assuma a hora local” … então agora há uma discrepância, esta implementação, chrome, safari móvel e ópera todos siga o ECMAScript-262 v5.1, enquanto que o IE10, firefox, safari de desktop parecem estar seguindo a especificação mais compatível com iso8601 ECMAScript-262 v6.0 … isto é confuso para dizer o mínimo. Quando cromo ou safari móvel puxam o gatilho e avançam para a implementação do ES6, acho que essa implementação deve acompanhá-lo, deixando o ES5.1 em minoria. Eu li que isso está listado na “errata” da versão 5.1, embora eu não tenha encontrado. Eu sou mais da opinião de que é um pouco cedo para puxar o gatilho no ES6 ainda, mas eu também sou da opinião que o código precisa ser prático, não ideal e ir para onde os fabricantes de navegadores se mudam. Dito isto, parece ser uma decisão 50/50 agora, então abaixo está a versão “futura” deste código …

Também devo mencionar que qualquer uma das versões do código normalizará os navegadores “não compatíveis” para corresponder ao comportamento do outro, já que é isso que os shims fazem;)

AQUI ESTÁ UMA VERSÃO ADAPTADA COMPATÍVEL COM ECMAScript-262 v6.0 (JavaScript Future)

veja seções relevantes aqui: (esta é a única versão html online da especificação que eu encontrei) 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); }; })(); 

espero que isso ajude -ck

Função simples para analisar o formato de data ISO8601 em qualquer navegador:

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

Sim, Date.parse não é consistente para diferentes navegadores. Você poderia:

  • Use Date.UTC , que divide a cadeia de datas em inputs separadas
  • Use uma biblioteca wrapper como parseDate do jQuery

Alguns navegadores mais antigos retornam a data errada (e não NaN) se você analisar uma string de data ISO.

Você pode usar seu próprio método em todos os navegadores ou usar Date.parse se ele for implementado corretamente – verifique um timestamp conhecido.

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

A especificação ES5 se desvia da especificação ISO8601, especialmente quando se trata do tratamento de datas sem um indicador / deslocamento de fuso horário. Há um ticket de bug em https://bugs.ecmascript.org/show_bug.cgi?id=112 descrevendo o problema e parece que ele será corrigido no ES6.

Por enquanto, recomendo olhar para https://github.com/csnover/js-iso8601 para uma implementação entre navegadores. Eu uso https://github.com/csnover/js-iso8601/tree/lax que não está em conformidade com a especificação ES5, mas tem melhor interoperabilidade com outras bibliotecas de serialização JSON como o JSON.NET.

Eu encontrei resposta ckozl realmente útil e interessante, mas o regexp não é perfeito e não funcionou no meu caso.

Além do fato de que datas sem minutos, segundos ou milissegundos não são analisadas, a especificação ISO 8501 diz que os separadores ‘-‘ e ‘:’ são opcionais, então “2013-12-27” e “20131227” são ambos válidos. No meu caso, isso é importante porque estou configurando a data e hora do servidor em uma variável JavaScript do PHP:

 var serverDate = new Date(Date.parse("< ?php date(DateTime::ISO8601); ?>")); 

Este código gera algo parecido com isto:

  

A parte importante é o designador de fuso horário “+0100”, em que o ‘:’ está ausente. Embora o Firefox analise essa string corretamente, o IE (11) falha (se o ‘:’ for adicionado, o IE também funciona). A dor de cabeça sobre o zonetime e as especificações do ECMAScript descritas por ckozl não é importante no meu caso, porque o PHP sempre adiciona o designador de fuso horário.

O RegExp que estou usando, em vez daquele do 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}))?)?)?)?)?$/; 

Tenha em mente que este regexp também não é perfeito. O ISO 8501 permite a especificação de semana (2007-W01-1 para segunda-feira, 1 de janeiro de 2007) ou frações decimais em horas e minutos (18,50 para 18:30:00 ou 18: 30,25 para 18:30:15). Mas eles são bastante incomuns.

PD Esta resposta deve ser, imagino, um comentário para a resposta original do chozl, mas eu não tenho reputação suficiente 🙁

Como mencionado anteriormente, as datas do estilo ISO 8601 foram adicionadas na versão 5 do ECMAScript, onde a implementação não é consistente e não está disponível em todos os navegadores. Há vários stubs de script disponíveis, mas você pode simplesmente adicionar seu próprio método 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; } }(); 

Eu uso o método acima para hidratação JSON.parse de datas …

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

Os formatos de data ISO 8601 foram adicionados ao ECMAScript-262 v5. Portanto, se um navegador não for compatível com v5, você simplesmente não poderá ser capaz de lidar com os formatos ISO 8601.

Os navegadores que não são compatíveis com v5 podem usar qualquer formato de data específico de implementação desejado. A maioria deles suporta pelo menos formatos de data RFC822 / RFC1123 . Exemplo:

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

O Microsoft Sharepoint 2013 também está usando uma notação diferente, por exemplo, “2013-04-30T22: 00: 00Z”

Se você quiser usar os serviços REST do sharepoint 2013 em combinação com o Internet Explorer 8 (IE8), a solução do ckozl NÃO estará funcionando. Você vai ter o NaN

altere a linha de expressão para:

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

isso fará com que os microssegundos sejam um pouco opcionais!

cheerio, leonardo