sql >> Base de Datos >  >> RDS >> Database

¿Cuál es el problema del año 2038?

El problema del año 2038 (también conocido como el error Y2K38) se refiere a un problema que algunos sistemas informáticos pueden encontrar cuando se trata de tiempos posteriores al 2038-01-19 03:14:07.

Muchos sistemas informáticos, como Unix y los sistemas basados ​​en Unix, no calculan el tiempo utilizando el calendario gregoriano. Calculan el tiempo como el número de segundos desde el 1 de enero de 1970. Por lo tanto, en estos sistemas, el tiempo se representa como un número grande (es decir, el número de segundos transcurridos desde el 01-01-1970 a las 00:00:00). Por lo general, esto se conoce como tiempo de época, tiempo de Unix, tiempo de época de Unix o tiempo POSIX. Mientras escribo esto, el tiempo de Unix es 1560913841. Y mientras escribo la siguiente línea, el tiempo de Unix ha aumentado a 1560913879.

El problema de 2038 se debe al hecho de que muchos sistemas almacenan este número como un entero binario de 32 bits con signo. El rango de un entero de 32 bits con signo es de -2 147 483 648 a 2 147 483 647. Esto significa que la última época que se puede representar es 2147483647. Esto ocurrirá a las 03:14:07 del martes 19 de enero de 2038.

Después de eso, el resultado dependerá en gran medida del sistema. En muchos sistemas, se producirá un desbordamiento de enteros y cualquier tiempo posterior se ajustará y se almacenará internamente como un número negativo. El resultado es que un segundo después, la hora se interpretará como el 13 de diciembre de 1901 en lugar del 19 de enero de 2038.

Sin embargo, también podría terminar con resultados variables, según la aplicación en uso. Incluso si su sistema operativo no tiene ningún problema, su propio código aún podría tener un problema. Por ejemplo, si ha escrito un código personalizado para devolver la hora de Unix y lo almacena en un entero de 4 bytes con signo, tendrá problemas. En tales casos, reescribir el código para usar un número entero de 8 bytes podría ser todo lo que necesita hacer.

Dado que este sitio web tiene que ver con bases de datos, aquí hay algunos ejemplos de bases de datos.

Ejemplo 1:MySQL

En MySQL, el TIMESTAMP el tipo de datos admite fechas/horas desde '1970-01-01 00:00:01.000000' UTC hasta '2038-01-19 03:14:07.999999'. Por lo tanto, se podría decir que cualquier base de datos que utilice este tipo de datos tiene un error Y2K38.

MySQL también tiene una función incorporada llamada UNIX_TIMESTAMP() que, como era de esperar, devuelve la marca de tiempo de Unix.

El UNIX_TIMESTAMP() La función acepta un argumento opcional que le permite especificar una fecha para usar para la hora de Unix (es decir, la cantidad de segundos desde '1970-01-01 00:00:00' UTC hasta la hora que especifique). El rango válido de valores de argumento es el mismo que para TIMESTAMP tipo de datos, que es '1970-01-01 00:00:01.000000' UTC a '2038-01-19 03:14:07.999999' UTC. Si pasa una fecha fuera de rango a esta función, devuelve 0 .

Esto es lo que sucede si intenta usar esta función para devolver la hora de Unix desde una fecha posterior a '2038-01-19 03:14:07.999999':

SELECT UNIX_TIMESTAMP('2038-01-20') Result;

Resultado:

+--------+
| Result |
+--------+
|      0 |
+--------+

Obtenemos 0 porque el argumento de fecha está fuera del rango admitido.

Se generó un informe de error relacionado para el equipo de MySQL en 2005 (aunque algunos de los detalles parecen ser diferentes), y al momento de escribir este artículo, aún no se ha abordado.

También se planteó un problema similar para abordar las limitaciones con TIMESTAMP tipo de datos, que aún no se ha abordado.

Ejemplo 2:Servidor SQL

SQL Server actualmente no tiene un equivalente de UNIX_TIMESTAMP de MySQL función. Por lo tanto, si necesita devolver la hora de Epoch, deberá hacer algo como esto:

SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE());

Esto está bien para fechas anteriores al problema de 2038. Después de esa fecha, tendrá problemas porque DATEDIFF() la función devuelve el resultado como un int tipo de datos. El int el tipo de datos tiene un rango de -2^31 (-2,147,483,648) a 2^31-1 (2,147,483,647).

Esto es lo que sucede si trato de devolver la hora de Epoch después de '2038-01-19 03:14:07':

SELECT DATEDIFF(SECOND,'1970-01-01', '2038-01-19 03:14:08') AS 'Result';

Resultado:

The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.

Afortunadamente, también hay un DATEDIFF_BIG() función, que hace exactamente lo mismo, excepto que devuelve el resultado como bigint tipo de datos.

Así que podemos reescribir el ejemplo anterior a lo siguiente para superar este problema:

SELECT DATEDIFF_BIG(SECOND,'1970-01-01 00:00:00', '2038-01-19 03:14:08') AS 'Result';

Resultado:

+------------+
| Result     |
|------------|
| 2147483648 |
+------------+

El grande el tipo de datos usa 8 bytes (a diferencia de los 4 bytes de un int ), por lo que deberá decidir si cambiar o no a DATEDIFF_BIG() ahora o más adelante. Si su aplicación trata con fechas futuras, puede ser prudente hacerlo más temprano que tarde.