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:
br = TZInfo::Country.get('BR') br.zone_names => ["America/Noronha", "America/Belem", "America/Fortaleza", "America/Recife", "America/Araguaina", "America/Maceio", "America/Bahia", "America/Sao_Paulo", "America/Campo_Grande", "America/Cuiaba", "America/Santarem", "America/Porto_Velho", "America/Boa_Vista", "America/Manaus", "America/Eirunepe", "America/Rio_Branco"]
Para adicionar os novos fusos, criei o arquivo config/initializers/active_support/time_zone.rb com o seguinte conteúdo:
ActiveSupport::TimeZone::MAPPING['Fernando de Noronha'] = 'America/Noronha' ActiveSupport::TimeZone::MAPPING['Amazônia'] = 'America/Manaus' ActiveSupport::TimeZone::MAPPING['Acre'] = 'America/Rio_Branco' ActiveSupport::TimeZone.instance_variable_set('@zones', nil) ActiveSupport::TimeZone.instance_variable_set('@zones_map', nil) module ActiveSupport class TimeZone def self.br_zones @br_zones ||= all.find_all { |z| z.name =~ /Brasilia|Noronha|Amazônia|Acre/ } end end end
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 %>