LoginSignup
131
131

More than 5 years have passed since last update.

Rails3系のtimezoneの扱いに関するメモ

Last updated at Posted at 2012-09-26

ローカルタイムに関する設定

Rails3系からデータベースにはUTCで保存、取り出して扱う際に必要なタイムゾーンに変更するというのが基本的な考え方の様子。

タイムゾーンの設定はapplication.rbにて行えるが、主に関係する設定が2つある。

  • config.active_record.default_timezone
  • config.time_zone

config.active_record.default_timezone

データベースに保存する際のタイムゾーンを指定するディレクティブ。先ほど書いたようにRails3からはデータベースに時刻を保存する場合は基本的にUTCで保存するようになったみたいで、これをローカルタイムで保存するには以下のように設定すれば良い。

config/application.rb
config.active_record.default_timezone = :local

config.time_zone

こちらが色々悩ましそうな感じで今確認出来たところだとActiveSupport::TimeZoneクラスの出力に影響を与える様子。試しに何も設定しない場合とtime_zoneをtokyoにした場合で色々出力してみると

設定しない場合

Time.zone # => (GMT+00:00) UTC
Time.zone.now # Mon, 24 Sep 2012 09:19:35 UTC +00:00 

Tokyoにした場合

config/application.rb
config.time_zone = 'Tokyo' 
Time.zone # => (GMT+09:00) Tokyo
Time.zone.now #=> Mon, 24 Sep 2012 18:16:43 JST +09:00

とこの様に出力が変更されていることが確認できた。注意が必要なのはActiveSupport::TimeZoneを使うにはTime.zoneで処理を行う必要がありTime.nowのようにTimeで直接処理すると設定に関係なくローカルタイムで表示されてしまう点。

Time / Time.zoneの違い

Time.class      # => Class (常にローカル扱い)
Time.zone.class # => ActiveSupport::TimeZone (config.time_zoneの設定に依存) 

ということでユーザによってタイムゾーンを変える必要があるアプリケーションは
* config.time_zone = 'Tokyo' を設定する
* Time.zoneを常に使う (追記: ActiveRecordと併用する場合はto_s(:db)でUTCに変換 => DB登録時に更に時刻の差分を補正と2重に処理が走ってしまうので注意)

更に追記、config.time_zoneを変更してしまうとActiveRecordを利用する際に
* オブジェクトを生成したタイミングでタイムゾーンをUTCに合わせようとする
* Arelなどwhereをする際にカラムの値で指定する場合などでは合わせようとしない
という違いが発生してしまう。

オブジェクトを生成した場合の挙動
created_at = "2012-09-01 00:00:00"
@example = Example.new(:created_at => created_at)
@example.created_at # => 2012-08-31-15:00:00
Arelを利用する場合の挙動
created_at = "2012-09-01 00:00:00"
Example.where(:created_at => created_at).to_sql # => SELECT `examples`.* FROM `examples`  WHERE `examples`.`created_at` = '2012-09-01 00:00:00

なので、結果的には何も設定せずにユーザ毎に自前で処理するのが良いかもしれないです…

常にローカルタイムで良いアプリケーションは
* config.active_record.default_timezone = :localを設定する
* config.time_zone = 'Tokyo'

って感じが良いのだろうか?

Tips

データベース用のフォーマット変換する

Time.zone.to_s(:db)は使ってしまうと事故が起きそう…

Time.zone.now.to_s(:db) # UTCに自動的に変更される
Time.zone.now.strftime("%Y-%m-%d %H:%M:%S") # ローカルタイムのまま
Time.now.to_s(:db)      # ローカルタイムのまま
131
131
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
131
131