Você já teve problemas com fuso horário ao converter datas em JSF?

266 views
Skip to first unread message

Rafael Ponte

unread,
Aug 10, 2015, 8:22:07 AM8/10/15
to jav...@googlegroups.com, javace
Olá senhores,

Há grandes chances de vocês já terem gravado data e hora errada no banco de dados por causa do fuso horário (timezone), certo? Esse problema parece ser um pouco mais comum ao trabalhar com JSF pois ele define um fuso horário padrão: UTC.

Apesar da boa intenção do JSF, isso acaba complicando nossa vida e só percebemos esse problema em produção. Mas não se preocupe, existem algumas práticas que podem te ajudar a contornar isso:


Além de entender o problema e aprender a resolvê-lo você também aprende algumas boas práticas sobre como trabalhar com fuso horário na sua aplicação Web. #fikadica

Vale a pena a leitura!

Um abraço a todos!


--
Rafael Ponte
TriadWorks | Formação Java
http://cursos.triadworks.com.br

Rafael Ponte

unread,
Aug 10, 2015, 8:56:54 AM8/10/15
to jav...@googlegroups.com, Javace
Oi Virgilio,

Fuso horário é algo muito delicado mesmo. É tão delicado e trabalhoso quanto trabalhar com internacionalização.

Sobre o highlight do código é um problema sim. Eu também percebi isso. Estou procurando um theme de cores mais bacanudo pois aquele ficou escurão mesmo.

Um abraço e obrigado pelo feedback!



On Mon, Aug 10, 2015 at 9:54 AM Virgilio Ximenes <virgilio...@gmail.com> wrote:
Muito boa leitura! Não conhecia nem a configuração do web.xml, tampouco o atributo do converter. Muito massa.
É um pouco complicado acompanhar as atualizações, não só o JSF, mas do Java, pois em muitos ambientes corporativos as versões são 1.2 e 5, respectivamente.

Lembro que utilizei uma aplicação há algum tempo, a hora recuperada era do servidor, que ficava em outro país e o formato era do servidor, embora no ato da criação da conta pedisse o local onde eu morava, logo era possível saber que eu estava em um fuso diferente e que a formatação da data também é diferente. Ficava estranho ver a data algumas horas "a mais".

Duas observações:
0 - Região norte fica em outro timezone, então o Brasil tem 2 timeszones;
1 - Os valores das tags "param-name" e "param-value" estão escuras em um fundo escuro.
--
Você recebeu essa mensagem porque está inscrito no grupo "java.ce" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para javace+un...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para jav...@googlegroups.com.
Acesse esse grupo em http://groups.google.com/group/javace.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Atenciosamente,
Virgílio Rocha Ximenes

--
Você recebeu essa mensagem porque está inscrito no grupo "javasf: JavaServer Faces Group" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para javasf+un...@googlegroups.com.
Acesse esse grupo em http://groups.google.com/group/javasf.
Para ver essa discussão na Web, acesse https://groups.google.com/d/msgid/javasf/CAA5Bhiw%2BJcuwHfmoqHp%3DpoQHgTAsAKo5o5bPaZi381gLkKCWgw%40mail.gmail.com.
Para mais opções, acesse https://groups.google.com/d/optout.

Bruno Maomeh

unread,
Aug 10, 2015, 10:01:44 AM8/10/15
to jav...@googlegroups.com

Opa Virgilio, é só algumas partes da região Norte que está no timezone diferente de Brasília (só no Acre, se não me engano) e Fernando de Noronha também está em outro timezone.. então o Brasil tem 3 timezones..

Hedley Luna

unread,
Aug 10, 2015, 1:31:58 PM8/10/15
to java.ce
Na verdade, são 4 fusos: um que só pega o Acre(UTC-5), um que pega o Amazonas e uma parte do centro-oeste(UTC-4), o geral (UTC-3) e o de fernando de noronha(UTC-2). Né não?

Bruno Maomeh

unread,
Aug 10, 2015, 1:49:20 PM8/10/15
to jav...@googlegroups.com

é verdade Hedley, é isso mesmo. acabei de conferir aqui..
utc-2 Fernando de Noronha
utc-3 Brasília
utc-4 Amazônia
utc-5 Acre

Rafael Ponte

unread,
Aug 10, 2015, 1:51:56 PM8/10/15
to jav...@googlegroups.com
Oi Bruno e Hedley,

Muito legal, eu sinceramente só conhecia 2 fusos horários. Apesar de já ter tido problemas sérios devido a timezone, infelizmente nunca tive que implementar uma aplicação com suporte a múltiplos fusos.

Valeu pela dica! Fica como aprendizado!

Virgilio Ximenes

unread,
Aug 10, 2015, 4:33:16 PM8/10/15
to Javace, jav...@googlegroups.com
Muito boa leitura! Não conhecia nem a configuração do web.xml, tampouco o atributo do converter. Muito massa.
É um pouco complicado acompanhar as atualizações, não só o JSF, mas do Java, pois em muitos ambientes corporativos as versões são 1.2 e 5, respectivamente.

Lembro que utilizei uma aplicação há algum tempo, a hora recuperada era do servidor, que ficava em outro país e o formato era do servidor, embora no ato da criação da conta pedisse o local onde eu morava, logo era possível saber que eu estava em um fuso diferente e que a formatação da data também é diferente. Ficava estranho ver a data algumas horas "a mais".

Duas observações:
0 - Região norte fica em outro timezone, então o Brasil tem 2 timeszones;
1 - Os valores das tags "param-name" e "param-value" estão escuras em um fundo escuro.
Em 10 de agosto de 2015 09:21, Rafael Ponte <rpo...@gmail.com> escreveu:
--
Você recebeu essa mensagem porque está inscrito no grupo "java.ce" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para javace+un...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para jav...@googlegroups.com.
Acesse esse grupo em http://groups.google.com/group/javace.
Para mais opções, acesse https://groups.google.com/d/optout.

Euder Levi

unread,
Aug 14, 2015, 10:51:37 AM8/14/15
to jav...@googlegroups.com
Olá Rafael Ponte,

Fiquei com uma dúvida nesse contexto.

Se a gente usar o parametro javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE como true, e pegássemos o fuso horário do servidor, 

não cairíamos no problema do Horário de Verão, por exemplo ?

Supondo que o servidor ficasse em São Paulo, e a gente aqui em Fortaleza, essa abordagem do web.xml não teria essa desvantagem?

abraços.

Rafael Uchôa

unread,
Aug 14, 2015, 11:39:06 AM8/14/15
to javace
Ponte,

Muito legal o artigo. Eu só acrescentaria de não pegar a data do servidor de aplicação e sim do banco de dados, ou seja, não usar 'new Date()'.

Acho mais interessante porque é ele que vai manter os dados consistentes, ou seja, se você tiver em cloud e/ou com load balance de servidores, para evitar ter que instalar o ntp em cada servidor, e ter problemas de cadastro não aparecendo devido 1 segundo sequer, é melhor pegar do banco de dados.

Outra coisa é que se o campo só importa a data, ou seja, não importa a hora, é bom zerar a hora, e não deixar gravar com a hora que foi gerada, por isso que o banco diferem date de timestamp.

E o ultimo, acho interessante deixar o fuso igual do browser do usuário. É chato entrar na amazon e vê a hora da compra, a hora de USA, se você pegar do banco e mostrar usando o componente, ele vai converter para o locale do usuário obtido do browser.

Valeu!!!


Rafael Uchôa
www.naskar.com.br


Rafael Ponte

unread,
Aug 14, 2015, 5:19:11 PM8/14/15
to jav...@googlegroups.com
Oi Euder,

Por o fuso horário ser configurado e trabalhado no lado servidor toda a manipulação de data e hora seria com o fuso de SP.

Por o JSF estar pegando o fuso horário do sistema operacional então o Horário de Verão será levado em conta se o sistema operacional também levar em conta.

Faz sentido?

Rafael Ponte

unread,
Aug 14, 2015, 5:33:33 PM8/14/15
to jav...@googlegroups.com
Oi Uchoa,

On Fri, Aug 14, 2015 at 12:39 PM 'Rafael Uchôa' via java.ce <jav...@googlegroups.com> wrote:
Ponte,

Muito legal o artigo. Eu só acrescentaria de não pegar a data do servidor de aplicação e sim do banco de dados, ou seja, não usar 'new Date()'.

Acho mais interessante porque é ele que vai manter os dados consistentes, ou seja, se você tiver em cloud e/ou com load balance de servidores, para evitar ter que instalar o ntp em cada servidor, e ter problemas de cadastro não aparecendo devido 1 segundo sequer, é melhor pegar do banco de dados.

É uma alternativa obter a data e hora atual do banco de dados, muitos sistemas fazem isso. Eu confesso que normalmente utilizo a data da aplicação mesmo, isto é, o "new Date()". 

Contudo, quando trabalho com sistemas onde o horário é critico eu costumo utilizar o conceito de Relogio na aplicação, assim simplifica a vida na hora de escrever os testes de unidade:

Relogio relogio = new RelogioDoSistema();
Date hoje = relogio.hoje()

Outra vantagem dessa abordagem é que seria simples ter uma implementação que obtivesse a data do banco de dados. O que você acha?
 

Outra coisa é que se o campo só importa a data, ou seja, não importa a hora, é bom zerar a hora, e não deixar gravar com a hora que foi gerada, por isso que o banco diferem date de timestamp.

Verdade. Vou mais longe, é muito importante definir a precisão da data no mapeamento da JPA, caso contrário erros sérios podem ocorrer. É até um tópico importante que discutimos no nosso curso de persistência.
 

E o ultimo, acho interessante deixar o fuso igual do browser do usuário. É chato entrar na amazon e vê a hora da compra, a hora de USA, se você pegar do banco e mostrar usando o componente, ele vai converter para o locale do usuário obtido do browser.

Concordo com você, mas vai depender dos requisitos da aplicação.

Se é um sistema corporativo que roda somente no CE então não há necessidade de obter o fuso horário do usuário. Caso seja um sistema que pode ser acessado de qualquer lugar do país então é melhor usar as preferências do usuário. 
 
Faz sentido?

Um abraço!

Rafael Uchôa

unread,
Aug 18, 2015, 12:54:39 PM8/18/15
to javace
Oi Ponte, desculpe a demora. Tempo..tempo..tempo.. rs

Seguem as respostas.

Valeu!!!!

Rafael Uchôa
www.naskar.com.br



Em 14 de agosto de 2015 18:33, Rafael Ponte <rpo...@gmail.com> escreveu:
Oi Uchoa,

On Fri, Aug 14, 2015 at 12:39 PM 'Rafael Uchôa' via java.ce <jav...@googlegroups.com> wrote:
Ponte,

Muito legal o artigo. Eu só acrescentaria de não pegar a data do servidor de aplicação e sim do banco de dados, ou seja, não usar 'new Date()'.

Acho mais interessante porque é ele que vai manter os dados consistentes, ou seja, se você tiver em cloud e/ou com load balance de servidores, para evitar ter que instalar o ntp em cada servidor, e ter problemas de cadastro não aparecendo devido 1 segundo sequer, é melhor pegar do banco de dados.

É uma alternativa obter a data e hora atual do banco de dados, muitos sistemas fazem isso. Eu confesso que normalmente utilizo a data da aplicação mesmo, isto é, o "new Date()". 

Contudo, quando trabalho com sistemas onde o horário é critico eu costumo utilizar o conceito de Relogio na aplicação, assim simplifica a vida na hora de escrever os testes de unidade:

Relogio relogio = new RelogioDoSistema();
Date hoje = relogio.hoje()

Outra vantagem dessa abordagem é que seria simples ter uma implementação que obtivesse a data do banco de dados. O que você acha?

>> Qualquer abstração de encapsulamento e isolamento é ótimo, segundo as leis do oeste, vulgo S.O.L.I.D., “Depend upon Abstractions. Do not depend upon concretions.”, ou seja, se você usar Relogio, Time ou qualquer abstração, é ótimo.


Eu preferiria usar interfaces, ou seja, contratos, do que uma classe concreta, só por causa do 'new'. A JVM ainda não tem "new interceptor", por isso o advento dos IoC's.

interface Time {
   getCurrentTime();
   getTimeByStr(String date);
}

class DatabaseTime implements Time {
    getCurrentTime() {
      return select sysdate from dual;
    }
}

class AppServerTime implements Time {
     getCurrentTime() {
        return new Date();
     }
}

Na hora de testar, é só mockar ou trocar a implementação.
 
 

Outra coisa é que se o campo só importa a data, ou seja, não importa a hora, é bom zerar a hora, e não deixar gravar com a hora que foi gerada, por isso que o banco diferem date de timestamp.

Verdade. Vou mais longe, é muito importante definir a precisão da data no mapeamento da JPA, caso contrário erros sérios podem ocorrer. É até um tópico importante que discutimos no nosso curso de persistência.

>>> Show!!!
 
 

E o ultimo, acho interessante deixar o fuso igual do browser do usuário. É chato entrar na amazon e vê a hora da compra, a hora de USA, se você pegar do banco e mostrar usando o componente, ele vai converter para o locale do usuário obtido do browser.

Concordo com você, mas vai depender dos requisitos da aplicação.

Se é um sistema corporativo que roda somente no CE então não há necessidade de obter o fuso horário do usuário. Caso seja um sistema que pode ser acessado de qualquer lugar do país então é melhor usar as preferências do usuário. 
 
Faz sentido?

>>>> Show, se você definir o TIMEZONE e encapsular da forma que você está dizendo dentro da classe Relogio, tanto para pegar a data atual, quanto pra converter uma string que vem da página usando o conversor, setando o Locale também, sim, porque assim, você não depende do servidor de aplicação está configurado para pt_br, mesmo estando no CE ou em qualquer parte do mundo, daria inconsistências, pois o 'new Date' que o JSF faria estaria diferente do 'new Date()' que você faz dentro das suas regras de negócio.

Então é bom manter o uso dessa classe Relogio/Time também dentro do conversor.

Outra restrição é que somente sua aplicação use essa base, incomum, mesmo em aplicações somente CE, que sempre tem integrações, relatórios, etc.
Reply all
Reply to author
Forward
0 new messages