MAGAZINE

ルーターマガジン

Ruby

ActiveRecordのみでDBから取得した時刻を日本時刻にする方法

2025.07.18
Pocket

はじめに

ActiveRecordを使い始めた多くの開発者が直面する問題の一つが、タイムゾーンの扱いです。「なぜDBから取得した時刻がUTCになってしまうのか?」「日本時間で保存したはずなのに、取得すると9時間ずれている」「時刻の比較処理が期待通りに動かない」といった問題に遭遇し、デバッグに時間を費やした経験がある方も多いのではないでしょうか。

マイクロサービスやシンプルなバッチ処理などで、Railsを使うほどでもないけれどActiveRecordだけは使いたい場合に「ActiveRecord タイムゾーン 日本時刻」で検索してもRailsでの設定方法ばかりが出てきて、ActiveRecord単体での設定方法に辿り着けないことがあったので、この記事ではRails環境を使わずにActiveRecordのみを使用して、DBから取得した時刻を日本時刻にする方法を解説します。

タイムゾーンを設定しないとどうなるか?

ActiveRecordでタイムゾーンを適切に設定しないと、以下のような問題が発生します:

1. 時刻がUTCで表示される

# タイムゾーン設定なしの場合
user = User.create!(name: 'テストユーザー')
puts user.created_at
# => 2025-07-11 03:00:00 UTC  # 日本時間の12:00がUTCで表示される

2. 時刻の比較や日付判定が意図しない結果になる

# 日本時間の朝9時にバッチを実行したつもりが...
if Time.now.hour == 9
  puts "朝の処理を実行"
end
# => UTCの朝9時(日本時間の夕方6時)に実行される

# 日付境界の処理でも同様の問題が発生
if Date.current.wday == 1  # 月曜日の処理
  puts "月曜日の処理を実行"
end
# => 日本時間では火曜日なのに、UTC基準で月曜日と判定される

これらの問題が発生する理由は、ActiveRecordのdefault_timezone設定のデフォルト値が:utcになっているためです。

# ActiveRecordのデフォルト設定を確認
puts ActiveRecord::Base.default_timezone
# => :utc

この設定は、ActiveRecordがデータベースから日時データを取得する際、およびデータベースに日時データを保存する際にどのタイムゾーンを使用するかを決定します。:utcの場合、ActiveRecordはシステムタイムゾーンやローカルタイムゾーン(ActiveSupportのTime.zone)に関係なく、常にUTCタイムゾーンでデータベースとやり取りします。

つまり、システムタイムゾーンがAsia/Tokyoに設定されていても、ActiveSupportでTime.zone_defaultを設定していても、ActiveRecord.default_timezone:utcのままであれば、データベースとのやり取りは常にUTCで行われます。

タイムゾーンを日本時刻(JST)にする設定方法

1. 必要なgemのインストール

# Gemfile
gem 'activerecord'
gem 'activesupport'
gem 'mysql2'  # MySQLの場合
# gem 'pg'    # PostgreSQLの場合

2. ActiveRecordの基本設定

require 'active_record'
require 'active_support'
require 'active_support/core_ext'

# データベース接続設定
ActiveRecord::Base.establish_connection(
  adapter: 'mysql2',
  host: 'localhost',
  username: 'root',
  password: 'password',
  database: 'your_database'
)

# 重要:バージョン互換性を保つタイムゾーン設定
Time.zone_default = Time.find_zone!('Tokyo')
ActiveRecord::Base.default_timezone = :local     # Rails 6.x以前
ActiveRecord.default_timezone = :local              # Rails 7.0以降

ここで、ActiveRecordのバージョンによってタイムゾーンの設定方法が異なってきます。

Rails 7.0以前(ActiveRecord 7.0以前)

# Rails 7.0以前の設定方法
ActiveRecord::Base.default_timezone = :local

Rails 7.0以降(ActiveRecord 7.0以降)

# Rails 7.0以降の推奨設定方法
ActiveRecord.default_timezone = :local

Rails 7.0以降でActiveRecord::Base.default_timezone = :localを使うとNoMethodErrorになります。

>> ActiveRecord::Base.default_timezone = :local
/.rbenv/versions/3.3.6/lib/ruby/gems/3.3.0/gems/activerecord-8.0.2/lib/active_record/dynamic_matchers.rb:22:in `method_missing': undefined method `default_timezone=' for class ActiveRecord::Base (NoMethodError)
Did you mean?  default_column_serializer=

各設定の詳細解説

Time.zone_default = Time.find_zone!('Tokyo')

この設定により:

  • ActiveSupportのタイムゾーンヘルパーが日本時間を使用
  • Time.currentTime.zone.nowが日本時間を返す
  • Date.currentも日本時間基準になる

ActiveRecord.default_timezone = :local

この設定により:

  • データベースから取得した日時をローカルタイムゾーン(上記で設定した東京)として解釈
  • データベースへ保存時もローカルタイムゾーンで保存

まとめ

Railsを使わずにActiveRecordのみでタイムゾーンを日本時刻に設定するには、バージョンに応じた適切な設定が重要です。

解説した設定により、マイクロサービスやバッチ処理などの軽量なアプリケーションでも、確実に日本時刻でデータベースとやり取りできるようになります。

データベースとの整合性を保つため、データベース側のタイムゾーン設定も忘れずに行いましょう。

Pocket

CONTACT

お問い合わせ・ご依頼はこちらから