いろいろ調べたけど、解決法はあっさり簡単だったのでメモしておく。
前提としては、データベースへの保存は UTC、アプリでの入出力はローカルタイムで行う。
サンプルアプリの作成
簡単なサンプルアプリを作る。
takatoh@nightschool $ rails new sampleapp takatoh@nightschool $ cd sampleapp takatoh@nightschool $ rails g scaffold items name:string release:datetime takatoh@nightschool $ rake db:migrate
サーバを起動して http://localhost:3000/items にアクセスすると下のような画面になる。
データを入力してみる
試しに一つ、データを入力してみよう。New Item リンクをクリックして新規データ入力のページに移動。
今、日本ではは午前10時51分だ。時刻が UTC で表示されているのがわかる。
データをひとつ入力してみたあとが↓これ。時刻は UTC で表示されている。
試しに、コンソールで確認してみよう。
takatoh@nightschool $ rails c Loading development environment (Rails 4.1.4) 2.1.1 :001 > Item.find(1) Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."id" = ? LIMIT 1 [["id", 1]] => #<Item id: 1, name: "Sampe item 1", release: "2014-11-22 01:51:00", created_at: "2014-11-22 01:51:30", updated_at: "2014-11-22 01:51:30">
release や created_at、 updated_at の値が 01:51:30 になっている。UTC とは書いていないけど、時刻からデータベースにも UTC で保存されているのがわかる。
アプリの入出力を日本時間にするには
config/application.rb に次の行を追加する。サンプルがコメントアウトされているので、その次辺りに入れればいいだろう。
config.time_zone = 'Asia/Tokyo'
書き加えたら、サーバを起動しなおして、itemsページにアクセスしてみよう。
今度は時刻が日本時間(+0900)で表示された!
じゃあ、新しいデータを入力するときはどうか。
ここも日本時間になっている。
データベースではどうか
コンソールで確かめてみよう。
Loading development environment (Rails 4.1.4) 2.1.1 :001 > item = Item.find(2) Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."id" = ? LIMIT 1 [["id", 2]] => #<Item id: 2, name: "SAmple item 2", release: "2014-11-22 02:07:00", created_at: "2014-11-22 02:08:15", updated_at: "2014-11-22 02:08:15"> 2.1.1 :002 > item => #<Item id: 2, name: "SAmple item 2", release: "2014-11-22 02:07:00", created_at: "2014-11-22 02:08:15", updated_at: "2014-11-22 02:08:15">
release や created_at、updated_at の時刻は 02:08:15 になっている。データベースには相変わらず UTC で保存されているのがわかる。
ちなみに、取得した Item クラスのインスタンス item からは日本時間に変換された時刻が返ってくる。
2.1.1 :003 > item.release => Sat, 22 Nov 2014 11:07:00 JST +09:00
まとめ
Rails 4 をローカル時間に合わせるには、config/application.rb に1行追記するだけでいい。あとは Rails が全てうまくやってくれる。