会社のWebサービスがRailsでPostgreSQLを使っているのですが、DBで保存されているタイムスタンプのタイムゾーンがよく分からず小一時間調べて複雑だったのでメモ。
それぞれのタイムゾーン設定状況
Ruby on Railsのタイムゾーン設定
config.active_record.default_timezone = :local
config.time_zone = 'Tokyo'
application.rbのconfig.time_zoneはRuby on Railsのタイムゾーンで理解しやすいのですが、config.active_record.default_timezoneの認識を間違っていてハマってしまいました。config.active_record.default_timezoneはActiveRecordがDBの読み書きに使用するタイムゾーンと理解すれば良いようです。このため、DBにタイムゾーンを設定していてもRails側はconfig.active_record.default_timezoneの設定したタイムゾーンで時間を取り扱います。そしてここを:localにしたとき、それはDBの設定を使うという意味ではなく、サーバーの設定を使うという意味です。Herokuを使っているならHeroku、DockerならDockerのタイムゾーンになるわけですね。
PostgreSQLのタイムゾーン設定
show timezone;
Postgreにログインして上記のコマンドで設定しているタイムゾーンを確認できます。UTCでした。
Herokuのタイムゾーン設定
$ heroku run bash
$ date
Herokuにログインしてbashでタイムゾーンを確認できます。JSTでした。
ActiveRecordのタイムゾーンは何になるのか
というわけで、まとめると設定は下記の通りになります。
- Ruby on Rails JST
- ActiveRecord Herokuに準拠
- PostgreSQL UTC
- Heroku JST
つまり、WebサービスはJSTで動いているということになります。ActiveRecordはJSTで時間を読み書きし、Ruby on RailsもJSTで取り扱います。しかしPostgreSQLは時刻をUTCで保存していると思っています。これは気持ち悪いですね…。なんでこんな設定にしてしまっているんだろう…。