Tengo un problema extraño aquí. En una aplicación que estoy creando, necesito generar una matriz de cadenas de fechas consecutivas, donde cada cadena de fechas es 'YYYY-MM-DD'. Funcionó bien durante mucho tiempo, pero luego, en noviembre, uno de mis usuarios me informó que faltaba una fecha, el 7 de noviembre de 2021, en la aplicación.
Pero, no faltaba para nadie más. Así que trabajé con él para reducir el problema al código a continuación. Se comporta de manera diferente si yo o él lo ejecutamos en nuestras consolas Chrome.
// Creates an array of 14 consecutive date strings function datesInclGaps(date, hour) { const latest = toUTCDate(date, hour) const result = [] for (let i = 0; i < 14; i++) { result.push(fromUTCDate(latest)) latest.setDate(latest.getDate() - 1) } return result } // Creates a Date object with the given UTC date and the give hour. const toUTCDate = (date, hour) => { const match = /(\d\d\d\d)-(\d\d)-(\d\d)/.exec(date) if (!match) throw new Error('Illegal date format: ' + date) const utc = new Date() utc.setUTCFullYear(+match[1], +match[2] - 1, +match[3]) utc.setUTCHours(hour, 0, 0, 0) return utc } // Returns a date string YYYY-MM-DD from a Date obj. // Date assumed to be in UTC. const fromUTCDate = date => { const y = date.getUTCFullYear() const m = pad(date.getUTCMonth() + 1) const d = pad(date.getUTCDate()) return `${y}-${m}-${d}` } const pad = (t, p = 2) => t.toString().padStart(p, '0') console.log('0-hour') console.log(datesInclGaps('2021-11-14', 0).join(', ')) console.log('12-hour') console.log(datesInclGaps('2021-11-14', 12).join(', '))La lista de fechas debe ser los primeros 14 días de noviembre. El argumento de la 'hora' es como finalmente 'arreglé' el error, ya que si lo configuro en 0, el día desaparece para él, pero si lo configuro en 12, funciona bien. Vea las capturas de pantalla a continuación. El modo claro es su salida, con el error, y el modo oscuro es cuando lo ejecuto, sin error. Exactamente la misma ejecución simple de Javascript en la consola de Chrome.
La razón por la que uso las versiones UTC es para asegurarme de que las zonas horarias no importen. Pero... es lo único que se me ocurre que podría ser una diferencia entre nosotros. ¡Me he devanado los sesos con esto, pero no puedo pensar en una sola buena razón por la que el código se comporte así! ¡Cualquier idea sería útil!
Esto sucede porque usa getDate : este es un método que funciona con la fecha local. Si la diferencia de zona horaria es tal que la medianoche UTC todavía está en el día anterior, getDate devolverá la fecha de ese día anterior. ¡Pero el primer día que cambia el horario de verano, mover la hora local una hora hacia atrás, restando 1 día en términos de zona horaria local, corresponde a restar 25 horas en términos UTC!
Entonces tenemos en un momento determinado esta Fecha:
8 November 2021, 0:00 UTC Al hacer getDate() , la fecha se interpreta como una fecha local, en la zona horaria GMT+00 sin horario de verano. Entonces obtenemos:
8 November 2021, 0:00 Local Time Zone Luego hacemos setDate con 1 día restado:
7 November 2021, 0:00 Local Time ZonePero esta fecha se encuentra en el período de ahorro de luz diurna, por lo que se traduce de nuevo a esta fecha UTC:
6 November 2021, 23:00 UTCEntonces, cuando se emite esta fecha, es el 6 de noviembre, no el 7 de noviembre, el que se omitió.
La solución es bastante obvia cuando la ve: debe usar getUTCDate y setUTCDate y mantenerse alejado de las variantes no UTC de estos métodos, ya que inicializó la fecha con la hora UTC.