El problema del año 2038 (también conocido como Y2038 , [1] Y2K38 , superbacteria Y2K38 o Epochalypse [2] [3] ) es un problema de cálculo del tiempo que deja a algunos sistemas informáticos incapaces de representar los tiempos después de las 03:14:07 UTC del 19 Enero de 2038.
El problema existe en sistemas que miden el tiempo Unix (el número de segundos transcurridos desde la época Unix (00:00:00 UTC del 1 de enero de 1970)) y lo almacenan en un entero de 32 bits con signo . El tipo de datos solo es capaz de representar números enteros entre −(2 31 ) y 2 31 − 1 , lo que significa que la última hora que se puede codificar correctamente es 2 31 − 1 segundos después de la época (03:14:07 UTC del 19 de enero de 2038). . Intentar incrementar al segundo siguiente (03:14:08) hará que el número entero se desborde , estableciendo su valor en −(2 31 ), que los sistemas interpretarán como 2 31 segundos antes de la época (20:45:52 UTC del 13 de diciembre). 1901). El problema es de naturaleza similar al problema del año 2000 . En 2106 se alcanzarán restricciones de almacenamiento análogas para enteros de 32 bits sin signo .
Los sistemas informáticos que utilizan el tiempo para cálculos críticos pueden encontrar errores fatales si no se aborda el problema del año 2038. Algunas aplicaciones que utilizan fechas futuras ya han encontrado el error. [4] [5] Los sistemas más vulnerables son aquellos que rara vez o nunca se actualizan, como los sistemas heredados e integrados . Para abordar el problema, muchos sistemas modernos se han actualizado para medir el tiempo Unix con números enteros de 64 bits con signo , lo que tardará 292 mil millones de años en desbordarse, aproximadamente 21 veces la edad estimada del universo .
Muchos sistemas informáticos miden la hora y la fecha como hora Unix , un estándar internacional para el cronometraje digital. El tiempo Unix se define como el número de segundos transcurridos desde las 00:00:00 UTC del 1 de enero de 1970 (un tiempo elegido arbitrariamente en función de la creación del primer sistema Unix ), que ha sido denominado la época Unix . [6]
Históricamente, el tiempo de Unix se ha codificado como un entero de 32 bits con signo , un tipo de datos compuesto por 32 dígitos binarios (bits) que representan un valor entero, donde "con signo" significa que el número puede representar números positivos y negativos, así como cero; y generalmente se almacena en formato complemento a dos . [a] Por lo tanto, un entero de 32 bits con signo solo puede representar valores enteros desde −(2 31 ) hasta 2 31 − 1 inclusive. En consecuencia, si se utiliza un entero de 32 bits con signo para almacenar la hora Unix, la última hora que se puede almacenar es 2 31 − 1 (2,147,483,647) segundos después de la época, que son las 03:14:07 del martes 19 de enero de 2038. [ 7] Los sistemas que intenten incrementar este valor en un segundo más a 2 31 segundos después de la época (03:14:08) sufrirán un desbordamiento de enteros , invirtiendo sin darse cuenta el bit de signo para indicar un número negativo. Esto cambia el valor entero a −(2 31 ), o 2 31 segundos antes de la época en lugar de después , lo que los sistemas interpretarán como 20:45:52 del viernes 13 de diciembre de 1901. A partir de aquí, los sistemas continuarán contando hacia arriba, hacia cero, y luego hacia arriba a través de los números enteros positivos nuevamente. Como muchos sistemas informáticos utilizan cálculos de tiempo para ejecutar funciones críticas, el error puede introducir errores fatales.
Cualquier sistema que utilice estructuras de datos con representaciones de tiempo firmadas de 32 bits tiene un riesgo inherente de fallar. Es prácticamente imposible obtener una lista completa de estas estructuras de datos, pero existen estructuras de datos bien conocidas que tienen el problema del tiempo de Unix:
UNIX_TIMESTAMP()
comandos tipo -Los sistemas integrados que utilizan fechas para el cálculo o el registro de diagnóstico tienen más probabilidades de verse afectados por el problema Y2038. [1] A pesar de la moderna actualización generacional de 18 a 24 meses en la tecnología de sistemas informáticos , los sistemas integrados están diseñados para durar toda la vida útil de la máquina de la que forman parte. Es posible que algunos de estos sistemas todavía estén en uso en 2038. Puede resultar poco práctico o, en algunos casos, imposible actualizar el software que ejecuta estos sistemas y, en última instancia, requerir su reemplazo si se quieren corregir las limitaciones de 32 bits.
Muchos sistemas de transporte, desde aviones hasta automóviles, utilizan ampliamente sistemas integrados. En los sistemas automotrices, esto puede incluir el sistema de frenos antibloqueo (ABS), el control electrónico de estabilidad (ESC/ESP), el control de tracción (TCS) y la tracción automática en las cuatro ruedas ; Las aeronaves pueden utilizar sistemas de guía inercial y receptores GPS . [b] Otro uso importante de los sistemas integrados es en dispositivos de comunicaciones, incluidos teléfonos móviles y dispositivos con acceso a Internet (por ejemplo , enrutadores , puntos de acceso inalámbrico , cámaras IP ) que dependen del almacenamiento de una hora y fecha precisas y se basan cada vez más en sistemas tipo Unix. sistemas operativos. Por ejemplo, el problema Y2038 hace que algunos dispositivos con Android de 32 bits se bloqueen y no se reinicien cuando se cambia la hora a esa fecha. [8]
Sin embargo, esto no implica que todos los sistemas integrados sufrirán el problema Y2038, ya que muchos de estos sistemas no requieren acceso a las fechas. Para aquellos que lo hacen, aquellos sistemas que sólo rastrean la diferencia entre horas/fechas y no horas/fechas absolutas, por la naturaleza del cálculo, no experimentarán un problema importante. Este es el caso del diagnóstico de automóviles basado en normas legisladas como CARB ( Junta de Recursos del Aire de California ). [9]
En mayo de 2006, surgieron informes de una manifestación temprana del problema Y2038 en el software AOLserver . El software fue diseñado con un error para manejar una solicitud de base de datos que "nunca" debería expirar. En lugar de abordar específicamente este caso especial, el diseño inicial simplemente especificaba una fecha de vencimiento arbitraria en el futuro. La configuración predeterminada para el servidor especificaba que la solicitud debería expirar después de mil millones de segundos. Mil millones de segundos (aproximadamente 32 años) después de las 01:27:28 UTC del 13 de mayo de 2006 superan la fecha límite de 2038. Por lo tanto, después de este tiempo, el cálculo del tiempo de espera se desbordó y devolvió una fecha que en realidad era pasada, lo que provocó que el software fallara. Cuando se descubrió el problema, los operadores de AOLServer tuvieron que editar el archivo de configuración y establecer el tiempo de espera en un valor más bajo. [4] [5]
No existe una solución universal para el problema del año 2038. Por ejemplo, en el lenguaje C , cualquier cambio en la definición del time_t
tipo de datos daría lugar a problemas de compatibilidad de código en cualquier aplicación en la que las representaciones de fecha y hora dependan de la naturaleza del time_t
entero de 32 bits con signo. Por ejemplo, cambiar time_t
a un entero de 32 bits sin signo, que ampliaría el rango a 2106 [10] (específicamente, 06:28:15 UTC del domingo 7 de febrero de 2106), afectaría negativamente a los programas que almacenan, recuperan o manipulan fechas anteriores a 1970, ya que dichas fechas están representadas por números negativos. Aumentar el tamaño del time_t
tipo a 64 bits en un sistema existente provocaría cambios incompatibles en el diseño de las estructuras y la interfaz binaria de las funciones.
La mayoría de los sistemas operativos diseñados para ejecutarse en hardware de 64 bits ya utilizan enteros de 64 bits con signo time_t
. El uso de un valor de 64 bits con signo introduce una nueva fecha envolvente que es más de veinte veces mayor que la edad estimada del universo : aproximadamente 292 mil millones de años a partir de ahora. [11] La capacidad de realizar cálculos sobre fechas está limitada por el hecho de que tm_year
se utiliza un valor entero de 32 bits con signo que comienza en 1900 para el año. Esto limita el año a un máximo de 2.147.485.547 (2.147.483.647 + 1900). [12]
Se han hecho propuestas alternativas (algunas de las cuales ya están en uso), como almacenar milisegundos o microsegundos desde una época (normalmente el 1 de enero de 1970 o el 1 de enero de 2000) en un entero de 64 bits con signo, proporcionando un rango mínimo de 300.000 años con una resolución de microsegundos. [13] [14] En particular, el uso que hace Java de enteros largos de 64 bits en todas partes para representar el tiempo como "milisegundos desde el 1 de enero de 1970" funcionará correctamente durante los próximos 292 millones de años. Otras propuestas de nuevas representaciones del tiempo proporcionan diferentes precisiones, rangos y tamaños (casi siempre superiores a 32 bits), además de resolver otros problemas relacionados, como el manejo de los segundos intercalares . En particular, TAI64 [15] es una implementación del estándar de Tiempo Atómico Internacional (TAI), el estándar internacional actual en tiempo real para definir un segundo y un marco de referencia.
time_t
. [17]time_t
para arquitecturas de 32 y 64 bits. Las aplicaciones que fueron compiladas para una versión anterior de NetBSD con 32 bits time_t
son compatibles a través de una capa de compatibilidad binaria, pero dichas aplicaciones más antiguas seguirán sufriendo el problema Y2038. [18]time_t
para arquitecturas de 32 y 64 bits. A diferencia de NetBSD , no existe una capa de compatibilidad binaria. Por lo tanto, las aplicaciones que esperan 32 bits time_t
y las aplicaciones que usan algo diferente time_t
para almacenar valores de tiempo pueden fallar. [19]time_t
solo para arquitecturas de 64 bits; la ABI pura de 32 bits no se modificó debido a la compatibilidad con versiones anteriores. [20] A partir de la versión 5.6 de 2020, 64 bits time_t
también es compatible con arquitecturas de 32 bits. Esto se hizo principalmente por el bien de los sistemas Linux integrados . [21]time_t
en plataformas de 32 bits con versiones de Linux apropiadas. Este soporte se puede activar definiendo una macro de preprocesador _TIME_BITS
al 64
compilar el código fuente. [22]time_t
para todas las arquitecturas de 32 y 64 bits, excepto i386 de 32 bits, que utiliza 32 bits firmados time_t
. [23]time_t
. Como se trataba de un entorno nuevo, no era necesario tomar precauciones especiales de compatibilidad. [20]struct nfstime4 {int64_t seconds; uint32_t nseconds;}
desde diciembre de 2000. [24] La versión 3 admite valores de 32 bits sin firmar como struct nfstime3 {uint32 seconds; uint32 nseconds;};
. [25] Los valores mayores que cero para el campo de segundos indican fechas posteriores a la hora 0, 1 de enero de 1970. Los valores menores que cero para el campo de segundos indican fechas anteriores a la hora 0, 1 de enero de 1970. En ambos casos, el El campo nsegundos (nanosegundos) se agregará al campo de segundos para la representación del tiempo final.time_t
. [29] Como parte del trabajo de cumplimiento del año 2000 que se llevó a cabo en 1998, el CRTL se modificó para utilizar enteros de 32 bits sin signo para representar el tiempo; ampliando el alcance time_t
hasta el 7 de febrero de 2106. [30]FROM_UNIXTIME()
, UNIX_TIMESTAMP()
y CONVERT_TZ()
manejan valores de 64 bits en plataformas que los admiten. Esto incluye versiones de 64 bits de Linux, MacOS y Windows. [32] [33] En versiones anteriores, funciones integradas como UNIX_TIMESTAMP()
devolverán 0 después de las 03:14:07 UTC del 19 de enero de 2038. [34]