Ruby On Rails PR

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

Docker+Rails6でTimeZoneを UTCからJSTに変更する方法! 設定方法はとても簡単!
記事内に商品プロモーションを含む場合があります

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

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

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

開発環境とバージョン

 

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

  • Docker
  • Rails 6.0.1
  • MySQL Ver 8.0.18

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

タイムゾーンを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 consoleirbを起動して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と記載されているのが分かります。

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

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

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

docker-compose.yml

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

docker-composeの変更は一度dockerコンテナを再起動しないと反映されないので、docker-compose downdocker-compose upの2つのコマンドを実行して再起動を行った後に動作確認をしましょう。

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の変更を行う事でTimeTimeWithZoneの挙動が下記のように変わります。

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:seedActiveRecord経由でインサートを行うと…

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_time03:00として扱われ、日本時間の01-12 06:30に入れたデータが 前日の01-11 21:30になってしまいました。

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

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を起動しなおしたか

まとめ

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

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

【初心者向け】 MacでRailsを使えるようにするための環境構築方法を徹底解説!
【初心者向け】MacでRailsを使えるようにするための環境構築方法を徹底解説! 今回の記事ではこんな方に向けて記事を書きます。 本記事の対象読者 Macを利用してRailsの環境構築をしたいRubyやRa...
ABOUT ME
himakuro
新卒で入社したブラック企業から脱出して超ホワイトな会社に転職。エンジニア歴は7年で普段はウェブサービス作ったりブログを書いたり、MENTAで未経験者の方にプログラミングを指導しています。
PR
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール