A nivel local, todo es exacto al minuto. Una vez desplegado en Heroku, la diferencia entre los tiempos es de aproximadamente 6 horas. No estoy buscando convertir la zona horaria de Heroku (me gustaría que siguiera siendo UTC). Probé de todo, desde conversiones getTimezoneOffset() hasta diferentes formatos de fecha, y sigo obteniendo el mismo resultado. ¿Cómo puedo hacer que estas 2 fechas y horas coincidan entre sí y no se compensen con las horas cuando se implementan? ¿Por qué son diferentes, cuando están formateados exactamente de la misma manera?
// Used to calculate current date time const currentDate = new Date(); // ^ Production - (2021-10-12T19:12:41.081Z) const time = `${currentDate.getHours()}:${currentDate.getMinutes()}`; const fullDate = `${currentDate.getMonth()}/${currentDate.getDate()}/${currentDate.getFullYear()}`; const currentDateFormatted = new Date(`${fullDate} ${time}`); // ^ Production - (2021-10-12T19:12:00.000Z) const currentParsedDateToUTC = Date.parse(currentDateFormatted.toUTCString()); // Used to calculate an event date time const eventDate = new Date(`${event.date} ${event.endTime}`); // same exact format as above // ^ Production - (2021-10-12T13:12:00.000Z) const eventParsedDateToUTC = Date.parse(eventDate.toUTCString()); const isExpired = (currentParsedDateToUTC > eventParsedDateToUTC); // works locally, but not in productionEn este ejemplo, la fecha del evento y la hora de inicio son idénticas a la fecha y hora actual. ¿Cómo puedo evitar que sean muy diferentes?
Esto se debe a que el servidor Heroku está en una zona horaria diferente a la suya, puede manejarlo convirtiendo el formato de hora desde su interfaz, le recomiendo que use moment.js, por ejemplo, en su interfaz puede convertir así:
npm install moment --saveY luego puede crear una función solo para cambiar el formato para mostrar:
const formatDatetime = ( datetime = "N/A", format = 'LLL' // here is your format ) => { return moment(datetime).isValid() ? moment(datetime).format(format) : datetime; };Entonces, Heroku está devolviendo la hora local UTC correcta, a partir de este escrito es 2021-10-12T19:36:00.000Z .
Le está pidiendo a Heroku que interprete 2012-10-12 13:12 como una fecha, pero no está especificando qué zona horaria debe usar, por lo que el valor predeterminado es su propia hora local UTC.
Todo aquí está funcionando como se esperaba.
Lo que creo que está preguntando implícitamente es que quiere que interprete 13:12 como si estuviera en su hora local. Sin embargo, Heroku no tiene forma de saber cuál es su hora local, por lo que deberá realizar un seguimiento de la zona horaria de los eventos en su base de datos.
La única razón por la que esto funciona localmente es porque su servidor local está en la misma zona horaria que usted; si tuviera que conectarme a su servidor local desde mi zona horaria, experimentaría el mismo problema.
Las primeras cuatro líneas de código parecen ser un intento de crear una fecha y establecer los segundos y milisegundos en cero. Eso se puede hacer como:
let d = new Date(); d.setSeconds(0,0);que establecerá los segundos y milisegundos a cero.
No sé qué crees que hace lo siguiente:
const currentParsedDateToUTC = Date.parse(currentDateFormatted.toUTCString());pero un resultado idéntico está dado por:
d.getTime();que en realidad es el valor devuelto en la llamada anterior a setSeconds . Así que las primeras 5 líneas de código se reducen a:
let currentParsedDateToUTC = new Date().setSeconds(0,0);Luego en:
const eventDate = new Date(`${event.date} ${event.endTime}`);Una marca de tiempo en el formato d/m/y H:m se analiza utilizando el analizador incorporado, lo cual es una mala idea, consulte ¿Por qué Date.parse da resultados incorrectos? . Puede usar una biblioteca en su lugar o simplemente escribir una función de 2 líneas para hacer el trabajo.
Entonces otra vez hay:
const eventParsedDateToUTC = Date.parse(eventDate.toUTCString());que es simple:
const eventParsedDateToUTC = eventDate.getTime();Finalmente hay:
const isExpired = (currentParsedDateToUTC > eventParsedDateToUTC);los operadores de comparación obligarán a las fechas a numerar por usted, por lo que puede dejar los valores como fechas.
Una función para hacer el trabajo es:
// eventDate is UTC timestamp in m/d/y H:m format function isExpired(eventDate) { // Parse eventDate as UTC let [M,D,Y,H,m] = eventDate.split(/\W/); let eventD = new Date(Date.UTC(Y, M-1, D, H, m)); // return true if has passed (minute precision) return eventD < new Date().setSeconds(0,0); } // Event dates (UTC) ['10/12/2021 12:00', // 12 Oct 2021 12:00 '10/13/2021 12:00', // 13 Oct 2021 12:00 '10/13/2022 12:00', // 13 Oct 2022 12:00 ].forEach(d => console.log(d + ' has' + (isExpired(d)? '':' not') + ' Expired') ); Donde podría usar el valor devuelto por Date.UTC(Y, M-1, D, H, m) sin conversión a Date, por lo que las dos últimas líneas podrían ser:
return Date.UTC(Y, M-1, D, H, m) < new Date().setSeconds(0,0);pero es un poco más semántico (si es innecesario) usar una Fecha. :-)