La utilidad era pequeña: una función que recibe una fecha y devuelve una etiqueta tipo 2026-S01, para agrupar en un informe las horas que apunta un equipo de tres personas. Mi primera versión hacía lo que hace casi todo el mundo: año del calendario y, de ahí, el día del año dividido entre 7 y redondeado hacia arriba.
Funcionó todo el año. Hasta que probé con el cambio de ejercicio. El lunes 29 de diciembre de 2025 salía como 2025-S52 y el jueves 1 de enero como 2026-S01. Con ese criterio, las horas de una misma semana laboral, de lunes a viernes, acababan en dos filas distintas del informe. Ninguna estaba «mal» por separado, y el total de cada fila parecía razonable.
Qué pasaba de verdad
Abrí Elffuss Code en el navegador, pegué la función y le describí el síntoma al modelo local: «la misma semana aparece partida en dos al cruzar el 31 de diciembre». No me dio un parche a ciegas. Me hizo notar que yo estaba mezclando dos ideas: el año del calendario y el año de la semana.
En ISO 8601 la semana 1 es la que contiene el primer jueves del año. Por eso el 29 de diciembre de 2025 es semana 1 de 2026. Y al revés: el 1 de enero de 2027 cae en viernes, así que pertenece a la semana 53 de 2026. El año de la etiqueta es el del jueves de esa semana, no el del día que miras.
- Desplazar la fecha al jueves de su semana.
- Tomar el año de ese jueves como año de la etiqueta.
- Contar semanas desde el 1 de enero de ese año.
La trampa de la que no me había acordado
Le pedí también casos de prueba. Entre ellos salió uno que yo no habría escrito: restar fechas en hora local y dividir entre milisegundos por día falla cuando hay cambio de hora, porque ese día dura 23 o 25 horas. El último domingo de octubre es dentro de dos días. Pasamos todo el cálculo a UTC y las pruebas dejaron de depender de la época del año en que se ejecutaban.
Acabé con una tabla de fechas frontera: 28 y 29 de diciembre de 2025, 31 de diciembre de 2026, 1 y 3 de enero de 2027, y un 31 de diciembre de un año con 52 semanas. Las comprobé contra el calendario a mano, no contra el modelo. Un modelo local ayuda a pensar, pero la última palabra la tiene la tabla.
Por qué prefiero que esto no salga de mi máquina
Aquel código era una pieza de una herramienta interna con nombres de proyectos reales en los comentarios y en los datos de prueba. No es un secreto de Estado, pero tampoco es algo que me apetezca pegar en un servicio de terceros solo para que me expliquen qué es una semana ISO. Aquí el prompt, la función y las pruebas se quedaron en el navegador, en mi GPU. Sin cuenta, sin cuota y sin que me importe si hay conexión.
Si tienes una utilidad pequeña que se rompe justo en el borde, ábrela en Elffuss Code: corre en tu navegador, con el modelo en tu propia GPU, y tu código y tus prompts no se suben a ningún sitio.
Abrir Code →