Escenario
Con el fin de dibujar una gráfica cronológica, necesito generar en javascript una matriz de fechas a partir de una de inicio y otra de fin. En stackoverflow doy con una solución que considero sencilla e inteligible:
1 2 3 4 5 6 7 8 |
const getDaysArray = function (start, end) { let days = [] let day; for (days, day = new Date(start); day <= end; day.setDate(day.getDate() + 1)) { days.push(day.toISOString().split('T')[0]); } return days; }; |
Problema
Un buen día nos damos cuenta que falta un día en el gráfico de nuestra aplicación. Lo primero que pensamos es en la base de datos. Pero no es así, no falta ninguno. El día en cuestión en es el 27 de octubre de 2019. ¿Qué tendrá ese día que no se niega a aparecer en el gráfico?. Una de sus peculiaridades es que coincidió con el cambio de horario de invierno del año 2019. Enseguida me vino a la cabeza un error que viví hace años en el que una fecha nos trajo de cabeza hasta que vimos que caía justo en esa hora inexistente resultante del adelanto de una hora. Depuré el código, y el bucle devolvía correctamente la fecha, pero al convertirla a literal con el método toISOString(), aplicacaba el huso horario UTC que, en el caso del horario de verano es dos horas menos, y en el otro solo una. De ahí que en un caso la convierte al día anterior y, en el otro, respeta el día.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Date Thu Oct 24 2019 01:00:00 GMT+0200 (Central European Summer Time) 2019-10-23T23:00:00.000Z Date Fri Oct 25 2019 01:00:00 GMT+0200 (Central European Summer Time) 2019-10-24T23:00:00.000Z Date Sat Oct 26 2019 01:00:00 GMT+0200 (Central European Summer Time) 2019-10-25T23:00:00.000Z Date Sun Oct 27 2019 01:00:00 GMT+0200 (Central European Summer Time) 2019-10-26T23:00:00.000Z Date Mon Oct 28 2019 01:00:00 GMT+0100 (Central European Standard Time) 2019-10-28T00:00:00.000Z |
Solución
Una posible solución sería convertir la fecha a UTC antes de aplicar la conversión a literal. Yo he optado por definir a piñón la hora del día, evitando así que el horario de verano vuelva a interferir:
1 2 3 4 5 6 7 8 9 |
const getDaysArray = function (start, end) { let days = [] let day; for (days, day = new Date(start); day <= end; day.setDate(day.getDate() + 1)) { day.setHours(11); // <- hora a piñón days.push(day.toISOString().split('T')[0]); } return days; }; |