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_2025dia_unoprimer_aniodia_cero
2025-01-010000-00-000001-01-010000-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_originalnumero_diasreconstruida
2025-06-157390512025-06-15
2000-01-017304852000-01-01
1999-12-317304841999-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_despuestreinta_dias_antes
2025-05-302025-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_contratofecha_vencimientodias_contratopunto_medio
2025-01-152025-07-151812025-04-15
2025-03-012026-02-283652025-08-30
2025-06-012025-12-312132025-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_eventodias_almacenadosfecha_evento
17388862025-01-01
27390002025-04-25
37391002025-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_antiguapre_gregorianagregoriana
0000-00-001582-10-141582-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;
fechadia_semanaproximo_lunes_o_hoyproximo_lunes_estricto
2025-06-16Monday2025-06-162025-06-23
2025-06-18Wednesday2025-06-232025-06-23
2025-06-22Sunday2025-06-232025-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