Marcio Trindade

Problemas com timezone no ActiveRecord

Quando você esta usando o ActiveRecord você acaba aproveitando os campos mágicos createdat e updatedat do Rails, mas uma coisa que poucos sabem é como ele lida com estes.

Quando você inicia a aplicação o Rails seta o time zone de acordo com a sua configuração, seja ela no application.rb no rails 3.x ou enveronment.rb no rails 2.x, porém este time zone não é utilizado no ActiveRecord por uma questão de configuração também, sendo assim quando um registro é criado o Rails utiliza o Time.zone.utc como padrão e salva no banco a hora com time zone utc, e quando ele traz este registro de volta a mágica é feita novamente e altera esta hora para o seu time zone, porém quando você utiliza estes como condições a mágica já não acontece, então é preciso que você faça isso manalmente. Veja um exemplo abaixo.

console
User.create(:name => "Marcio Trindade") # criar o registro com o time zone UTC.
User.where(:created_at => Time.now) # busca com o time zone da sua aplicação.
User.where(:created_at => Time.now.utc) # busca com o time zone UTC igual ao registro.

Então quando for utilizar Time.now ou mesmo Date.today em consultas não se esqueça de utilizar o utc para não ter o mesmo problema que tive.

Outra solução é alterar a configuração do seu ActiveRecord pra salvar estes campos mágicos com o time zone da sua aplicação dentro do banco de dados, o que pode ser uma dor de cabeça quando você tiver a mesma aplicação rodando em diferentes zonas. Para este modo a configuração fica no mesmo arquivo em que você seta o time zone da aplicação.

config/application.rb
config.time_zone = 'Brasilia' # altera o time zone para a aplicação
config.active_record.default_timezone = :local # altera o ActiveRecord pra gravar os campos mágicos com o mesmo time zone da aplicação

Na minha experiência a melhor alternativa é setar o time zone pra utc em suas condições, mas tenho uma aplicação que é específica de uma região e optei por usar a segunda alternativa.