FROM_DAYS
La función FROM_DAYS convierte un número absoluto de días en una fecha. Este número representa la cantidad de días transcurridos desde el "día cero" en el sistema de calendario interno de MySQL. Es la operación inversa de TO_DAYS: mientras TO_DAYS convierte una fecha a un número de días, FROM_DAYS toma ese número y lo convierte de vuelta a una fecha.
En la práctica, FROM_DAYS es una herramienta de bajo nivel que raramente usarás de forma directa. Su utilidad principal aparece cuando necesitas hacer aritmética de fechas basada en números de días almacenados internamente, o cuando trabajas con datos que provienen de sistemas que almacenan fechas como contadores de días.
Sintaxis
FROM_DAYS(N)El argumento N es un entero que representa un número absoluto de días. La función devuelve un valor de tipo DATE. El rango práctico va desde el día 366 (que corresponde al 0001-01-01) hasta valores cercanos al año 9999, aunque los resultados solo son fiables a partir del año 1582 cuando se adoptó el calendario gregoriano.
Comportamiento básico
Veamos cómo FROM_DAYS traduce números de días a fechas:
SELECT
FROM_DAYS(738886) AS fecha_2025,
FROM_DAYS(1) AS dia_uno,
FROM_DAYS(366) AS primer_anio,
FROM_DAYS(0) AS dia_cero;| fecha_2025 | dia_uno | primer_anio | dia_cero |
|---|---|---|---|
| 2025-01-01 | 0000-00-00 | 0001-01-01 | 0000-00-00 |
El número 738886 corresponde al 1 de enero de 2025. El día 1 devuelve una fecha inválida (0000-00-00), el día 366 corresponde al 1 de enero del año 1 y el día 0 también devuelve una fecha inválida. Estos valores extremos son poco útiles en la práctica, pero te dan una idea del rango de la función.
La relación inversa con TO_DAYS
La propiedad fundamental de FROM_DAYS es que deshace lo que hace TO_DAYS. Puedes verificarlo fácilmente:
SELECT
fecha_original,
TO_DAYS(fecha_original) AS numero_dias,
FROM_DAYS(TO_DAYS(fecha_original)) AS reconstruida
FROM (
SELECT '2025-06-15' AS fecha_original
UNION SELECT '2000-01-01'
UNION SELECT '1999-12-31'
) fechas;| fecha_original | numero_dias | reconstruida |
|---|---|---|
| 2025-06-15 | 739051 | 2025-06-15 |
| 2000-01-01 | 730485 | 2000-01-01 |
| 1999-12-31 | 730484 | 1999-12-31 |
En todos los casos, aplicar FROM_DAYS al resultado de TO_DAYS devuelve la fecha original. Esta propiedad es la base de muchas técnicas de aritmética de fechas.
Caso práctico: aritmética de fechas con números
Aunque MySQL tiene DATE_ADD y DATE_SUB para sumar y restar días a una fecha, la combinación de TO_DAYS y FROM_DAYS permite hacer aritmética directa con números. Por ejemplo, para calcular una fecha que está exactamente a N días de otra:
SELECT
FROM_DAYS(TO_DAYS('2025-03-01') + 90) AS noventa_dias_despues,
FROM_DAYS(TO_DAYS('2025-03-01') - 30) AS treinta_dias_antes;| noventa_dias_despues | treinta_dias_antes |
|---|---|
| 2025-05-30 | 2025-01-30 |
Esto es equivalente a DATE_ADD('2025-03-01', INTERVAL 90 DAY), pero el enfoque con TO_DAYS y FROM_DAYS puede ser más intuitivo cuando ya estás trabajando con números de días almacenados en tu base de datos.
Caso práctico: calcular puntos medios entre fechas
Una aplicación práctica es calcular la fecha exacta a la mitad entre dos fechas dadas. Esta operación es natural con números de días:
SELECT
fecha_contrato,
fecha_vencimiento,
TO_DAYS(fecha_vencimiento) - TO_DAYS(fecha_contrato) AS dias_contrato,
FROM_DAYS(TO_DAYS(fecha_contrato) +
FLOOR((TO_DAYS(fecha_vencimiento) - TO_DAYS(fecha_contrato)) / 2)
) AS punto_medio
FROM (
SELECT '2025-01-15' AS fecha_contrato, '2025-07-15' AS fecha_vencimiento
UNION SELECT '2025-03-01', '2026-02-28'
UNION SELECT '2025-06-01', '2025-12-31'
) contratos;| fecha_contrato | fecha_vencimiento | dias_contrato | punto_medio |
|---|---|---|---|
| 2025-01-15 | 2025-07-15 | 181 | 2025-04-15 |
| 2025-03-01 | 2026-02-28 | 365 | 2025-08-30 |
| 2025-06-01 | 2025-12-31 | 213 | 2025-09-17 |
El cálculo del punto medio toma el número de días del contrato, divide entre dos y suma al inicio para encontrar la fecha exacta a la mitad del período. Este tipo de cálculo es útil para programar revisiones intermedias o pagos a medio plazo.
Caso práctico: convertir datos almacenados como número de días
Algunos sistemas almacenan fechas como un número entero de días desde una época determinada. Si esa época coincide con el punto de referencia de MySQL, FROM_DAYS es la conversión directa:
SELECT
id_evento,
dias_almacenados,
FROM_DAYS(dias_almacenados) AS fecha_evento
FROM (
SELECT 1 AS id_evento, 738886 AS dias_almacenados
UNION SELECT 2, 739000
UNION SELECT 3, 739100
) eventos;| id_evento | dias_almacenados | fecha_evento |
|---|---|---|
| 1 | 738886 | 2025-01-01 |
| 2 | 739000 | 2025-04-25 |
| 3 | 739100 | 2025-08-03 |
Si el sistema de origen usa una época diferente (como días desde el 1 de enero de 1970, que es la época Unix), necesitarás sumar un offset: FROM_DAYS(dias_desde_1970 + TO_DAYS('1970-01-01')).
La advertencia del calendario gregoriano
Es importante saber que FROM_DAYS no es fiable para fechas anteriores al año 1582, cuando se adoptó el calendario gregoriano. Antes de esa fecha, se usaba el calendario juliano, que tenía reglas de años bisiestos diferentes:
SELECT
FROM_DAYS(1) AS muy_antigua,
FROM_DAYS(577737) AS pre_gregoriana,
FROM_DAYS(577738) AS gregoriana;| muy_antigua | pre_gregoriana | gregoriana |
|---|---|---|
| 0000-00-00 | 1582-10-14 | 1582-10-15 |
El 15 de octubre de 1582 es la fecha en que entró en vigor el calendario gregoriano en muchos países. Para fechas anteriores, los cálculos de FROM_DAYS pueden no coincidir con las fechas históricas reales. En la práctica, esto rara vez es un problema, ya que la mayoría de bases de datos empresariales no manejan fechas tan antiguas.
FROM_DAYS con NULL
Como es habitual en MySQL, si el argumento es NULL, la función devuelve NULL:
SELECT FROM_DAYS(NULL) AS resultado;| resultado |
|---|
| NULL |
Combinación con otras funciones
FROM_DAYS se combina frecuentemente con TO_DAYS y funciones aritméticas. Un ejemplo interesante es calcular el próximo lunes a partir de una fecha dada:
SELECT
fecha,
DAYNAME(fecha) AS dia_semana,
FROM_DAYS(TO_DAYS(fecha) + (7 - WEEKDAY(fecha)) % 7) AS proximo_lunes_o_hoy,
FROM_DAYS(TO_DAYS(fecha) + ((7 - WEEKDAY(fecha)) % 7) +
CASE WHEN WEEKDAY(fecha) = 0 THEN 7 ELSE 0 END
) AS proximo_lunes_estricto
FROM (
SELECT '2025-06-16' AS fecha
UNION SELECT '2025-06-18'
UNION SELECT '2025-06-22'
) fechas;| fecha | dia_semana | proximo_lunes_o_hoy | proximo_lunes_estricto |
|---|---|---|---|
| 2025-06-16 | Monday | 2025-06-16 | 2025-06-23 |
| 2025-06-18 | Wednesday | 2025-06-23 | 2025-06-23 |
| 2025-06-22 | Sunday | 2025-06-23 | 2025-06-23 |
La aritmética con TO_DAYS y FROM_DAYS permite este tipo de cálculos de calendario que serían más complicados con DATE_ADD solamente. Aunque para la mayoría de operaciones cotidianas es preferible usar DATE_ADD y DATEDIFF por su legibilidad, conocer FROM_DAYS y TO_DAYS amplía tu arsenal para situaciones más complejas.
En el siguiente artículo veremos TO_DAYS para convertir una fecha a número de días.
Escrito por Eduardo Lázaro
