Una de las fuentes habituales de errores a la hora de desarrollar software y administrar sistemas informáticos es el tiempo. Formatos, husos horarios, conversiones… suelen generar problemas cuando diferentes aplicaciones o sistemas no están alineados.

En sistemas tipo Unix, el tiempo se representa como el número de segundos transcurridos desde el 1 de enero de 1970. Este valor se conoce como Unix time. El problema aparece cuando ese valor se almacena en un entero de 32 bits con signo. Ese tipo de dato tiene un valor máximo que, cuando se alcanza, el contador se desborda y pasa a valores negativos.

El efecto 2000

A finales de los años 90, el mundo de la tecnología vivió una cuenta atrás peculiar que se denominó efecto 2000. En etapas iniciales de desarrollo de los sistemas informáticos la memoria era un elemento con un coste elevado, por lo que muchos almacenaban el año con sólo dos dígitos. Asumían implícitamente que siempre sería “19xx”, lo cual iba a provocar que al pasar de “99” a “00” se interpretase el año 2000 como 1900.

El problema se mitigó sin incidentes relevantes y dejó una lección: las decisiones técnicas aparentemente inocentes, en sistemas destinados a perdurar en el tiempo, pueden tener consecuencias mucho tiempo después.

El tiempo se romperá de nuevo en 2038

El 19 de enero de 2038 a las 03:14:07 UTC los segundos transcurridos desde la fecha base en Unix alcanzarán el valor máximo que pueden almacenar los sistemas de 32 bits. En el siguiente, el valor se desbordará y el tiempo “volverá atrás”, provocando comportamientos impredecibles.

A diferencia del año 2000, esta vez, el problema no afecta tanto a sistemas de escritorio modernos, sino a pequeños dispositivos de infraestructura. Esto son: sistemas embebidos, dispositivos IoT, maquinaria industrial o software legado que sigue funcionando años después de haber sido escrito. Muchos de estos sistemas no se actualizan con facilidad, o directamente no se actualizan, y podrían seguir funcionando dentro de 10 o 15 años y romperse de golpe.

1
2
3
4
5
6
7
public class Year2038Example {
	public static void main(String[] args) {
		int maxSeconds = Integer.MAX_VALUE;
		System.out.println(maxSeconds);      //  2147483647
		System.out.println(maxSeconds + 1);  // -2147483648
	}
}

No es un fallo del futuro, sino una deuda del pasado. Una decisión técnica antigua que sigue vigente. Diseñar pensando a largo plazo, así como tener en cuenta los supuestos ocultos o extremos, es una de las responsabilidades de los ingenieros de software.