Fusos horários brasileiros no Ruby on Rails

Estou fazendo um sistema onde o usuário pode adicionar uma data limite para a execução de algumas operações, após trabalhar um pouco em algumas telas e ter que fazer algumas conversões na data e hora para ser exibida corretamento no Bootstrap 3 Datepicker, me veio a preocupação em relação aos fusos horários brasileiros.
 
 Inicialmente pensei em adotar o horário de Brasília e colocar observações nos locais onde as datas e hora seriam exibidas, pois inicialmente o sistema teria um uso maior nas regiões que utilizam este fuso horário, além disso tornaria a implementação um pouco mais fácil.
 
 Depois pensei em como eu gostaria que o sistema se comportasse se fosse eu o usuário, aí não restou dúvida, mesmo sabendo que o público alvo se concentraria mais em uma região, o serviço ainda continuará na nuvem, podendo ser acessado de todo o território nacional.
 
 O Brasil possui 27 Unidades Federativas, sendo que apenas 9 utilizam o horário de Brasília, desta forma optar por utilizar apenas este fuso horário, seria ignorar 18 UFs!
 
 Existem diversos posts a respeito de como utilizar o fuso horário do usuário que fez a requisição, um é o It’s About Time (Zones) do pessoal da thoughtbot, que descreve até a inclusão do campo do fuso horário na edição do perfil do usuário.
 
 A classe do Rails que contem os fusos horários é a ActiveSupport::TimeZone, porém o único fuso horário brasileiro é o de Brasília e eu gostaria de colocar todos os fusos horários, são apenas 4, nas primeiras opções do select.
 
 A biblioteca TZInfo, utilizada pelo ActiveSupport::TimeZone, apresenta os seguintes fusos para o Brasil:

Para adicionar os novos fusos, criei o arquivo config/initializers/active_support/time_zone.rb com o seguinte conteúdo:

Fiz um mapeamento usando os nomes dos fusos horários que estão na Wikipédia, forcei as variávies @zones e @zones_map para nil, pois elas são cacheadas durante a criação do objeto que representa a classe ActiveSupport::TimeZone, desta forma quando clientes da classe fazem uso dos métodos all e/ou zone_maps (as únicas formas de acessá-las sem metaprogramação), estas variáveis são recomputadas.
 
 Por último adicionei o método br_zones, inspirado no método us_zones, presente na classe, o que facilita a criação do select:

<%= f.input :time_zone, priority: ActiveSupport::TimeZone.br_zones %>


Originally published at cerdiogenes.blogspot.com.br on February 12, 2016.