Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Discrepância de fuso horário no mysql e java


Antecedentes:Um equívoco surpreendentemente comum - e grande - compartilhado até mesmo por programadores brilhantes é a noção de que os carimbos de hora armazenados (em seu banco de dados, Data, Calendário, Timestamp, etc.) de alguma forma têm informações de fuso horário. Não. Um carimbo de data/hora (até o Java 8, pelo menos) é armazenado como o número de milissegundos desde a meia-noite de 1º de janeiro de 1970 UTC. Fim da frase. A única coisa que a configuração do fuso horário faz é fornecer informações suficientes ao computador para converter esse carimbo de hora em um formato legível por humanos e vice-versa.

Resposta:Quando você suspeitou que este era um problema de fuso horário, você estava certo . Mas o código que você usou para tentar verificar isso também tem um problema:
end.setTimeZone(TimeZone.getTimeZone("America/New York"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTimeInMillis()));

Esse setTimeZone declaração não tem nenhum efeito no tempo armazenado em end , porque a hora já foi definida. Só teria efeito se você armazenasse a hora depois, e somente se você usasse um dos métodos do Calendar que convertesse a hora de um formato legível por humanos (e não setTimeInMillis ).

Quando você usa getTimeInMillis para passar o carimbo de hora para sua declaração preparada, você está recuperando o carimbo de hora diretamente. Como você não está convertendo para um formato humano, mais uma vez as informações de fuso horário são ignoradas.

Quando você tenta
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
end.setTime(sdf.parse("2012-10-01 00:00:00"));
pst.setTimestamp(1, new java.sql.Timestamp(end.getTime()));

e
pst.setTimestamp(1, new java.sql.Timestamp(octDate.get(Calendar.YEAR)-1900,octDate.get(Calendar.MONTH),octDate.get(Calendar.DATE),octDate.get(Calendar.HOUR),octDate.get(Calendar.MINUTE),octDate.get(Calendar.SECOND),0));
pst.setTimestamp(2, new java.sql.Timestamp(end.get(Calendar.YEAR)-1900,end.get(Calendar.MONTH),end.get(Calendar.DATE),end.get(Calendar.HOUR),end.get(Calendar.MINUTE),end.get(Calendar.SECOND),0));

coisas aparecem para funcionar porque agora você está usando métodos que convertem de/para um formato legível por humanos e, portanto, as informações de fuso horário especificadas são usadas. No entanto, isso está apenas encobrindo o problema real. O problema real é que o tempo foi convertido incorretamente quando você o analisou de endString . Ou seja, o fuso horário que endString foi expresso em não corresponde ao fuso horário definido em df1 no momento em que a data foi analisada.

RESPOSTA CURTA:antes desta linha:
end.setTime(df1.parse(endString));

Você precisa:
  • Descubra qual fuso horário é o horário em endString foi expresso em.
  • Definir df1 e não end para esse mesmo fuso horário. Desde df1 é o que está convertendo a data do formato humano, é essa informação de fuso horário que é usada.

Saúde!