javascript - new - extraños segundos de desplazamiento en el objeto fecha js en cromo
string to date javascript (2)
Al mirar el valor valueOf de un objeto de fecha al comienzo de un año, esperaba recibir siempre cero segundos. El siguiente código muestra que hasta 1917 hubo un desplazamiento de 54 segundos o 40 segundos en cromo. en IE recibo 0 segundos para todos los años.
¿Hay alguna razón para esto? Parece que solo pasa en la última versión de Chrome.
for(var i=0; i<2020;i++)
if(!new Date(i,0,1).valueOf().toString().match("00000$"))
console.log({
y:i,
s: new Date(i,0,1).valueOf().toString().match(/(/d{2})/d{3}$/)[1]})
Esto no es un error ..
Como @Krzysztof señaló, Chrome ha implementado una nueva especificación para el cálculo del desplazamiento de la zona horaria luego de la combinación de Make LocalTZA toma ''t'' e ''isUTC'' y suelta DSTA (t) a Ecma 262. Así que ahora la conversión de zona horaria no funciona solo un intervalo de segundos hacia atrás, se calcula según la hora local que se estaba observando en una región específica .
Explicación:
Soy de un pequeño y maravilloso país llamado Bangladesh del sur de Asia, que sigue el horario BST (hora estándar de Bangladesh +0600 GMT), que no siempre fue exactamente 6 horas antes de GMT. Como la date
JavaScript toma tiempo local cuando imprimo la hora de inicio de este año en GMT, obtengo:
new Date(2018, 0, 1).toUTCString()
// "Sun, 31 Dec 2017 18:00:00 GMT"
En 2009, se observó una hora de ahorro de luz diurna en Bangladesh del 19 de junio al 31 de diciembre. Así que si imprimo el primer día de diciembre de 2009 obtengo:
new Date(2009, 11, 1).toUTCString()
// "Mon, 30 Nov 2009 17:00:00 GMT"
Puede ver que el nodeJS
verano se refleja ahora en la fecha, que no está visible en la consola de mi nodeJS
. También hubo cambios en la hora local en 1941-1942 como se muestra a continuación y puede verse en timeanddate.com :
Todos los cambios se reflejan en Chrome ahora:
new Date(1941, 6, 1).toUTCString()
// "Mon, 30 Jun 1941 18:06:40 GMT"
new Date(1941, 11, 1).toUTCString()
// "Sun, 30 Nov 1941 17:30:00 GMT"
new Date(1942, 7, 1).toUTCString()
// "Fri, 31 Jul 1942 18:30:00 GMT"
new Date(1942, 11, 1).toUTCString()
// "Mon, 30 Nov 1942 17:30:00 GMT"
Así que ahora, si elijo una fecha antes de 1941 teniendo en cuenta que mi hora local es 6 horas por delante, veo un desplazamiento de 6 minutos y 40 segundos . Variará dependiendo de la zona horaria para las fechas anteriores debido a la reciente actualización de Chrome, o específicamente a la actualización de ECMAScript (JavaScript).
Es posible que no sea el 100% la solución del problema, pero se puede obtener el "jitter" introducido por chrome new Date(oldDate.getTime() + jitter)
en UTC y viceversa, y luego compensarlo con una new Date(oldDate.getTime() + jitter)
.
// Compensates for google chrome 67+ issue with very old dates.
// We should skip this test if any other browser.
$getJitter: function (d) {
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCMilliseconds())),
jitter = 0;
// As we''re setting UTC date, the non-UTC year could be
// shifted one ahead or behind, so set the utc full
// year to ensure compliance.
utcDate.setUTCFullYear(d.getUTCFullYear());
if (d.getFullYear() != utcDate.getFullYear() ||
d.getMonth() != utcDate.getMonth() ||
d.getDate() != utcDate.getDate() ||
d.getHours() != utcDate.getHours() ||
d.getMinutes() != utcDate.getMinutes() ||
d.getMilliseconds() != utcDate.getMilliseconds()) {
// infers the "jitter" introduced during the conversion to compensate in the
// actual value of ticks
jitter = d.getTime() - utcDate.getTime()
}
return jitter;
}
Este "jitter" depende en gran medida de la zona horaria. Para Brasil, recibo un ruido de 28 segundos (así que vuelve a estar como, 12:00:00 AM> 23:59:32 PM el día anterior.
Para Brasil, el problema se produce hasta 1913. Esto coincide con el momento en que obtuvimos nuestros horarios de ahorro de luz diurna y zona horaria a -3: 00 desde -3: 06, según los cambios de hora a lo largo de los años en https://www.timeanddate.com/time/zone/brazil/sao-paulo .
Con el código anterior puede explorar las fechas rotas con este bucle:
for (var i=1900; i < 2020; i++) {
for (var j=0; j < 12; j++) {
var dt = new Date(i, j, 1);
var jitter = System.DateTime.$getJitter(dt);
if (jitter != 0) {
console.log("broken: " + i + ", " + j + ", jitter: " + (jitter/1000) + "s: " + dt.toString());
}
}
}