Pessoal, estou tendo um problema de Calendar com timezone no Java. Não sei se alguém já passou por isso aqui, mas o problema é um tanto quanto estranho. Estou com um projetinho de console que usa Hibernate Annotations e Banco MySQL. Tudo está funcionando muito bem, exceto os campos de data.
Eu estou desenvolvendo meu projeto em uma máquina Windows com Java 6. Porém o projeto irá rodar em uma máquina com Debian, também Java 6 só que o fuso da máquina onde irá rodar o projeto é PST (Pacific Standard Time -08:00 horas). Então, para não ter problemas com fuso (quero sempre saber a hora que rodou pelo horário oficial brasileiro), estou usando a seguinte forma de se obter a data:
Calendar saoPauloDate = Calendar.getInstance(TimeZone.getTimeZone("America/Sao_Paulo"));
Quando eu rodo em minha máquina Windows esse código eu tenho a seguinte data:
21/2/2011 13:42
// Método de formatação de data omitido
No servidor com Debian, a hora também está voltando correta. Só que quando essa hora é persistida no Banco de Dados MySQL, volta-se 5 horas! Ou seja, se aqui em São Paulo é 10h00 e a aplicação roda, a data persistida é de 05h00 da madrugada!
Para tirar as dúvidas sobre o retorno de datas na minha máquina Windows e na máquina Debian, montei o seguinte código e rodei nos dois ambientes. Exportei via Eclipse como Runnable Jar File e executei usando o comando java -jar dateTest.jar. Veja o resultado abaixo:
Código rodado:
[code]import java.util.Calendar;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
Calendar systemDate = Calendar.getInstance();
Calendar saoPauloDate = Calendar.getInstance(TimeZone.getTimeZone("America/Sao_Paulo"));
Calendar brazilEastDate = Calendar.getInstance(TimeZone.getTimeZone("Brazil/East"));
System.out.println("Sem Timezone: " + Main.getFormatedDate(systemDate));
System.out.println("America/São_Paulo: " + Main.getFormatedDate(saoPauloDate));
System.out.println("Brazil/East: " + Main.getFormatedDate(brazilEastDate));
}
private static String getFormatedDate(Calendar date) {
StringBuffer formattedDate = new StringBuffer();
formattedDate.append(date.get(Calendar.DAY_OF_MONTH)).append("/");
formattedDate.append(date.get(Calendar.MONTH) + 1).append("/");
formattedDate.append(date.get(Calendar.YEAR)).append(" ");
formattedDate.append(date.get(Calendar.HOUR_OF_DAY)).append(":");
formattedDate.append(date.get(Calendar.MINUTE));
return formattedDate.toString();
}
}[/code]
Resultado na máquina Windows:
Sem Timezone: 21/2/2011 13:42
America/São_Paulo: 21/2/2011 13:42
Brazil/East: 21/2/2011 13:42
Resultado na máquina Debian:
Sem Timezone: 21/2/2011 8:49
America/São_Paulo: 21/2/2011 13:49
Brazil/East: 21/2/2011 13:49
Desconsiderem as diferenças de minutos. Quero que vejam que os resultados batem. Para finalizar o teste, rodei o comando date do Linux via SSH para obter a data e horário da máquina servidora e obtive o seguinte resultado:
Mon Feb 21 08:51:05 PST 2011
Chego a conclusão que o problema deva ser com o MySQL. Alguma configuração errada ou talvez anotação errada no Hibernate. Não sei. Alguém sabe o que pode estar acontecendo? É a primeira vez que trabalho com fuso horário no Java e estou apanhando demais.
Minha classe Hibernate que é persistida:
[code]@Entity
@Table(name = “tm_app_execution”)
public class AppExecution implements Serializable {
private static final long serialVersionUID = -1461955698187380141L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "APP_EXECUTION_ID")
private Long appExecutionID;
@Column(name = "DATE_STARTED", nullable = false)
private Calendar dateStarted;
@Column(name = "DATE_FINISHED", nullable = true)
private Calendar dateFinished;
@Column(name = "EXECUTION_TIME", nullable = true)
private Integer executionTime;
@Column(name = "CONSOLE_PARAMS_USED", nullable = true)
private String consoleParamsUsed;
@Column(name = "HAVE_ERROR", nullable = true)
private Boolean haveError;
public Long getAppExecutionID() {
return appExecutionID;
}
public void setAppExecutionID(Long appExecutionID) {
this.appExecutionID = appExecutionID;
}
public Calendar getDateStarted() {
return dateStarted;
}
public void setDateStarted(Calendar dateStarted) {
this.dateStarted = dateStarted;
}
public Calendar getDateFinished() {
return dateFinished;
}
public void setDateFinished(Calendar dateFinished) {
this.dateFinished = dateFinished;
}
public Integer getExecutionTime() {
return executionTime;
}
public void setExecutionTime(Integer executionTime) {
this.executionTime = executionTime;
}
public String getConsoleParamsUsed() {
return consoleParamsUsed;
}
public void setConsoleParamsUsed(String consoleParamsUsed) {
this.consoleParamsUsed = consoleParamsUsed;
}
public Boolean getHaveError() {
return haveError;
}
public void setHaveError(Boolean haveError) {
this.haveError = haveError;
}
}[/code]
No MySQL estou usando InnoDB.
Resumindo o problema após toda essa explicação: Quando vou persistir um objeto Calendar usando Hibernate e Timezone America/Sao_Paulo em um banco de dados MySQL rodando em uma máquina Linux Debian configurado com o fuso horário PST, ele está gravando no horário PST ao invés de usar o fuso America/Sao_Paulo.
Se alguém precisar de mais alguma informação, é só pedir. Esse erro está bem chato de resolver.
Obrigado