Railsのタイムゾーン設定について
株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。
DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら弊社HPからご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。
- プロジェクトでRailsエンジニアが足りなくて困っている
- Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
- オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい
また、Railsエンジニアも募集しておりますので、興味がありましたら弊社HPからご連絡いただけますと幸いです。
前提
本記事は表題の通り、Railsのタイムゾーンで考慮しなければならないことが多くあったので備忘録として残しておきます。
Railsのタイムゾーン関連には2つの設定がある
Railsのタイムゾーン関連で調べてみると大まかに2つの設定がありました。
config.time_zone
config.active_record.default_timezone
この2つの設定をするだけなのに、考慮しなければならないことが多くありました。
まとめ(タイムゾーンを日本時間にしたい場合に設定すること)
- OSのタイムゾーン設定をAsia/Tokyoにする
- ローカルのMacで開発していれば、おそらくTokyoの設定になっているので不要
- Dockerなどを使っている場合には、UTCとなっているためDockerファイルやdocker-compose.ymlの設定でAsia/Tokyoにする
- config/application.rb内で、
config.time_zone = 'Tokyo'
を設定する - config/application.rb内で、
config.active_record.default_timezone = :local
にする - OSの再起動、rails serverの再起動で設定を反映させる
Railsの2つの設定の違い
2つの設定の違いは以下のようになっています。
設定項目 | 設定される内容 |
---|---|
config.time_zone | Rails自体のアプリケーションの時刻の設定 |
config.active_record.default_timezone | DBを読み書きする際に、DBに記録されている時間をどのタイムゾーンで読み込むかの設定 |
Railsのタイムゾーンで考慮しなければならない設定
この記事を読む際に、以下のタイムゾーン設定が関係してくることを頭の片隅に入れておいてください。
- OSのタイムゾーン設定
- Railsのタイムゾーン設定(config.time_zone)
- ActiveRecordでレコードを読み書きする際のタイムゾーン設定(config.active_record.default_timezone)
実際に試してみる
config.time_zone='UTC'
、config.active_record.default_timezone='UTC'
OSタイムゾーン:UTC、まずは、config.time_zone
もconfig.active_record.default_timezone
もデフォルトのままでrails console
で挙動を確認してみます。
ただし、実行環境のOSのタイムゾーン設定はUTCとしているので、ローカルで開発している場合にはタイムゾーン設定が違う可能性があるため注意が必要です。
Time.now
=> 2021-05-22 04:34:18.938170881 +0000
Time.current
=> Sat, 22 May 2021 04:34:20.861324049 UTC +00:00
User.create(name: 'test', email: 'test@test.com')
=> <User id: 4, name: "test", email: "test@test.com", created_at: "2021-05-22 04:36:00.738175000 +0000", updated_at: "2021-05-22 04:36:00.738175000 +0000">
user.created_at
=> Sat, 22 May 2021 04:36:00.738175000 UTC +00:00
実際のDBのレコードに保存されているcreated_atのタイムスタンプ
2021-05-22 04:36:00.738175
表示項目 | 表示されているタイムゾーン |
---|---|
Time.now | UTC |
Time.current | UTC |
User.createで表示されるcreated_at | UTC |
user.created_atで表示されるcreated_at | UTC |
実際のDBのレコードのタイムスタンプ | UTC |
すべてUTCで表示されています。(当たり前の結果ですね。)
では、config.time_zone
だけをconfig.time_zone='Tokyo'
に変更してみるとどうなるでしょうか。
config.time_zone='Tokyo'
、config.active_record.default_timezone= :UTC
OSタイムゾーン:UTC、Time.now
=> 2021-05-22 04:40:15.267729046 +0000
Time.current
=> Sat, 22 May 2021 13:40:17.768190047 JST +09:00
user = User.create(name: 'test1', email: 'test1@test.com')
=> <User id: 4, name: "test", email: "test@test.com", created_at: "2021-05-22 04:36:00.738175000 +0000", updated_at: "2021-05-22 04:36:00.738175000 +0000">
user.created_at
=> Sat, 22 May 2021 13:36:00.738175000 JST +09:00
実際のDBのレコードに保存されているcreated_atのタイムスタンプ
2021-05-22 04:40:30.082069
表示項目 | 表示されているタイムゾーン |
---|---|
Time.now | UTC |
Time.current | JST |
User.createで表示されるcreated_at | UTC |
user.created_atで表示されるcreated_at | JST |
実際のDBのレコードのタイムスタンプ | UTC |
Time.current
とuser.created_at
の出力結果がJSTの時刻となっています。
それ意外はUTCとなっています。
Time.now
はOSのタイムゾーンの結果(この場合ではUTC)を返し、Time.current
はRailsアプリのタイムゾーンの結果(この場合ではJST)を返すため違う結果が返ってきます。
しかし、ActiveRecordの読み書きの設定はUTC(config.active_record.default_timezone= :UTC
)なのに、user.created_at
がJSTで表示されるのはなぜでしょうか?
これは、config.time_zone
の設定はActiveSupport::TimeWithZoneに影響するためです。
そのため、ActiveRecordのcreated_atの日時に関する表示は、config.time_zone
で設定したタイムゾーン(今回の場合JST)に変換されるためです。
次に、config.active_record.default_timezone
の設定を変更してみましょう。
この設定で気をつけることは、config.time_zone
とは違い:UTC
か:local
の2つの設定しかサポートしていないことです。
ActiveRecordを読み書きする際に、:UTC
と設定されていればUTC時刻として読み書きすることになり、:local
と設定すると、OSのタイムゾーン設定と同じ形になります。
そのため今回の場合では、OSのタイムゾーン設定がUTCとなっているため、ActiveRecordの読み書きもUTCとなるはずです。
config.time_zone='UTC'
、config.active_record.default_timezone= :local
OSタイムゾーン:UTC、Time.now
=> 2021-05-22 05:01:03.079872846 +0000
Time.current
=> Sat, 22 May 2021 05:01:05.337906708 UTC +00:00
User.create(name: 'test2', email: 'test2@test.com')
=> <User id: 6, name: "test2", email: "test2@test.com", created_at: "2021-05-22 05:01:26.756013000 +0000", updated_at: "2021-05-22 05:01:26.756013000 +0000">
user.created_at
=> Sat, 22 May 2021 05:01:26.756013000 UTC +00:00
実際のDBのレコードに保存されているcreated_atのタイムスタンプ
2021-05-22 05:01:26.756013
表示項目 | 表示されているタイムゾーン |
---|---|
Time.now | UTC |
Time.current | UTC |
User.createで表示されるcreated_at | UTC |
user.created_atで表示されるcreated_at | UTC |
実際のDBのレコードのタイムスタンプ | UTC |
OSタイムゾーン:UTC、config.time_zone='UTC'
、config.active_record.default_timezone= :UTC
と同じ実行結果になっていることがわかります。(当然の結果ですね。)
config.active_record.default_timezone= :local
はOSのタイムゾーン設定を引き継ぐので、config.active_record.default_timezone
の設定は:local
のままにして、OSのタイムゾーンを変更して実行してみましょう。
config.time_zone='UTC'
、config.active_record.default_timezone= :local
OSタイムゾーン:Asia/Tokyo、Time.now
=> 2021-05-22 14:16:09.609170085 +0900
Time.current
=> Sat, 22 May 2021 05:16:12.199845378 UTC +00:00
user = User.create(name: 'test6', email: 'test6@test.com')
=> <User id: 10, name: "test6", email: "test6@test.com", created_at: "2021-05-22 05:16:24.630028000 +0000", updated_at: "2021-05-22 05:16:24.630028000 +0000">
user.created_at
=> Sat, 22 May 2021 05:16:24.630028000 UTC +00:00
実際のDBのレコードに保存されているcreated_atのタイムスタンプ
2021-05-22 14:16:24.630028
表示項目 | 表示されているタイムゾーン |
---|---|
Time.now | JST |
Time.current | UTC |
User.createで表示されるcreated_at | JST |
user.created_atで表示されるcreated_at | UTC |
実際のDBのレコードのタイムスタンプ | JST |
Time.now
はOSのタイムゾーンの結果を返すため、JSTが結果として返される形となります。
また、config.active_record.default_timezone= :local
となっているため、実際のDBのレコードのタイムスタンプがOSのタイムゾーンであるJSTとして保存されています。
ただし、user.created_at
に関しては前述の通り、config.time_zone
がUTCとなっているため、ActiveRecordのcreated_atの日時に関する表示はUTCになっています。
では、すべてをJSTにしたい場合の設定をして確認してみましょう。
config.time_zone='Tokyo'
、config.active_record.default_timezone= :local
OSタイムゾーン:Asia/Tokyo、この設定により、OSのタイムゾーン設定、Railsアプリケーションのタイムゾーン設定、ActiveRecordで読み書きする際のタイムゾーン設定がJSTになります。
挙動を確認してみましょう。
Time.now
=> 2021-05-22 14:34:53.4952888 +0900
Time.current
=> Sat, 22 May 2021 14:34:56.058340301 JST +09:00
user = User.create(name: 'test7', email: 'test7@test.com')
=> <User id: 11, name: "test7", email: "test7@test.com", created_at: "2021-05-22 14:35:10.214590000 +0900", updated_at: "2021-05-22 14:35:10.214590000 +0900">
user.created_at
=> Sat, 22 May 2021 14:35:10.214590000 JST +09:00
実際のDBのレコードに保存されているcreated_atのタイムスタンプ
2021-05-22 14:35:10.214590
表示項目 | 表示されているタイムゾーン |
---|---|
Time.now | JST |
Time.current | JST |
User.createで表示されるcreated_at | JST |
user.created_atで表示されるcreated_at | JST |
実際のDBのレコードのタイムスタンプ | JST |
無事、すべてがJSTになっていることが確認できました。
めでたしめでたし。
参考記事
Discussion