Pergunta

Eu estava pensando em usar TIMESTAMP para armazenar a data + tempo, mas eu li que há uma limitação do ano de 2038 sobre ele. Em vez de pedir a minha pergunta a granel, preferi dividi-lo em pequenas partes para que seja fácil para os usuários novatos a entender bem. Então, minha pergunta (s):

  1. O que é exatamente o problema ano de 2038?
  2. Por que isso ocorre eo que acontece quando ele ocorre?
  3. Como é que vamos resolver isso?
  4. Existem alternativas possíveis para usá-lo, que não representam um problema semelhante?
  5. O que podemos fazer para as aplicações existentes que utilizam TIMESTAMP, para evitar o chamado problema, quando realmente ocorre?

Agradecemos antecipadamente.

Foi útil?

Solução

Eu marquei isso como uma comunidade wiki tão à vontade para editar em seu lazer.

O que é exatamente o problema do ano 2038?

"O problema do ano 2038 (também conhecido como Unix Bug do Milénio, Y2K38 por analogia com o problema Y2K) pode causar algum software de computador para falhar antes ou durante o ano de 2038. O problema afeta todos os softwares e sistemas que o tempo sistema de loja como um inteiro de 32 bits assinado, e interpretar esse número como o número de segundos desde 00:00:00 UTC de 01 de janeiro de 1970 ".


Por que isso ocorre eo que acontece quando ele ocorre?

Número além 03:14:07 UTC de terça - feira, 19 de janeiro, 2038 'enrole' e ser armazenado internamente como um número negativo, que estes sistemas vão interpretar como uma vez em 13 de dezembro de 1901 e não em 2038. Isto é devido ao fato de que o número de segundos desde a época UNIX (01 de janeiro de 1970 00:00:00 GMT) vai ter excedido o valor máximo de um computador para um inteiro assinado de 32 bits.


Como é que vamos resolver isso?

  • Use tipos longo de dados (64 bits é suficiente)
  • Para o MySQL (ou MariaDB), se você não precisa a informação de tempo considerar o uso do tipo de coluna DATE. Se você precisar de maior precisão, use DATETIME em vez de TIMESTAMP. Cuidado que DATETIME colunas não armazenar informações sobre o fuso horário, assim que sua aplicação terá de saber qual fuso horário foi usado.
  • outras soluções possíveis descrito na Wikipedia
  • Aguarde MySQL devs para corrigir este bug relatado mais de uma década atrás.

Existem alternativas possíveis para usá-lo, que não representam um problema semelhante?

Tente sempre que possível utilizar grandes tipos para armazenar datas em bases de dados:. 64-bits é suficiente - um longo digite GNU C e POSIX / SUS, ou sprintf('%u'...) em PHP ou a extensão bcmath


Quais são algumas potencialmente quebrar casos de uso, embora não estamos ainda em 2038?

Assim, um MySQL DATETIME tem uma gama de 1000- 9999, mas TIMESTAMP só tem uma gama de 1970-2038. Se o seu sistema armazena datas de nascimento, datas futuras para a frente (por exemplo, 30 anos hipotecas), ou similar, você já está indo para executar para esse bug. Novamente, não use TIMESTAMP se isso vai ser um problema.


O que podemos fazer para as aplicações existentes que utilizam TIMESTAMP, para evitar o chamado problema, quando realmente ocorre?

Poucas aplicações PHP ainda será em torno de 2038, embora seja difícil de prever como a web dificilmente uma plataforma herdada ainda.

Aqui está um processo para alterar uma coluna da tabela de banco de dados para TIMESTAMP convertido ao DATETIME. Ela começa com a criação de uma coluna temporária:

# 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`

Resources

Outras dicas

Ao usar UNIX Timestamps para datas de loja, você está realmente usando um 32 bits inteiros, que mantém a contagem do número de segundos desde 1970-01-01; consulte Unix Tempo

Esse número de 32 bits irá transbordar em 2038. Esse é o problema 2038.


Para resolver esse problema, você não deve usar um 32 bits UNIX timestamp para armazenar as datas - o que significa, ao usar MySQL, você não deve usar TIMESTAMP, mas DATETIME (veja 10.3.1 a data e hora, data e tipos TIMESTAMP ):.

O tipo DATETIME é usado quando você valores precisam que contêm data e informação de tempo. O intervalo suportado é '1000-01-01 00:00:00' para '9999-12-31 23:59:59'.

O tipo de dados TIMESTAMP tem uma gama da UTC '1970-01-01 00:00:01' para '2038-01-19 03:14:07' UTC.


O (provavelmente) melhor coisa que você pode fazer para a sua aplicação para evitar / corrigir esse problema é não usar TIMESTAMP, mas DATETIME para as colunas que devem conter datas que não são entre 1970 e 2038.

Uma pequena nota, no entanto: há um muito alto, provavelmente, (estatisticamente falando) que sua aplicação terá sido re-escrito um par de vezes antes de 2038 ^^ Então, talvez, se você don 't tem que lidar com datas no futuro, você não terá que cuidar desse problema com a versão atual da sua aplicação ...

Uma rápida pesquisa no Google irá fazer o truque: ano de 2038 problema

  1. O problema ano de 2038 (também conhecido como Unix Bug do Milénio, Y2K38 por analogia com o problema Y2K) pode causar algum software de computador para falhar antes ou no ano de 2038
  2. O problema afeta todos os softwares e sistemas que o tempo sistema de loja como um inteiro de 32 bits assinado, e interpretar esse número como o número de segundos desde 00:00:00 UTC em 1 de Janeiro de 1970. A última vez que podem ser representada desta maneira é 03:14:07 UTC de terça-feira, 19 de Janeiro de 2038. tempos além deste momento vai "envolvente" e ser armazenado internamente como um número negativo, que estes sistemas vão interpretar como uma data em 1901 em vez de 2038
  3. Não há nenhuma solução fácil para esse problema para formatos de dados binários combinações CPU / OS existente, sistemas de arquivo existente ou existente

http://en.wikipedia.org/wiki/Year_2038_problem tem a maior parte do detalhes

Em resumo:

1) + 2) O problema é que muitos sistemas de armazenar informações data como um int assinado de 32 bits igual ao número de segundos desde 1/1/1970. A data mais recente que pode ser armazenado como este é 03:14:07 UTC de terça - feira, janeiro 19 2038. Quando isso acontece o int vai "envolvente" e ser armazenado como um número negativo que será interpretado como uma data em 1901. o que exatamente vai acontecer em seguida, varia de sistema para sistema, mas basta dizer que ele provavelmente não vai ser bom para qualquer um deles!

Para sistemas que apenas datas de loja no passado, então eu acho que você não precisa se preocupar por um tempo! O principal problema é com os sistemas que trabalham com datas no futuro. Se as suas necessidades de sistema para trabalhar com datas 28 anos no futuro, então você deve começar a se preocupar agora!

3) Use um dos formatos de data alternativos disponíveis ou passar para um sistema de 64 bits e de uso de 64 bits ints. Ou para bancos de dados usar um formato de carimbo de tempo alternativa (por exemplo, MySQL uso DATETIME)

4) Ver 3!

5) 4 !!! ;)

Bros, se você precisa usar o PHP para exibir marcas de tempo, esta é a melhor solução PHP sem mudar de formato UNIX_TIMESTAMP.

Use um CUSTOM_DATE () função. Dentro dele, use o DateTime. Aqui está a solução DateTime .

Enquanto você tem UNSIGNED BIGINT (8) como suas marcas de tempo no banco de dados. Contanto que você tem PHP 5.2.0 ++

Como eu did't deseja atualizar qualquer coisa, eu perguntei ao meu backend (MSSQL) para fazer este trabalho em vez 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'];

pode não ser uma forma eficiente, mas funciona.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top