DEV Community

Carlos Arturo Castaño G.
Carlos Arturo Castaño G.

Posted on

Microalucinaciones: un ejemplo de un error de un día al formatear fechas en JavaScript


El uso de la inteligencia artificial como herramienta de programación ofrece una ventaja evidente: rapidez.

Sin embargo, esa rapidez también exige algo que nunca deberíamos delegar completamente en una IA: la revisión y comprensión del código que vamos a llevar a producción.

Esto es especialmente importante cuando trabajamos con aplicaciones transaccionales, donde un pequeño error aparentemente insignificante puede producir consecuencias importantes.

Un error de un día en una fecha puede afectar una factura, una reserva, una vigencia, una fecha de vencimiento, un sorteo o cualquier otro proceso donde la fecha tenga significado comercial o legal.

En este artículo presento un ejemplo muy sencillo de lo que podríamos llamar una microalucinación de código: una solución que parece completamente correcta, funciona en muchas situaciones y, sin embargo, contiene un comportamiento que puede producir un error muy difícil de detectar.


El problema

Supongamos que necesitamos convertir una fecha recibida como:

2026-08-25
Enter fullscreen mode Exit fullscreen mode

en:

25/08/2026
Enter fullscreen mode Exit fullscreen mode

A primera vista parece una operación trivial.

Podríamos pensar que basta con crear un objeto Date y obtener el día, el mes y el año.

Pero aquí aparece una particularidad importante de JavaScript:

Una fecha calendario y una fecha-hora son conceptos diferentes.

Cuando utilizamos Date, estamos trabajando con un instante en el tiempo, y ese instante está relacionado con una zona horaria.

Cuando solamente tenemos:

YYYY-MM-DD
Enter fullscreen mode Exit fullscreen mode

quizá lo que realmente tenemos no es un instante, sino simplemente una fecha de calendario.


Tres formas de resolver el problema

Veamos tres implementaciones aparentemente similares.

Opción 1: trabajar directamente con el texto

Esta implementación evita crear un objeto Date cuando recibe una fecha en formato YYYY-MM-DD.

export function formatDate(iso) {
    const s = (iso || '').toString().trim();

    let y, m, d;

    if (s.includes('-') && s.length >= 10) {
        [y, m, d] = s.slice(0, 10).split('-');
    } else if (iso instanceof Date && !isNaN(iso)) {
        y = String(iso.getFullYear());
        m = String(iso.getMonth() + 1).padStart(2, '0');
        d = String(iso.getDate()).padStart(2, '0');
    } else {
        return s;
    }

    return `${d}/${m}/${y}`;
}
Enter fullscreen mode Exit fullscreen mode

Para:

formatDate("2026-08-25");
Enter fullscreen mode Exit fullscreen mode

obtenemos:

25/08/2026
Enter fullscreen mode Exit fullscreen mode

¿Por qué funciona?

Porque en este caso no estamos interpretando la fecha.

Simplemente estamos diciendo:

  • los primeros cuatro caracteres son el año;
  • los siguientes dos son el mes;
  • los últimos dos son el día.

No existe ninguna conversión de zona horaria.


Opción 2: utilizar Date

Ahora veamos una solución que parece igualmente correcta:

export function formatDate(dateString) {
    if (!dateString) return '';

    const date = new Date(dateString);

    if (isNaN(date.getTime())) {
        return dateString;
    }

    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const year = date.getFullYear();

    return `${day}/${month}/${year}`;
}
Enter fullscreen mode Exit fullscreen mode

A primera vista parece perfectamente razonable.

Pero aquí está el problema.


¿Qué ocurre con new Date("2026-08-25")?

Cuando JavaScript recibe una fecha ISO de la forma:

new Date("2026-08-25")
Enter fullscreen mode Exit fullscreen mode

esa representación se interpreta como:

2026-08-25T00:00:00.000Z
Enter fullscreen mode Exit fullscreen mode

Es decir, medianoche en UTC.

Ahora supongamos que ejecutamos el código en una zona horaria UTC-5.

La conversión sería aproximadamente:

UTC:
2026-08-25 00:00

UTC-5:
2026-08-24 19:00
Enter fullscreen mode Exit fullscreen mode

El instante sigue siendo exactamente el mismo.

Lo que cambió fue la representación local.

Y entonces ocurre algo aparentemente absurdo:

date.getDate()
Enter fullscreen mode Exit fullscreen mode

puede devolver:

24
Enter fullscreen mode Exit fullscreen mode

cuando el texto original decía:

2026-08-25
Enter fullscreen mode Exit fullscreen mode

Por eso podemos terminar mostrando:

24/08/2026
Enter fullscreen mode Exit fullscreen mode

en lugar de:

25/08/2026
Enter fullscreen mode Exit fullscreen mode

El detalle que hace peligroso este error

Lo interesante de este problema es que el código no falla de manera evidente.

No tenemos necesariamente:

  • una excepción;
  • un null;
  • un undefined;
  • un error en consola;
  • un NaN;
  • un fallo de ejecución.

El programa continúa funcionando.

Simplemente muestra una fecha incorrecta.

Y eso es mucho más peligroso en determinados sistemas.


Opción 3: utilizar una expresión regular

Otra solución sencilla es tratar la fecha como lo que realmente representa en este contexto: un dato textual.

export function formatDate(dateString) {
    if (!dateString) return '';

    const s = String(dateString).trim();

    const match = s.match(/^(\d{4})-(\d{2})-(\d{2})/);

    if (match) {
        const year = match[1];
        const month = match[2];
        const day = match[3];

        return `${day}/${month}/${year}`;
    }

    return s;
}
Enter fullscreen mode Exit fullscreen mode

El resultado será:

25/08/2026
Enter fullscreen mode Exit fullscreen mode

porque nunca se crea un objeto Date.

No hay conversión de UTC.

No hay conversión de zona horaria.

No hay posibilidad de que la fecha retroceda cinco horas.


La diferencia fundamental

Podemos resumir el problema de esta manera:

Situación Tipo de dato ¿Conviene usar Date?
2026-08-25 Fecha de calendario No necesariamente
2026-08-25T14:30:00Z Instante en el tiempo
Timestamp Unix Instante en el tiempo
Fecha de nacimiento Fecha de calendario Normalmente no
Fecha de vencimiento Fecha de calendario Depende del sistema
Hora de una transacción Fecha-hora

La pregunta importante antes de utilizar Date debería ser:

¿Estoy trabajando con una fecha de calendario o con un instante en el tiempo?


¿Cómo evitar el problema?

Si solamente necesitamos transformar:

YYYY-MM-DD
Enter fullscreen mode Exit fullscreen mode

a:

DD/MM/YYYY
Enter fullscreen mode Exit fullscreen mode

no necesitamos convertir el valor en un objeto Date.

Podemos utilizar split():

const [year, month, day] = dateString.split('-');

const result = `${day}/${month}/${year}`;
Enter fullscreen mode Exit fullscreen mode

O una expresión regular:

const match = dateString.match(/^(\d{4})-(\d{2})-(\d{2})/);
Enter fullscreen mode Exit fullscreen mode

Esto mantiene el dato como texto y evita introducir innecesariamente una zona horaria.


¿Y si realmente necesitamos utilizar Date?

Si el dato representa un instante y necesitamos trabajar con él, entonces Date es apropiado.

En esos casos debemos ser conscientes de la diferencia entre:

getDate()
getMonth()
getFullYear()
Enter fullscreen mode Exit fullscreen mode

y:

getUTCDate()
getUTCMonth()
getUTCFullYear()
Enter fullscreen mode Exit fullscreen mode

Por ejemplo:

const date = new Date("2026-08-25");

console.log(date.getUTCDate());
Enter fullscreen mode Exit fullscreen mode

puede devolver:

25
Enter fullscreen mode Exit fullscreen mode

porque estamos consultando explícitamente la representación UTC.

Mientras que:

console.log(date.getDate());
Enter fullscreen mode Exit fullscreen mode

consulta la representación en la zona horaria local.


El verdadero problema cuando usamos IA

Este ejemplo no pretende decir que la inteligencia artificial sea una mala herramienta para programar.

Todo lo contrario.

La IA puede ahorrar una enorme cantidad de tiempo.

El problema aparece cuando aceptamos una solución simplemente porque:

  1. compila;
  2. parece lógica;
  3. funciona en nuestras primeras pruebas;
  4. tiene una sintaxis correcta;
  5. fue generada por una herramienta aparentemente confiable.

Una IA puede generar código técnicamente válido que, sin embargo, no sea correcto para el contexto específico de nuestra aplicación.

En este ejemplo, la función puede funcionar perfectamente durante semanas o meses.

Y solamente fallar cuando:

  • cambia la zona horaria;
  • el servidor está configurado en otra zona;
  • el usuario está en otro país;
  • se procesa una fecha cercana a medianoche;
  • se utiliza una fecha sin componente horario.

Ese tipo de errores son especialmente difíciles de encontrar.


Una microalucinación peligrosa

Podemos llamar a esto una microalucinación de programación porque la solución generada puede parecer perfectamente razonable.

El código:

const date = new Date(dateString);
Enter fullscreen mode Exit fullscreen mode

es correcto desde el punto de vista sintáctico.

También es válido utilizar:

date.getDate();
Enter fullscreen mode Exit fullscreen mode

El problema no está necesariamente en cada instrucción individual.

El problema está en la combinación de ambas y en el significado del dato que estamos procesando.

La IA puede no conocer, o no considerar, que en nuestra aplicación:

2026-08-25
Enter fullscreen mode Exit fullscreen mode

significa simplemente:

"25 de agosto de 2026"

y no:

"el instante correspondiente a las 00:00 UTC del 25 de agosto de 2026".

Esa diferencia conceptual es la que puede producir el error.


Regla de oro

Una regla sencilla que podemos aplicar es:

Si el dato es una fecha de calendario y solamente necesitamos reorganizar sus componentes, tratémoslo como texto.

Por ejemplo:

YYYY-MM-DD
Enter fullscreen mode Exit fullscreen mode

puede transformarse directamente en:

DD/MM/YYYY
Enter fullscreen mode Exit fullscreen mode

sin utilizar Date.

En cambio, si tenemos:

2026-08-25T15:30:00Z
Enter fullscreen mode Exit fullscreen mode

estamos trabajando con un instante concreto.

En ese caso sí debemos considerar:

  • UTC;
  • zona horaria;
  • hora local;
  • conversión de fechas;
  • formato de salida.

Conclusión

Este pequeño ejemplo muestra por qué revisar el código generado por inteligencia artificial no es opcional.

Un error de un día puede parecer insignificante.

Pero en una aplicación transaccional podría significar:

  • una factura vencida antes de tiempo;
  • una reserva asignada al día incorrecto;
  • una promoción finalizada antes de tiempo;
  • un pago asociado a otra fecha;
  • un sorteo programado para un día diferente;
  • una vigencia contractual incorrecta;
  • o cualquier otro proceso donde la fecha tenga importancia.

Lo más peligroso es que probablemente no veremos ningún error en consola.

El sistema continuará funcionando.

Simplemente estará produciendo información incorrecta.

Y precisamente por eso estos errores son difíciles de detectar.

La inteligencia artificial puede escribir código mucho más rápido que nosotros.

Pero entender qué significa ese código y verificar que corresponde al problema real sigue siendo responsabilidad del programador.


La pregunta que deberíamos hacernos

Antes de aceptar cualquier código relacionado con fechas, conviene preguntarnos:

¿Estoy manipulando una fecha de calendario o estoy manipulando un instante en el tiempo?

Esa pequeña pregunta puede evitar un bug de un día que, dependiendo del sistema, podría terminar siendo un problema mucho más grande.

Top comments (0)