validate - JavaScript: qué navegadores admiten el análisis de la cadena de fecha ISO-8601 con Date.parse
new date javascript format dd mm yyyy (10)
No pude analizar una fecha ISO-8601 "2011-04-26T13: 16: 50Z" en IE8 y Safari 5, pero funcionó en Chrome 10, FF4. El soporte parece estar bastante mezclado?
¿Alguien sabe el estado actual de qué navegadores pueden analizar este formato? Supongo que IE6, y 7 también fallarán.
var d = Date.parse("2011-04-26T13:16:50Z");
Algunos navegadores más antiguos devuelven la fecha incorrecta (y no NaN) si analiza una cadena de fecha ISO.
Puede usar su propio método en todos los navegadores, o usar Date.parse si se implementa correctamente: verifique una marca de tiempo conocida.
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;
}
})()
Como se mencionó anteriormente, las fechas de estilo ISO 8601 se agregaron en ECMAScript versión 5, donde la implementación no es consistente y no está disponible en todos los navegadores. Hay una number of apuntes of guiones disponibles, pero es posible que desee simplemente agregar su propio 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;
}
}();
Utilizo el método anterior para la hidratación de fechas JSON.parse ...
JSON.parse(text, function(key, val) {
return Date.parseISO(val) || Date.parseAjax(val) || val;
});
Encontré la respuesta de ckozl realmente útil e interesante, pero la expresión regular no es perfecta y no funcionó en mi caso.
Además del hecho de que las fechas sin minutos, segundos o milisegundos no se analizan, la especificación ISO 8501 dice que los separadores ''-'' y '':'' son opcionales, por lo que "2013-12-27" y "20131227" son ambos válidos. En mi caso, esto es importante porque estoy configurando la fecha y hora del servidor en una variable de JavaScript desde PHP:
var serverDate = new Date(Date.parse("<?php date(DateTime::ISO8601); ?>"));
Este código genera algo como esto:
<script>
var serverDate = new Date(Date.parse("2013-12-27T15:27:34+0100"));
</script>
La parte importante es el designador de zona horaria "+0100" donde falta el '':''. Aunque Firefox analiza esa cadena correctamente, IE (11) falla (si se agrega '':'', IE también funciona). El dolor de cabeza acerca de zonetime y las especificaciones de ECMAScript descritas por ckozl no es importante en mi caso, porque PHP siempre agrega el designador de zona horaria.
El RegExp que estoy usando, en lugar de aquel de ckozl es:
var regexIso8601 = /^(/d{4}|/+/d{6})(?:-?(/d{2})(?:-?(/d{2})(?:T(/d{2})(?::?(/d{2})(?::?(/d{2})(?:(?:/.|,)(/d{1,}))?)?)?(Z|([/-+])(/d{2})(?::?(/d{2}))?)?)?)?)?$/;
Tenga en cuenta que esta expresión regular tampoco es perfecta. ISO 8501 permite la especificación de la semana (2007-W01-1 para el lunes 1 de enero de 2007), o fracciones decimales en horas y minutos (18.50 para 18:30:00, o 18: 30.25 para 18:30:15). Pero son bastante inusuales.
PD Esta respuesta debería ser, supongo, un comentario a la respuesta original de Chozl, pero no tengo suficiente reputación :(
Función simple para analizar el formato de fecha ISO8601 en cualquier 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;
}
La especificación ES5 se desvía de la especificación ISO8601, especialmente cuando se trata del tratamiento de fechas sin un indicador / desviación de zona horaria. Hay un error en https://bugs.ecmascript.org/show_bug.cgi?id=112 describe el problema y parece que se solucionará en ES6.
Por ahora, recomiendo consultar https://github.com/csnover/js-iso8601 para una implementación entre navegadores. Uso https://github.com/csnover/js-iso8601/tree/lax que no se ajusta a la especificación ES5 pero tiene una mejor interoperabilidad con otras bibliotecas de serialización JSON como JSON.NET.
Microsoft Sharepoint 2013 TAMBIÉN está utilizando una notación diferente, por ejemplo, "2013-04-30T22: 00: 00Z"
Si desea utilizar los servicios REST de sharepoint 2013 en combinación con Internet Explorer 8 (IE8), entonces la solución de ckozl NO está funcionando. Obtendrás el NaN
cambiar la línea de expresiones regulares a:
regexIso8601 = /^(/d{4}|/+/d{6})(?:-(/d{2})(?:-(/d{2})(?:T(/d{2}):(/d{2}):(/d{2})(/.(/d{1,3}))?(?:Z|([/-+])(/d{2}):(/d{2}))?)?)?)?$/;
¡Esto hará que los microsegundos sean poco opcionales!
Cheerio, Leo
Sí, Date.parse no es consistente para diferentes navegadores. Tú podrías:
- Use Date.UTC en Date.UTC lugar, que divide la cadena de fecha en entradas separadas
- Use una biblioteca contenedora como parseDate de jQuery
Tuve este problema hoy. Descubrí que momentjs era una buena forma de analizar las fechas de ISO 8601 en un feudo de navegador cruzado.
momentjs también se puede usar para mostrar la fecha en un formato diferente.
Yo digo que lo calce solo si es necesario a través de algunas pruebas,
aquí hay uno que ya he escrito:
(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);
};
})();
y en su código siempre use Date.fromString(...)
lugar de new Date(...)
prueba un navegador para ver si se usará la cuña:
http://jsbin.com/efivib/1/edit
funciona en todos los principales navegadores, usó estas referencias:
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 requiere un inicio de sesión para ver:
IE9 fallaba en milisegundos con conteos de dígitos que no eran 3: (corregidos en IE10) https://connect.microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail-on-valid-formats
IE10 aún (a partir del 1/17/2013) falla cuando se omite el huso horario (según ECMA, esto debe desvanecerse a Z o UTC, no local): https://connect.microsoft.com/IE/feedback/details/776783/date-parse-and-new-date-fail-on-valid-formats
- Lea esto si le importa dónde está el estándar ahora / en el futuro y por qué no puedo lograr que el equipo de IE reconozca que su implementación de IE10 es técnicamente incorrecta:
ECMAScript-262 v6.0 pasará a la versión un poco más iso8601 de "si se omite el indicador de zona horaria, asuma la hora local" ... entonces ahora hay una discrepancia, esta implementación, Chrome, safari móvil y opera todo siga ECMAScript-262 v5.1, mientras que IE10, firefox, desktop safari parecen seguir la especificación ECMAScript-262 v6.0 más iso8601 ... esto es confuso, por decir lo menos. Cuando Chrome o el safari móvil aprietan el gatillo y pasan a la implementación de ES6, creo que esta implementación debería irse, dejando a ES5.1 en minoría. He leído que esto aparece en la "errata" de la versión 5.1, aunque no lo he encontrado. Tengo más la opinión de que es un poco pronto para apretar el gatillo en ES6 por el momento, pero también opino que el código debe ser práctico, no ideal y moverse hacia donde se mueven los fabricantes de navegadores. Dicho esto, parece ser una decisión 50/50 en este momento, por lo que a continuación se muestra la versión "futura" de este código ...
También debo mencionar que cualquier versión del código normalizará los navegadores "no conformes" para que coincida con el comportamiento del otro, ya que eso es lo que hacen los calzos;)
AQUÍ HAY UNA VERSIÓN ADAPTADA COMPATIBLE CON ECMAScript-262 v6.0 (JavaScript Future)
vea las secciones relevantes aquí: (esta es la única versión html en línea de la especificación que pude encontrar) 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 esto ayude -ck
Los formatos de fecha ISO 8601 se agregaron con ECMAScript-262 v5. Entonces, si un navegador no es compatible con v5, simplemente no puede esperar ser capaz de manejar formatos ISO 8601.
Los navegadores que no son compatibles con v5 pueden usar cualquier formato de fecha específico de implementación que deseen. La mayoría de ellos al menos admiten formatos de fecha RFC822 / RFC1123 . Ejemplo:
var d = Date.parse("Wed, 26 Apr 2011 13:16:50 GMT+0200");