Fecha inválida en safari

155
 alert(new Date('2010-11-29'));

chrome, ff no tiene problemas con esto, pero safari grita "fecha inválida". Por qué ?

editar: ok, según los comentarios a continuación, utilicé el análisis de cadenas y probé esto:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

editar 22 de marzo de 2018 : Parece que la gente todavía está aterrizando aquí: hoy, usaría momento date-fnsterminaría. Date-fns es muy libre de dolor y ligero también.

Shrinath
fuente
Solo para otros que buscan el mismo problema: terminé usando DateJS, que resolvió mi problema en general. Vea la respuesta aceptada para más detalles.
Shrinath
2
use moment.js para analizar la marca de tiempo. Especialmente cuando se trata de web multiplataforma
Ming Yuen
1
Esta es una vieja pregunta. A partir de ECMAScript 2015, las cadenas de fecha ISO 8601 solo se analizan como UTC. Sin embargo, todavía puede haber navegadores más antiguos que no lo analicen en absoluto o lo traten como local.
RobG

Respuestas:

167

El patrón yyyy-MM-ddno es un formato oficialmente compatible para el Dateconstructor. Firefox parece admitirlo, pero no cuente con que otros navegadores hagan lo mismo.

Aquí hay algunas cadenas compatibles:

  • MM-dd-aaaa
  • aaaa / MM / dd
  • MM / dd / aaaa
  • MMMM dd, aaaa
  • MMM dd, aaaa

DateJS parece una buena biblioteca para analizar formatos de fecha no estándar.

Editar : acabo de comprobar el estándar ECMA-262 . Citando de la sección 15.9.1.15:

Fecha Hora Cadena Formato

ECMAScript define un formato de intercambio de cadenas para fechas y horas basado en una simplificación del formato extendido ISO 8601. El formato es el siguiente: AAAA-MM-DDTHH: mm: ss.sssZ Donde los campos son los siguientes:

  • AAAA son los dígitos decimales del año en el calendario gregoriano.
  • "-" (hyphon) aparece literalmente dos veces en la cadena.
  • MM es el mes del año del 01 (enero) al 12 (diciembre).
  • DD es el día del mes del 01 al 31.
  • "T" aparece literalmente en la cadena, para indicar el comienzo del elemento de tiempo.
  • HH es el número de horas completas que han pasado desde la medianoche como dos dígitos decimales.
  • ":" (dos puntos) aparece literalmente dos veces en la cadena.
  • mm es el número de minutos completos desde el comienzo de la hora como dos dígitos decimales.
  • ss es el número de segundos completos desde el comienzo del minuto como dos dígitos decimales.
  • "." (punto) aparece literalmente en la cadena.
  • sss es el número de milisegundos completos desde el comienzo del segundo como tres dígitos decimales. Ambos "." y el campo de milisegundos puede omitirse.
  • Z es el desplazamiento de zona horaria especificado como "Z" (para UTC) o "+" o "-" seguido de una expresión de tiempo hh: mm

Este formato incluye formularios solo de fecha:

  • AAAA
  • AAAA-MM
  • AAAA-MM-DD

También incluye formularios de solo hora con un desplazamiento de zona horaria opcional añadido:

  • THH: mm
  • THH: mm: ss
  • THH: mm: ss.sss

También se incluyen "fechas-horas" que pueden ser cualquier combinación de lo anterior.

Entonces, parece que AAAA-MM-DD está incluido en el estándar, pero por alguna razón, Safari no lo admite.

Actualización : después de mirar la documentación de datejs , usarla, su problema debe resolverse usando un código como este:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");
darioo
fuente
44
El formato ISO8601 se usa en la quinta edición del estándar ECMAScript, y aún no es ampliamente compatible, la forma más segura de ir a la OMI, analiza la fecha manualmente :(
CMS
1
Eso fue muy útil amigo ... Gracias ... :) Finalmente terminé usando datejs para formatear.
Shrinath
para aquellos en el futuro, tenga en cuenta que si bien datejs es fantástico en la mayoría de los aspectos, no resuelve todos los problemas de formato de fecha, particularmente con safari. es un PITA, pero es mejor hacerlo manualmente si aún tiene problemas.
totallyNotLizards
@darioo Intenté su respuesta de la siguiente manera: "var start = Date.parseExact (marca de tiempo," AAAA-DD-MM HH: mm: SS ");" la marca de tiempo es "2016-01-28 00:00:00". Sin embargo, ahora aparece el error, que "Date.parseExact no es una función". ¿Sabes qué está pasando aquí?
threxx
55
Mi problema similar fue causado por Safari al no saber cómo leer la zona horaria en un formato de zona horaria RFC 822. Pude solucionar esto usando el formato ISO 8601. Si tiene control del formato de fecha, obtuve esto trabajando con "aaaa-MM-dd'T'HH: mm: ss.sssXXX" que crea, es decir. "2018-02-06T20: 00: 00.000 + 00: 00". Por alguna razón Safari no puede leer "2018-02-06T20: 00: 00.000 + 0000", observe la falta de dos puntos en el formato de zona horaria.
Olmstov
224

Para mí, implementar una nueva biblioteca solo porque Safari no puede hacerlo correctamente es demasiado y una expresión regular es exagerada. Aquí está el oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));
Elzo Valugi
fuente
Si obtener un corte fue solo mi problema, entonces habría 'aceptado' su respuesta (aunque era mi único objetivo cuando hice esta pregunta). ¡Ahora que encontré dateJS, implementé el formato MMM DD, AAAA para una experiencia más fácil de usar!
Shrinath
13
¡Esta línea de ayuda fue perfecta para mi necesidad! ¡Gracias!
Cyril N.
44
Esto fue bastante simple para mí también. No puedo creer que a Safari no le guste, pero el mismo formato con un \\ funciona. Gracias @Elzo y gracias Shrinath por publicar la pregunta
Pete
1
Creo que esta es la mejor respuesta que tiendo a olvidar / - / g en lugar de '-'
Jacek Pietal
12
aplausos por no implementar una biblioteca.
lharby
56

Estaba enfrentando un problema similar. Date.Parse("DATESTRING")estaba trabajando en Chrome (Versión 59.0.3071.115) pero no en Safari (Versión 10.1.1 (11603.2.5))

Safari:

Date.parse("2017-01-22 11:57:00")
NaN

Cromo:

Date.parse("2017-01-22 11:57:00")
1485115020000

La solución que funcionó para mí fue reemplazar el espacio en dateString con "T". (Ejemplo: dateString.replace(/ /g,"T"))

Safari:

Date.parse("2017-01-22T11:57:00")
1485086220000

Cromo:

Date.parse("2017-01-22T11:57:00")
1485115020000

Tenga en cuenta que la respuesta del navegador Safari es 8 horas (28800000 ms) menor que la respuesta vista en el navegador Chrome porque Safari devolvió la respuesta en TZ local (que está 8 horas detrás de UTC)

Para obtener los dos tiempos en la misma TZ

Safari:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Cromo:

Date.parse("2017-01-22T11:57:00Z")
1485086220000
nizantz
fuente
O si desea que ambas fechas sean iguales en Safari y Chrome, puede usar el new Date(year, month, date, hours, minutes, seconds, milliseconds)constructor. Analice la fecha de la cadena a una matriz de sus componentes para usar esos componentes en el constructor. @nizantz sería genial si crees que ese ejemplo podría agregarse a tu respuesta.
h3dkandi
No es particularmente útil ya que obtiene la fecha en UTC y no la hora local.
Jonas Äppelgran
1
Esta dateString.replace(/ /g,"T")línea mágica de código funcionó conmigo. :)
Mazdak Shojaie
reemplazar (/ - / g, '/')
Jack Hu
11

Utilizo momento para resolver el problema. Por ejemplo

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();
liwp_Stephen
fuente
10

Para tener una solución que funcione en la mayoría de los navegadores, debe crear su objeto de fecha con este formato

(year, month, date, hours, minutes, seconds, ms)

p.ej:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

funciona bien con IE, FF, Chrome y Safari. Incluso versiones anteriores.

IE Dev Center: Fecha Objeto (JavaScript)

Mozilla Dev Network: Fecha

Luxx
fuente
6

convertir cadena a Fecha desde (debe conocer la zona horaria del servidor)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

donde +08: 00 = timeZone del servidor

Anja Ishmukhametova
fuente
Esto no tiene en cuenta el horario de verano. El desplazamiento de TZ puede fluctuar y depende de la fecha misma (y la hora).
costa
5

Tuve el mismo problema. Luego usé el momento. Js. El problema ha desaparecido.

Al crear un momento a partir de una cadena, primero verificamos si la cadena coincide con los formatos ISO 8601 conocidos, luego volvemos a la nueva Fecha (cadena) si no se encuentra un formato conocido.

Advertencia: El soporte del navegador para analizar cadenas es inconsistente. Debido a que no hay una especificación sobre qué formatos deben ser compatibles, lo que funciona en algunos navegadores no funcionará en otros navegadores.

Para obtener resultados consistentes que analicen cualquier cosa que no sean cadenas ISO 8601, debe usar String + Format.

p.ej

var date= moment(String);
Sampath
fuente
3

Aunque es de esperar que los navegadores admitan ISO 8601 (o subconjuntos solo de fecha), este no es el caso. Todos los navegadores que conozco (al menos en los entornos locales de EE. UU. / Inglés que uso) pueden analizar el horrible MM/DD/YYYYformato de EE . UU .

Si ya tiene las partes de la fecha, puede intentar usar Date.UTC () . Si no lo hace, pero debe usar el YYYY-MM-DDformato, sugiero usar una expresión regular para analizar las piezas que conoce y luego pasarlas Date.UTC().

Phrogz
fuente
Supongo que el análisis de cadenas es el camino a seguir :(
Shrinath
1

Use el formato a continuación, funcionaría en todos los navegadores

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

// Su salida se vería así "Mié Mar 23 2016 00:00:00 GMT + 0530 (IST)"

// Tenga en cuenta que esto estaría en la zona horaria actual en este caso denotado por IST, para convertir a la zona horaria UTC que puede incluir

alert(dateObj.toUTCSting);

// Su salida ahora quisiera este "Mar, 22 Mar 2016 18:30:00 GMT"

Tenga en cuenta que ahora dateObj muestra la hora en formato GMT, también tenga en cuenta que la fecha y la hora se han cambiado de manera correspondiente.

La función "toUTCSting" recupera el tiempo correspondiente en el meridiano de Greenwich. Esto se logra al establecer la diferencia horaria entre su zona horaria actual y la zona horaria Meridiano de Greenwich.

En el caso anterior, el tiempo antes de la conversión fue de 00:00 horas y minutos el 23 de marzo del año 2016. Y después de la conversión de GMT + 0530 (IST) horas a GMT (básicamente resta 5,30 horas de la marca de tiempo dada en este caso) el tiempo refleja 18.30 horas el 22 de marzo del año 2016 (exactamente 5.30 horas menos que la primera vez).

Además, para convertir cualquier objeto de fecha en marca de tiempo, puede usar

alert(dateObj.getTime());

// la salida se vería similar a esta "1458671400000"

Esto le daría la marca de tiempo única del tiempo

Abhay Aradhya
fuente
1

¿Qué tal un secuestro Datecon fecha fija ? Sin dependencias, min + gzip = 280 B

Kenberkeley
fuente
1

La mejor manera de hacerlo es utilizando el siguiente formato:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

Esto es compatible con todos los navegadores y no le dará ningún problema. Tenga en cuenta que los meses se escriben del 0 al 11.

Daniël Brito
fuente
Funciona bien en Safari y Chrome, pero aún tiene problemas en Firefox. Safari: fecha var = nueva fecha (2018,06,08,19,17) dom jul 08 2018 19:17:00 GMT + 0800 (+08) Chrome: fecha var = nueva fecha (2018,06,08,19, 17) Dom Jul 08 2018 19:17:00 GMT + 0800 (Hora de Malasia) Firefox: var fecha = nueva Fecha (2018,06,08,19,17) Fecha 2018-07-08T11: 17: 00.000Z
Biranchi
0

El mismo problema que enfrenta Safari y se resolvió insertando esto en la página web

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

Espero que funcione también tu caso

Gracias

Yasir Shabbir Choudhary
fuente
¿Por qué crees que esto funcionaría? Miré el script y no parece anular los métodos en el objeto Date. Fui aquí: polyfill.io/v3/url-builder y parece que no hay nada sobre analizar fechas.
costa
0

Como @nizantz mencionó anteriormente, usar Date.parse () no funcionó para mí en Safari. Después de un poco de investigación, descubrí que la propiedad lastDateModified para el objeto File ha quedado en desuso y Safari ya no la admite. El uso de la propiedad lastModified del objeto File resolvió mis problemas. Claro que no me gusta cuando se encuentra mala información en línea.

Gracias a todos los que contribuyeron a esta publicación que me ayudaron a seguir el camino que necesitaba para conocer mi problema. Si no hubiera sido por esta información, probablemente nunca habría descubierto mi problema raíz. Tal vez esto ayude a alguien más en mi situación similar.

S. Costello
fuente
0

También estoy enfrentando el mismo problema en Safari Browser

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

Aquí la solución:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 
venkatskpi
fuente
0

Esta no es la mejor solución, aunque simplemente capto el error y devuelvo la fecha actual. Personalmente, tengo ganas de no resolver los problemas de Safari, si los usuarios quieren usar un navegador que no cumpla con los estándares sh * t, tienen que vivir con caprichos.

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

Sugeriría que su backend envíe fechas ISO.

AndrewMcLagan
fuente
Con todo respeto, cuando quiere decir que los usuarios tienen que usar el navegador para el que escribió el código, eso se ve mal en sentido general. También depende de nuestros casos de uso y público objetivo: si se está creando un sitio web para el consumo del mercado masivo, también estaríamos respaldando IE10, como mínimo. Estoy seguro de que alguien en MS pensó lo mismo cuando diseñaba / codificaba para Internet Explorer. Todos sabemos cómo se habla ahora.
Shrinath
-1

use el formato 'mm / dd / aaaa'. Por ejemplo: - nueva fecha ('02 / 28/2015 '). Funciona bien en todos los navegadores.

Ravi S
fuente