Java – data salva no dia anterior

Eu estou experimentando um comportamento muito estranho ao salvar datas no database. No meu servidor (Linux centOS 6.2) eu uso servidor de aplicativos glassfish (3.1.1 – build 12) e Java (1.7.0_09), o aplicativo é desenvolvido em Java + GWT, e usa o servidor PostgreSQL (9.2.1). Dentro do aplicativo existem vários campos de data que são salvos no database. Os campos de data usam datepicker (http://code.google.com/p/gwt-datepicker, r30).

O atributo date da relação db é o tipo de data (não timestamp). Algumas datas são salvas no dia anterior no database. O problema acontece apenas para datas entre intervalos, por exemplo, entre 31.03.1968 e 27.10.1968, o que me faz pensar em algum tipo de questão de horário de verão. Mas como isso não acontece em 1969, por exemplo, não posso isolar o problema muito bem. Estou tentando encontrar algum outro intervalo de datas dentro do qual o problema acontece. Por exemplo, se eu selecionar 19.05.1968 no aplicativo, depois de salvar no database, a data será salva como 18.05.1968.

O mais estranho é que eu tenho outra instância do mesmo aplicativo em outro servidor, e para as mesmas datas eles são salvos corretamente. Isso me faz pensar que o problema poderia confiar em:

  • configuração glassfish;
  • java (java.util.Data implementação?);
  • algum tipo de configuração do servidor que eu estou perdendo

Tentei definir para a Europa / Roma (meu fuso horário) todas as configurações possíveis do meu servidor, mas nada. Qualquer ideia? Como eu poderia resolver ou investigar esse problema?

ATUALIZAÇÃO: 1968 foi um ano bissexto. O problema também acontece em 1972, que é novamente um ano bissexto. Resumindo: o problema “data-salvo-um-dia-antes” acontece em anos bissextos durante o intervalo de data do horário de verão.

A parte do código onde o object de data é criado é:

Date d = dateField.getSelectedDate(); if (d != null) { txtVal = DateTimeFormat.getFormat("dd/MM/yyyy").format(d); } 

onde dateField é declarado como:

 transient private DatePicker dateField; 

O pacote é org.zenika.widget.client.datePicker.DatePicker (gwt-datepicker-r30 mencionado anteriormente) e DateTimeFormat refere-se a com.google.gwt.i18n.shared.DateTimeFormat

UPDATE depois de aceitar a resposta:

Eu usei esta solução alternativa: quando eu crio uma data, eu uso o seguinte código:

 final long hours12 = 12L * 60L * 60L * 1000L; Date d = new Date(d1.getTime() + hours12); 

Basta definir a hora da data para 12:00 (em vez do padrão 0:00) e você deve estar bem. A questão é que a biblioteca de fuso horário do GWT não inclui todos os anos bissextos anteriores a 1990 e, assim, você terá um tempo errado no servidor (já que o valor é enviado na forma de um registro de data e hora e tem uma hora de folga).

A propósito: o GWT tem um seletor de datas integrado, veja sua demonstração em http://gwt.google.com/samples/Showcase/Showcase.html#!CwDatePicker

Você está usando java.util.date ou java.sql. data (esta última é a correta)? Eu tive um problema semelhante com o SQL Server, mesmo que fosse regular e sim, relacionado com o horário de verão.

Basicamente, você armazena uma data Java como meia-noite de um dia específico. se, no verão, a data for movida para o dia anterior às 23:00 e, em seguida, a hora ficar truncada! Se você enviar a data com um carimbo de data “random”, você perceberá o problema uma vez em 24 durante o verão.

Não me lembro exatamente da solução (que não vai ajudá-lo diretamente, pois se refere a um DBMS diferente), mas havia uma configuração no dB para dizer “armazenar a data como você a recebe”. Você pode testar se esse é o caso alterando a dbcolumn para timestamp e observando como o tempo é armazenado.

Eu fiz um pouco de pesquisa – parece que o gwt-datepicker tem muitos problemas! http://code.google.com/p/google-apps-script-issues/issues/detail?id=2022 http://code.google.com/p/google-apps-script-issues/issues/detail id = 2001

Eu não ficaria surpreso se o cálculo deles tivesse um bug nos anos bissextos. Além disso, é inteiramente possível que seja apenas um descompasso entre o que você está fazendo e o que você pensa que está fazendo – trabalhar com o Dates é um assunto surpreendentemente difícil.

Para verificar, tente:

 final java.util.Date ud = dateField.getSelectedDate();; final java.sql.Date sd = new java.sql.Date(ud.getTime()); System.out.println(ud);// this is what you pick from the DatePicker System.out.println(sd);// this is what will be stored on the database 

E veja se eles combinam durante o verão nos anos bissextos. Se for um erro do GWT, http://code.google.com/p/google-apps-script-issues/ é o lugar certo para denunciá-lo

Enfrentou esta questão em tempo real para a data de nascimento.

Eu fiz a correção abaixo, de modo que, em vez de salvar uma data às 12 horas, a data será salva às 6 horas, que é antes do horário comercial do servidor. Até uma hora é deduzida, não afetará o dob.

 Calendar now = Calendar.getInstance(); now.setTime(YOUR_DATE); now.set(Calendar.HOUR_OF_DAY, 6); YOUR_DATE = now.getTime(); 

Resposta Mikes está bem. Mas, se salvarmos às 12 horas, existe a possibilidade de erro na comparação de datas, se o usuário inserir a data durante o horário comercial antes das 12 horas.