2012-04-22 11 views
18

Antes que nada, creo que la zona horaria probablemente tenga algo que ver con esto. Estoy en EST/EDT. Además, estoy probando esto en chromium 17/linux.Constructor de fecha: argumentos numéricos frente a un argumento de cadena que da fechas diferentes en algunos casos

Ahora, digamos que puedo crear dos fechas como esta:

// December 5 

dateFromNumbers = new Date(2020, 11, 5); 
dateFromString = new Date("2020-12-5"); 

Parece estas fechas deben tener marcas de tiempo idénticos, y que hacen:

+dateFromNumbers == +dateFromString; // true 

... al menos en este caso . Pero en algunos casos, no:

// December 15 

dateFromNumbers = new Date(2020, 11, 15); 
dateFromString = new Date("2020-12-15"); 

+dateFromNumbers == +dateFromString; // false 

¿Qué está pasando aquí?

dateFromNumbers; // Tue Dec 15 2020 00:00:00 GMT-0500 (EST) 
dateFromString; // Mon Dec 14 2020 19:00:00 GMT-0500 (EST) 

Parece que es dateFromString 5 horas antes de lo dateFromNumbers en este caso (EST es GMT - 5, estoy seguro de que está relacionado de alguna manera).

Parece afectar los fines de los meses de octubre a diciembre. Aquí hay un violín que facilita ver qué días son diferentes (a menos que sea daltónico de color rojo-verde, en ese caso puede ser difícil de ver, mis disculpas).

http://jsfiddle.net/9gBfX/

Lo que da?


Notas:

  • usted puede configurar su sistema de zona horaria a EST/EDT para ver el ejemplo jsFiddle como lo estoy viendo.
  • Los números de mes de la fecha están basados ​​en cero; el 11 no es un error tipográfico.
  • Este problema aparece en cada año que revisé.
+1

En su segunda fecha del caso es 15 de noviembre de 2020 y 15 de diciembre de 2020. ¿Es un error tipográfico? – Habib

+0

Ejecutando Chrome 18.0.1025.162 m, Windows, GMT +2: los resultados son reproducibles. Pero especificar explícitamente el tiempo en la representación de cadena resuelve el problema. Por lo general, evito las fechas de las cadenas porque el soporte de formato en los navegadores es variado y está poco documentado, los milisegundos son mucho más confiables. – DCoder

Respuesta

6

Después de mirar en V8's source code:

// Specification: 
// Accept ES5 ISO 8601 date-time-strings or legacy dates compatible 
// with Safari. 
<...> 
// A string that matches both formats (e.g. 1970-01-01) will be 
// parsed as an ES5 date-time string - which means it will default 
// to UTC time-zone. That's unavoidable if following the ES5 
// specification. 

lectura del código rodea, parece que una cadena de fecha y hora con los dos meses y los días 2 símbolos larga se considera una cadena de fecha y hora válida ES5.Más abajo, en el analizador ES5, después de que analiza las fechas y horas, hay un comentario:

// Successfully parsed ES5 Date Time String. Default to UTC if no TZ given. 

En caso de "AAAA-MM-DD", una vez que el código obtiene tan lejos, el analizador ES5 ha analizado correctamente toda la cadena, por lo que regresa antes de que el analizador heredado tenga la oportunidad de localizar la zona horaria. De lo contrario (el mes/día tiene un símbolo de largo) se trata como una fecha de entrega "heredada" y el analizador heredado lo trata y lo localiza.

2

El uso de "-" como separador de fechas para las fechas de los EE. UU. Confunde algunos navegadores, algunos realizarán la aritmética de la fecha, otros devolverán NaN, así que utilice el separador de fecha "/". Una solución consciente de la cultura es usar date.js, que es un manejador de fechas de JavaScript excepcional que resuelve problemas como el que usted ha señalado (http://www.datejs.com/). Utilizando el método de análisis elimina toda confusión:

Date.parse("2020-12-15").toString() // yields the correct date ("Tue Dec 15 00:00:00 PST 2020"). 
+2

Intenta usar "/" en lugar de "-". –

+0

GGG estaba en lo cierto al votar mi respuesta. Debería haber elaborado y ahora lo he hecho. –

+0

No lo rechacé. –

2

la retransmisión en this post, parece que la cadena del argumento del constructor del Date 's es una implementación sensibles, debido a diversas Date.parse() implementaciones por los navegadores.

sus medidas son correctas, y probablemente deba evitar usar este constructor por completo, si desea que su navegador analice EST correctamente.

2

Parece que el constructor de fecha requiere espacios en lugar de '-'. Es la forma recomendada. Confirmar este enlace:
3.3. Date and Time Specification

Aunque se permite el espacio foldingwhite durante todo el día en tiempo especificación, se recomienda que un solo espacio se utilizará en cada lugar que aparece FWS (si es necesario u opcional)

también puedes ver este enlace:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date

dateString: valor de cadena que representa una fecha. La cadena debe estar en un formato reconocido por el método de análisis (IETF-obediente RFC 2822 marcas de tiempo).

me trataron siguiente código y devuelve verdadero

dateFromNumbers = new Date(2020, 11, 15); 
dateFromString = new Date("2020 12 15"); 
alert(+dateFromNumbers == +dateFromString);​ 

también que no es un problema de comenzar con el mes de octubre, que tiene ver con los meses de dos dígitos. Si intento el mismo método a septiembre a continuación:

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020-09-15"); 
alert(+dateFromNumbers == +dateFromString);​ // This returns false 

Pero si uso un solo dígito para septiembre entonces devuelve verdadero

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020-9-15"); 
alert(+dateFromNumbers == +dateFromString);​ // This returns true 

Y si el uso del espacio con dos dígitos de septiembre de entonces se devuelve verdadero

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020 09 15"); 
alert(+dateFromNumbers == +dateFromString);​//This returns true 
3

Aquí hay un dibujo con una respuesta simplificada de las otras respuestas.

Fecha reconoce diferentes formatos de cadena

  • fechas no estándar
  • RFC 2282 fechas
  • ES 5 fechas

mayoría de los formatos se interpretan como fechas locales

En la página 14 de RFC 2282, vemos:

La fecha y la hora del día debe expresar hora local.

Las fechas no estándar se tratan de manera similar.

ES 5 formato se interpreta como UTC

En section 15.9.1.15 de la especificación ES 5 vemos:

El valor de una zona de tiempo ausente de desplazamiento es “Z”.

"Z" representa la hora UTC.

El décimo del mes de octubre

ES 5 fechas con formato requieren meses de dos dígitos y día. Los meses y días en la publicación original no son acolchados con cero. "2020-9-9" no es una representación válida de fecha ES 5; es un formato no estándar, por lo que se interpreta en la hora local. "2020-10-10" es una representación válida de fecha ES 5, por lo que debe interpretarse en UTC.

soluciones posibles

  • No utilice el constructor de cadena/Date.parse!
  • Cambie el carácter separador para que el formato nunca coincida con el formato ES 5.
  • Especifique una zona horaria.
  • Ajuste las fechas a la hora local. Si tienen horas o minutos: date.setMinutes(date.getTimezoneOffset()); (esto parece funcionar de todos modos).
Cuestiones relacionadas