Sinto muito, mas todas as respostas até agora estão geralmente incorretas. A resposta é bastante simples, mas exige que separemos cinco pontos:
- DATE =java.sql.Date, que é um wrapper em torno de java.util.Date que é o número de milissegundos desde a Epoch no fuso horário UTC. Portanto, isso tem o ano/mês/data/horas/minutos/segundos em um fuso horário GMT+0 (UTC) fixo. Observe, no entanto, que java.sql.Date define os componentes de tempo como zero!
- TIMESTAMP =java.sql.TimeStamp que é um wrapper de componente em torno de Date que adiciona frações de segundos para suportar o padrão do tipo SQL DATE. Esta classe/tipo não é relevante ou necessária para esta pergunta, mas em resumo, tem a data mais a hora.
- O banco de dados armazena objetos DATE conforme definido (usando UTC como o deslocamento de Java), mas pode traduza a hora se configurada no banco de dados para estar em um fuso horário diferente. Por padrão, a maioria dos bancos de dados adota o fuso horário do servidor local, o que é uma péssima ideia. Senhoras, senhores... SEMPRE armazene objetos DATE em UTC. Continue lendo...
- A hora na JVM e o fuso horário precisam estar corretos. Como o objeto Date está usando UTC, um deslocamento está sendo calculado para o horário do servidor? Considere isso com a forte recomendação de que o horário do servidor seja definido como GMT+0 (UTC).
- Finalmente, quando queremos renderizar o DATE do banco de dados (usando JSF ou qualquer outro), deveria ser configurado para ser o fuso horário GMT + 0 e, se feito do lado do servidor também ... suas datas e horários SEMPRE serão consistentes, referenciais e todas as coisas boas. Tudo o que resta é renderizar a hora e ESTE é onde o agente do usuário (para um aplicativo da Web, por exemplo) poderia ser usado para traduzir a hora GMT+0 para o fuso horário "local" dos usuários.
Resumo:Use UTC (GMT+0) no servidor, no banco de dados, em seus objetos Java.
DATE e TIMESTAMP são diferentes apenas de uma perspectiva de banco de dados, pois TIMESTAMP carrega frações de segundos adicionais. Ambos usam GMT+0 (implícito). JodaTime é uma estrutura de calendário preferida para lidar com tudo isso, mas não corrigirá os problemas de JVM incompatível com as configurações de fuso horário do banco de dados.
Se os projetos de aplicativos da JVM para o DB não usarem GMT, devido ao horário de verão, ajustes de relógio e todos os outros tipos de jogos regionais que são jogados nos relógios locais do mundo ... os horários das transações e tudo o mais serão distorcidos para sempre , não referencial, inconsistente, etc.
Outra boa resposta relacionada sobre tipos de dados:java.util .Data vs java.sql.Data
Observe também que o Java 8 tem atualizações com melhor manipulação de data/hora (finalmente), mas isso não corrige o relógio do servidor em que a JVM está sendo executada em um fuso horário e o banco de dados em outro. Neste ponto, há sempre tradução acontecendo. Em todos os clientes grandes (inteligentes) com os quais trabalho, os fusos horários do banco de dados e do servidor JVM são definidos como UTC exatamente por esse motivo, mesmo que suas operações ocorram em grande parte em algum outro fuso horário.