« HE:labs
HE:labs

Evitando problemas com datas e time zones no Rails

Postado por Cayo Medeiros (yogodoshi) em 11/06/2013

Volta e meia passo por alguns problemas com time zones no Rails. Hoje, demonstrarei algumas dicas para evitá-los:

A primeira coisa a ser feita para evitar problemas é setar a time zone do projeto no config/application.rb para Brasília (se o site for basileiro): config.time_zone = 'Brasilia' e não para "UTC -3" ou algo do gênero; de forma a evitar problemas com horário de verão também.

Dessa forma, o Rails permanecerá a hora certa para que seja salva no banco de dados corretamente em UTC 0, como mandam as regras. Da mesma forma, quando você puxar algo salvo no banco em UTC 0, ele já mostrará na tela a time zone do projeto utilizada corretamente.

Só que não!

O problema é que o Rails tem métodos que retornam a data em UTC 0 e outros, de acordo com a time zone do projeto.

Porém, a boa notícia é que você pode seguir essa cheat sheet sempre que for trabalhar com time zones para não ter problemas e rapidamente irá decorar quais métodos devem ou não ser usados.

Não use

1 Time.now # => Retorna o horário do sistema e ignora a time zone do projeto.
2   Time.parse("2012-03-02 16:05:37") # => Irá assumir que a string recebida tá na time zone do sistema.
3   Time.strptime(time_string, '%Y-%m-%dT%H:%M:%S%z') # Mesmo problema do Time.parse.
4   Date.today # Pode ser ontem ou amanhã de acordo com a time zona setada na máquina.
5   Date.today.to_time # => # Também não segue a time zone do projeto.

Use

 1 2.hours.ago # => Fri, 02 Mar 2012 20:04:47 UTC -03:00
 2   1.day.from_now # => Fri, 03 Mar 2012 22:04:47 UTC -03:00
 3   Date.today.to_time_in_current_zone # => Fri, 02 Mar 2012 22:04:47 UTC -03:00
 4   Date.current # => Fri, 02 Mar
 5   Time.zone.parse("2012-03-02 16:05:37") # => Fri, 02 Mar 2012 16:05:37 UTC -03:00
 6   Time.zone.now # => Fri, 02 Mar 2012 22:04:47 UTC -03:00
 7   Time.current # Mesma coisa, só que de forma mais curta.
 8   Time.zone.today # Se você não pode usar Time ou DateTime.
 9   Time.zone.now.utc.iso8601 # Quando for trabalhar com APIs.
10   Time.strptime(time_string, '%Y-%m-%dT%H:%M:%S%z').in_time_zone(Time.zone) # Se não pode usar Time.pars

Outra dica que recomendo é sempre escrever testes com horários limites. Exemplo: se quero uma query com os itens da semana passada, crio documentos no banco com domingo 23:59 e segunda 00:01, justamente para ter certeza de que não teremos problemas com time zone em lugar algum.

Fonte: o excelente post da elabs.se (quase nossa xará =p)

Compartilhe

Sabia que nosso blog agora está no Medium? Confira Aqui!