O que um TimeZone pode fazer por você
As vezes, o uso de algumas combinações pregam uma grande peça.
Neste post, vou expor algo que acontece quando se usa ICEFaces para manipular datas através do componente selectInputDate combinado com o conversor convertDateTime.
O uso do trecho de código abaixo…
<ice:selectInputDate id="dataInicio"
renderMonthAsDropdown="true" renderYearAsDropdown="true"
title="Selecione a Data" renderAsPopup="true"
required="true" value="#{meuBackingBean.dataInicio}"
partialSubmit="true">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm:ss"/>
</ice:selectInputDate>
… produz um resultado BEM DIFERENTE do trecho de código abaixo.
<ice:selectInputDate id="dataInicio"
renderMonthAsDropdown="true" renderYearAsDropdown="true"
title="Selecione a Data" renderAsPopup="true"
required="true" value="#{meuBackingBean.dataInicio}"
partialSubmit="true">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</ice:selectInputDate>
E quando digo diferente, digo da pior maneira possível.
Antes de mostrar o resultado, perceberam a diferença entre as implementações?
A única diferença está na definição do pattern na tag convertDateTime.
Suponhamos que neste objeto seja selecionado a data de 03/02/2010, e isto foi feito as 17h52.
Para o trecho com o pattern indicando dd/MM/aaaa HH:mm:ss, o resultado da definição do atributo dataInicio no Backing Bean é “setDataInicio=Wed Feb 03 17:52:28 BRST 2010″. Correto, se o componente não tivesse exibido estas mesmas informações no input com o horário 2h a frente.
Para o trecho com o pattern indicando dd/MM/aaaa, o resultado da definição do atributo dataInicio no Backing Bean é “setDataInicio=Wed Feb 02 22:00:00 BRST 2010″. Errado, bem errado. Notem que aqui o componente, por algum motivo, criou ou formatou a data/hora usando o timezone GMT e subtraiu 2h (já que estamos no timezone America/Sao_Paulo).
O que fazer para solucionar isso?
Para resolver esta questão será necessário adicionar o atributo timeZone no formatador convertDateTime.
<ice:selectInputDate id="dataInicio"
renderMonthAsDropdown="true" renderYearAsDropdown="true"
title="Selecione a Data" renderAsPopup="true"
required="true" value="#{meuBackingBean.dataInicio}"
partialSubmit="true">
<f:convertDateTime pattern="dd/MM/yyyy" timeZone="#{meuBackingBean.timeZone}"/>
</ice:selectInputDate>
Neste caso, adicionamos #{meuBackingBean.timeZone} como valor do atributo timeZone.Por algum motivo, esta definição torna-se obrigatória para que a data não seja criada com horário incorreto.
No Backing Bean, o que devemos implementar é:
@Component
@scope("session")
public class MeuBackingBean.... {
private java.util.Timezone timeZone = TimeZone.getDefault();
...
public TimeZone getTimeZone() {
return this.timeZone;
}
}