Docker+Rails6でTimeZoneをUTCからJSTに変更する方法!設定方法はとても簡単!

5 min
Docker+Rails6でTimeZoneを UTCからJSTに変更する方法! 設定方法はとても簡単!
Sponsored Link
himakuro

himakuro

新卒で入社したブラック企業から脱出して超ホワイトな会社に転職。エンジニア歴は7年で普段はウェブサービス作ったりブログを書いたり、MENTAで未経験者の方にプログラミングを指導しています。

FOLLOW

今回の記事ではDockerを使ったRailsの開発環境で、MySQLに対してJST(日本時間)でレコードを入れる方法を書いて行きます。

RailsではデフォルトのタイムゾーンがUTCになっているため、日本時間だと思ってdb:seedで初期データを投入したりすると、想定していた時間とは違う値でレコードがインサートされてしまいます。

今回紹介する方法はとても簡単なので、TimeZoneをJSTで固定したい方は是非参考にしてみてください。


開発環境とバージョン

今回himakuroが検証した環境は下記のような構成になっているよ

開発環境&使用バージョン

  • Docker
  • Rails 6.0.1
  • MySQL Ver 8.0.18

今回僕が開発している環境ではDockerを使っていますが、Dockerを使っていない場合でも今回紹介する変更でタイムゾーンをJSTに変更可能です。

Sponsored Link

タイムゾーンをJSTに変更する方法

早く変更箇所が知りたいという人のために、先に変更方法だけざっくりと記載します。

TZをJSTに変更する方法

  1. 環境変数TZを用意し、 ‘Asia/Tokyo’ をセットする
  2. config/application.rbに下記の2行を足す
    • config.time_zone = ‘Asia/Tokyo’
    • config.active_record.default_timezone = :local

それぞれの設定項目がどう影響するか、確認方法などを次の項目から説明していきます。

Rails(Ruby)のタイムゾーンを確認

まずは変更を加える前にrails consoleでirbを起動してTimeコマンドの挙動を確認します。

Rails Console


$ rails c
irb(main):001:0> Time.now
=> 2020-01-11 20:48:31 +0000

irb(main):002:0> Time.current
=> Sat, 11 Jan 2020 20:48:35 UTC +00:00

irb(main):003:0> Time.zone.now
=> Sat, 11 Jan 2020 20:49:58 UTC +00:00

Time.nowではTZが表示されていないけど、他の2つはしっかりとUTCと記載されているのがわかるね!

Sponsored Link

Rubyプロセスのタイムゾーンを変更

最初に環境変数TZをセットしてRubyプロセスのタイムゾーンを変更していきます。

Dockerを使っている場合はdocker-compose.ymlか、 .env ファイル経由でセットするのが楽だと思います。

docker-compose.yml


 build: .
 environment: #追加
    TZ: "Asia/Tokyo" #追加

docker-composeの変更は一度dockerコンテナを再起動しないと反映されないので、docker-compose down, docker-compose upで起動し直した後に動作確認をしましょう。

Rails Console


$ rails c
irb(main):001:0> Time.now
=> 2020-01-12 06:07:44 +0900

irb(main):002:0> Time.current
=> Sat, 11 Jan 2020 21:07:45 UTC +00:00

irb(main):003:0> Time.zone.now
=> Sat, 11 Jan 2020 21:07:47 UTC +00:00

Time.nowの結果の末尾に +0900と記載され、JSTの時間が表示されるようになったよ!

Railsのtime_zoneを変更する

続いてRails側の設定変更です。

config/application.rb


module App
  class Application < Rails::Application
    # 末尾に下記の1行を追加
    config.time_zone = 'Asia/Tokyo' #追加
  end
end

config.time_zoneの変更を行う事でTimeやTimeWithZoneの挙動が下記のように変わります。

Rails Console


$ rails c
irb(main):001:0> Time.now
=> 2020-01-12 06:21:15 +0900

irb(main):002:0> Time.current
=> Sun, 12 Jan 2020 06:21:18 JST +09:00

irb(main):003:0> Time.zone.now
=> Sun, 12 Jan 2020 06:21:23 JST +09:00

しかしこの状態でdb:seedやActiveRecord経由でインサートを行うと…

Rails Console


$ rails c
irb(main):001:0> user = User.new
   (0.5ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483

irb(main):002:0> user.execute_time = '2020-1-12-12:00:00'
=> "2020-1-12-12:00:00"

irb(main):003:0> user.save
   (0.3ms)  BEGIN
  User Create (0.4ms)  INSERT INTO `users` (`execute_time`, `created_at`, `updated_at`) VALUES ('2020-01-12 03:00:00', '2020-01-11 21:30:00.00000', '2020-01-11 21:30:00.00000')

12:00にセットした execute_timeが 03:00として扱われ、日本時間の01-12 06:30に入れたデータが 前日の01-11 21:30になってしまいました。

よって上記のtime_zoneの設定だけではActive RecordのタイムゾーンはまだUTCのままだということがわかります。

Sponsored Link

ActiveRecordのタイムゾーンをJSTに変更する

RailsではActive Recordのタイムゾーンを変更するのも1行追加するだけで可能です。

config/application.rb


module App
  class Application < Rails::Application
    config.time_zone = 'Asia/Tokyo'
    # 末尾に下記の1行を追加
    config.active_record.default_timezone = :local # 追加
  end
end

ActiveReocrdのdefault_timezone = :localに指定することで、Rubyプロセスのタイムゾーンを見てくれるようになります。

Rails Console


$ rails c
irb(main):001:0> user = User.new
   (0.4ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483

irb(main):002:0> user.execute_time = '2020-01-12 12:00:00'
=> "2020-01-12 12:00:00"

irb(main):003:0> user.save
   (0.4ms)  BEGIN
  User Create (0.7ms)  INSERT INTO `users` (`execute_time`, `created_at`, `updated_at`) VALUES ('2020-01-12 12:00:00', '2020-01-12 06:40:00.00000', '2020-01-12 06:40:00.00000')
   (3.1ms)  COMMIT
=> true

無事に発行されるINSERT文も想定通りのものになってくれました。

こんな感じでRailではTZの環境変数を用意して、config/application.rbに2行追加するだけでタイムゾーンをJSTにすることが出来るよ!

タイムゾーンがJSTにならない場合

今回紹介した方法でもまだタイムゾーンが日本時間のJSTにならない場合は下記の事を確認してみましょう。

確認ポイント

  1. Command Lineに date を入力したら日本時間が返ってくるか
  2. docker-compose変更後にコンテナを再起動したか
  3. コードを変更した後にRails Consoleを起動しなおしたか

まとめ

タイムゾーンを固定しないと、時間に関連する処理を行った際に予期せぬ問題が発生する場合があります。

今回紹介した方法でしっかりと、どのタイムゾーンで処理を行っているかを意識してコーディングするようにしましょう。

Sponsored Link
himakuro

himakuro

新卒で入社したブラック企業から脱出して超ホワイトな会社に転職。エンジニア歴は7年で普段はウェブサービス作ったりブログを書いたり、MENTAで未経験者の方にプログラミングを指導しています。

FOLLOW

カテゴリー:
関連記事

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です