Skip to content

fix: las fechas de entrega salían un día antes al oeste de UTC - #96

Merged
JoseSerpaCode merged 2 commits into
mainfrom
fix/fechas-solo-dia
Oct 18, 2026
Merged

JoseSerpaCode merged 2 commits into
mainfrom
fix/fechas-solo-dia

Conversation

@JoseSerpaCode

@JoseSerpaCode JoseSerpaCode commented Oct 18, 2026 •

Copy link
Copy Markdown
Owner

Qué pasaba

Una entrega puesta para el 9 de septiembre se veía «Sep 8, 2026» en Colombia. issues.due_date se guarda como '2026-09-09' (un día del calendario, sin hora ni zona) y deSQLite() le añadía la Z que sí necesitan las marcas de CURRENT_TIMESTAMP. Así pasaba a medianoche UTC, que en Bogotá (UTC−5) son las siete de la tarde del día 8. Ocurría en la tarjeta que pinta el servidor (IssueCard.astro) y, desde la 1.27.1, también en el modal, porque los dos usan fecha().

Cambios

  • src/lib/fechas.ts: deSQLite() lee las fechas solo-día como la medianoche local de ese día, y rechaza los días que no existen (2026-02-30 daba el 2 de marzo). Las marcas de tiempo no cambian: siguen siendo UTC.
  • diaDeCalendario() (nueva): devuelve una fecha solo-día tal cual, y una marca de tiempo como el día local de ese instante. La usan vencida() y el <input type="date"> del modal, que antes hacía new Date(x).toISOString().split('T')[0] y sacaba el día en UTC.
  • El modal marcaba en rojo una entrega de hoy al repintar la tarjeta: comparaba new Date(iso + 'T00:00:00') < new Date(), que la da por vencida desde la medianoche. Ahora usa vencida(), igual que la tarjeta servida.
  • «Mis Tareas» (TaskTable) y el contador de vencidas del Hub ya pasaban por fecha()/vencida(), así que quedan arreglados con el mismo cambio. La ordenación por fecha compara cadenas y no se movía.

Pruebas

  • tests/fechas-solo-dia.test.ts: los mismos casos en America/Bogota y Asia/Tokyo, con una comprobación previa de que el cambio de zona se aplicó de verdad. Con el código anterior fallan 10 de 16.
  • tests/e2e/fecha-y-cancelar.spec.ts ahora fija el día exacto (9 en la tarjeta servida, 10 después de editar en el modal). playwright.config.ts arranca el servidor con TZ=America/Bogota y la prueba fija timezoneId: en UTC, que es la zona de CI, el fallo no se ve. Pasada contra main, la prueba falla con "Due: Sep 8, 2026"; pasada contra esta rama, 10 de 10 en serie.
  • Con main ya fusionado (PR fix(deps): actualizaciones de seguridad dentro de la misma versión mayor #94 y PR test(timer): no volcar la página entera al log #95 incluidos) y npm ci sobre el lockfile: npx vitest run 366/366 y npx playwright test 253/253.
  • Antes del merge, en una de cuatro corridas completas falló esta misma prueba de fecha, en el paso de repintado tras editar. Ya había pasado la aserción del día correcto, y sola y en serie pasa 10 de 10, así que parece una intermitencia con carga y no algo del arreglo.

Qué cambia en lib/fechas (para quien construya encima)

Las firmas no cambian; cambia el comportamiento con las cadenas AAAA-MM-DD:

  • deSQLite('2026-09-09') devuelve la medianoche local de ese día (antes daba medianoche UTC). Un día inexistente, como '2026-02-30', da null. Las cadenas con hora ('2026-09-09 14:00:00', con T, con Z o con desfase) se leen igual que antes: sin zona, como UTC.
  • fecha(), fechaHora() y relativo() heredan ese cambio: una fecha solo-día se formatea como ese día en cualquier zona.
  • vencida(valor, ahora) compara el día de calendario con hoyLocal(ahora). Para una fecha solo-día, el resultado es el mismo que antes. Para una marca de tiempo, usa ahora el día local de ese instante (antes cortaba la cadena, es decir, el día en UTC).
  • Nueva: diaDeCalendario(valor): string | null. Devuelve una fecha solo-día tal cual, o el día local de una marca de tiempo. Es el valor que espera un <input type="date">.
  • En IssueDetailsModal.astro, el repintado de la tarjeta usa vencida() en lugar de su comparación propia, y el campo de fecha se rellena con diaDeCalendario().
  • playwright.config.ts: el servidor e2e arranca con TZ=America/Bogota.

Si se añade hora de entrega, ojo: un valor con hora y sin zona se sigue leyendo como UTC. Para guardar una hora local hay que guardarla con su desfase, o convertirla a UTC antes de guardarla.

Notas

🤖 Generated with Claude Code

JoseSerpaCode and others added 2 commits October 18, 2026 14:15
`due_date` se guarda como '2026-09-09', un día del calendario sin zona, y
`deSQLite()` le añadía la `Z` de las marcas de CURRENT_TIMESTAMP: pasaba a
medianoche UTC, que en Bogotá es el día 8 por la tarde. La tarjeta y el
modal enseñaban «Sep 8, 2026» para una entrega del 9.

Ahora una fecha solo-día se lee como la medianoche local de ese día, y
`diaDeCalendario()` la devuelve tal cual para el <input type="date"> y
para `vencida()`. Las marcas de tiempo siguen siendo UTC.

El modal, además, recalculaba «vencida» a mano y daba por vencida una
entrega de hoy desde las 00:00; ahora usa `vencida()` como la tarjeta.

Pruebas unitarias en America/Bogota y Asia/Tokyo, y el e2e fija el día
exacto, con servidor y navegador en Bogotá: en UTC, la zona de CI, el
fallo no se veía.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	CHANGELOG.md
#	package-lock.json
#	package.json
@JoseSerpaCode
JoseSerpaCode merged commit d81f922 into main Oct 18, 2026
1 check passed
@JoseSerpaCode
JoseSerpaCode deleted the fix/fechas-solo-dia branch October 19, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant