LoginSignup
16
9

More than 3 years have passed since last update.

Rails + Heroku 環境で、レコードのタイムゾーンがずれていることに気が付いた際に確認したいこと & リカバリ方法

Last updated at Posted at 2017-12-19

Heroku としては DB のタイムゾーンは UTC としておくことを推奨しています。例えばユーザ環境が JST となる場合、保存時には -9時間 (UTC変換) し、表示時に +9時間 (JST変換) する形となります。

こちらは Heroku Postgres の例となりますが、 How to change the Timezone setting for Heroku Postgres? でもデータベースのタイムゾーンは UTC に設定し、アプリケーションレベルでの変換を推奨しています。

以下、推奨される方法ではありませんが、元記事を残しておきます。


DB を直接参照した時に created_at が UTC になっていることに気がつくこと、よくありますよね。

TL; DR

  • heroku 使うときは heroku config:add TZ=Asia/Tokyo し忘れがちなので気をつけろ
  • リカバる時は heroku run bash してから Rails Console 立ち上げろ

まず確認するポイント

time_zone, default_timezone

# config/application.rb
config.time_zone = "Tokyo"
config.active_record.default_timezone = :local

こちらは問題なし。

heroku config

$ heroku config
=== app-name Config Vars
JAWSDB_URL: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
LANG: en_US.UTF-8
RACK_ENV: production
RAILS_ENV: production
RAILS_LOG_TO_STDOUT: enabled
RAILS_MASTER_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
RAILS_SERVE_STATIC_FILES: enabled
SECRET_KEY_BASE: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

TZ 設定忘れてますね...

リカバリ作業

1. heroku のタイムゾーンを Tokyo にする

$ heroku config:add TZ=Asia/Tokyo

2. ついでに LANG も変更する

$ heroku config:add LANG=ja_JP.UTF-8

3. Heroku に SSH

$ heroku run bash
Running bash on ⬢ app-name... up, run.6391 (Free)

4. Rails Console の立ち上げ

$ rails c -e production
Loading production environment (Rails 5.1.4)

時間修正

irb(main):001:0> tasks = Task.where("created_at < ?" , "2017-12-19 21:10:00") # ※1
=> #<ActiveRecord::Relation [#<Task id: 1, name: "洗濯", created_at: "2017-12-16 05:06:45", updated_at: "2017-12-16 05:06:45">, #<Task id: 2, name: "風呂掃除", created_at: "2017-12-16 05:06:58", updated_at: "2017-12-16 05:06:58">, #<Task id: 3, name: "トイレ掃除", created_at: "2017-12-16 05:07:04", updated_at: "2017-12-16 05:07:04">, #<Task id: 4, name: "電子レンジ掃除", created_at: "2017-12-16 05:07:16", updated_at: "2017-12-16 05:07:16">]>

irb(main):002:0> tasks.update_all("created_at = created_at + interval 9 hour")
=> 4

irb(main):003:0> tasks.update_all("updated_at = updated_at + interval 9 hour")
=> 4

irb(main):004:0> tasks.map{|t| Rails.logger.info "id: #{t.id}, created_at: #{t.created_at}, updated_at: #{t.updated_at}"}
I, [2017-12-19T21:17:52.254054 #8] INFO -- : id: 1, created_at: 2017-12-16 23:06:45 +0900, updated_at: 2017-12-16 3:06:45 +0900
I, [2017-12-19T21:17:52.254558 #8] INFO -- : id: 2, created_at: 2017-12-16 23:06:58 +0900, updated_at: 2017-12-16 3:06:58 +0900
I, [2017-12-19T21:17:52.254790 #8] INFO -- : id: 3, created_at: 2017-12-16 23:07:04 +0900, updated_at: 2017-12-16 3:07:04 +0900
I, [2017-12-19T21:17:52.254968 #8] INFO -- : id: 4, created_at: 2017-12-16 23:07:16 +0900, updated_at: 2017-12-16 3:07:16 +0900
=> [true, true, true, true]

※1 「1. heroku のタイムゾーンを Tokyo にする」 の実施時間より前の日時を where 句に指定すること

蛇足

TZ 設定し忘れがちなので、 Terraform 書いた
tetsuya/kochiku-heroku

16
9
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
16
9