Pregunta

Yo estaba pensando en usar TIMESTAMP para almacenar la fecha + hora, pero he leído que hay una limitación de los años 2038 en él. En vez de pedir mi pregunta a granel, he preferido dividirla en partes pequeñas para que sea fácil para los usuarios novatos a entender así. Así que mi pregunta (s):

  1. ¿Cuál es exactamente el problema del año 2038?
  2. ¿Por qué se produce y lo que sucede cuando se produce?
  3. ¿Cómo lo resolvemos?
  4. ¿Hay posibles alternativas al uso de la misma, que no supongan un problema similar?
  5. ¿Qué podemos hacer para las aplicaciones existentes que utilizan TIMESTAMP, para evitar el llamado problema, cuando lo que realmente ocurre?

Gracias de antemano.

¿Fue útil?

Solución

He marcado esto como un wiki de la comunidad, así que siéntase libre de editar en su tiempo libre.

¿Qué es exactamente el problema del año 2038?

"El problema del año 2038 (también conocido como Bug del Milenio Unix, Y2K38 por analogía con el problema Y2K) puede causar algún tipo de software de ordenador falle antes o en el año 2038. El problema afecta a todo el software y los sistemas que almacenan la hora del sistema como un entero de 32 bits, e interpretar este número como el número de segundos desde las 00:00:00 UTC el 1 de enero de 1970. "


¿Por qué se producen y qué sucede cuando ocurre?

Los tiempos más allá de 03:14:07 GMT el martes 19 de enero de 2038 'envolver' y se almacena internamente como un número negativo, que estos sistemas se interpretan como un tiempo en el 13 de diciembre de 1901 y no en 2038. Esto es debido al hecho de que el número de segundos desde la época UNIX (1 de enero 1.970 00:00:00 GMT) habrá superado el valor máximo de un ordenador para un entero con signo de 32 bits.


¿Cómo lo resolvemos?

  • Use tipos de datos de longitud (64 bits es suficiente)
  • Para MySQL (o MariaDB), si usted no necesita la información de tiempo considere usar el tipo de columna DATE. Si necesita una mayor precisión, utilice DATETIME en lugar de TIMESTAMP. Tenga en cuenta que DATETIME columnas no almacenan información sobre la zona horaria, por lo que su aplicación tendrá que saber qué zona horaria se utilizó.
  • Otras soluciones posibles se describe en la Wikipedia
  • Esperar a que los desarrolladores de MySQL para fijar este error informó hace más de una década.

¿Hay posibles alternativas al uso de la misma, que no supongan un problema similar?

Pruebe siempre que sea posible utilizar grandes tipos para el almacenamiento de fechas en bases de datos:. 64-bits es suficiente - un tipo largo, largo en GNU C y POSIX / SUS, o sprintf('%u'...) en PHP o la extensión bcmath


¿Cuáles son algunos casos de uso potencialmente rompen a pesar de que no estamos todavía en el 2038?

Así que un MySQL DATETIME tiene un alcance de 1000- 9999, pero TIMESTAMP sólo tiene un rango de 1970 a 2038. Si su sistema almacena las fechas de nacimiento, fechas futuras hacia adelante (por ejemplo, 30 hipotecas año), o similares, que ya va a ejecutar en este error. Una vez más, no utilice TIMESTAMP si esto va a ser un problema.


¿Qué podemos hacer para las aplicaciones existentes que utilizan TIMESTAMP, para evitar el llamado problema, cuando lo que realmente ocurre?

Pocas aplicaciones PHP seguirá siendo alrededor de 2038, aunque es difícil de prever que la banda apenas una plataforma heredada todavía.

Este es un proceso para modificar una columna de tabla de base de datos para convertir TIMESTAMP a DATETIME. Se inicia con la creación de una columna temporal:

# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;

# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;

# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);

# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`

Recursos

Otros consejos

Cuando se utiliza marcas de tiempo UNIX para almacenar fechas, en realidad se está utilizando una de 32 bits enteros, que lleva la cuenta del número de segundos desde el 1970-01-01; ver Unix Time

Ese número de 32 bits se desbordará en 2038. Ese es el problema 2038.


Para resolver ese problema, no se debe utilizar una marca de tiempo UNIX de 32 bits para almacenar sus fechas - lo que significa que, cuando se utiliza MySQL, no debe utilizar TIMESTAMP, pero DATETIME (ver 10.3.1 Los fecha y hora, la fecha, y tipos TIMESTAMP ):.

  

Se utiliza el tipo DATETIME cuando   necesita valores que contienen la fecha y   información de tiempo. El intervalo admitido   se '1000-01-01 00:00:00' a   '9999-12-31 23:59:59'.

     

El tipo de datos TIMESTAMP tiene un rango   de UTC a '1970-01-01 00:00:01'   '2038-01-19 03:14:07' UTC.


El (probablemente) Lo mejor que puede hacer a su aplicación para evitar / solucionar ese problema es no utilizar TIMESTAMP, pero DATETIME para las columnas que tienen que contener fechas que no son entre 1970 y 2038.

Una pequeña nota, sin embargo: hay una muy alta, probablemente (estadísticamente hablando) que su aplicación se han re-escrito todo un par de veces antes de 2038 ^^ Así que tal vez, si no 't tiene que lidiar con fechas en el futuro, usted no tendrá que hacerse cargo de ese problema con la versión actual de su aplicación ...

Una búsqueda rápida en Google hará el truco: problema del año 2038

  1. El problema del año 2038 (también conocido como Bug del Milenio Unix, Y2K38 por analogía con el problema Y2K) puede causar algún tipo de software de ordenador falle antes o en el año 2038
  2. El problema afecta a todo el software y los sistemas que almacenan la hora del sistema como un entero de 32 bits con signo, e interpretan este número como el número de segundos transcurridos desde las 00:00:00 UTC del 1 de enero de 1970. La última vez que puede ser en este modo es 03:14:07 GMT el martes, 19 de enero de 2038. los tiempos más allá de este momento será "envolvente" y se almacena internamente como un número negativo, que estos sistemas se interpretará como una fecha en 1901 en lugar de 2038
  3. No hay una solución fácil para este problema para los formatos de datos binarios combinaciones de CPU / OS existente, los sistemas de archivos existentes, o ya existente

http://en.wikipedia.org/wiki/Year_2038_problem tiene la mayor parte del detalles

En resumen:

1) + 2) El problema es que muchos sistemas de información almacenar la fecha como 32 bits con signo int igual al número de segundos desde el 1/1/1970. La última fecha en la que se pueden almacenar como este es 03:14:07 GMT el martes 19 de enero de 2038. Cuando esto ocurre, el int se "envolver" y se almacena como un número negativo, que se interpreta como una fecha en 1901. ¿Qué es exactamente va a pasar a continuación, varía de un sistema a otro, pero basta con decir que probablemente no será bueno para ninguno de ellos!

Para los sistemas que sólo almacenan las fechas en el pasado, entonces supongo que usted no tiene que preocuparse por un tiempo! El principal problema es con los sistemas que funcionan con fechas en el futuro. Si el sistema necesita para trabajar con fechas de 28 años en el futuro, entonces debería empezar a preocuparse ahora!

3) Utilice uno de los formatos de fecha alternativas disponibles o pasar a un sistema de 64 bits y el uso de enteros de 64 bits. O para bases de datos utilizan un formato de marca de tiempo alternativa (por ejemplo, para MySQL utilizar DATETIME)

4) Ver 3!

5) Ver 4 !!! ;)

Bros, si necesita usar PHP para mostrar las marcas de tiempo, esta es la solución PHP MEJOR sin cambiar de formato UNIX_TIMESTAMP.

Utilice una función CUSTOM_DATE (). Dentro de él, utilice el DateTime. Aquí está la solución de DateTime .

Como siempre y cuando tenga UNSIGNED BIGINT (8) como sus marcas de tiempo en la base de datos. Mientras usted tiene PHP 5.2.0 ++

Como Yo no he deseado para actualizar nada, le pregunté a mi backend (MSSQL) para hacer este trabajo en lugar de PHP!

$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);

echo $row_tmp['next_date'];

Puede que no sea una forma eficiente, pero funciona.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top