config.time_zone = 'Tokyo' と設定しても、ActiveRecordがDBに保存する際のタイムゾーンはデフォルトのUTCで保存する
疑問の発端
code: .rb
# ここではJST時間でクエリが発行されてるのに、
Time.current.all_week # 現在の週の開始日時(今週月曜の0:00~)と終了日時(今週日曜の~23:59)
=> 2024-12-02 00:00:00.000000000 JST +09:00..2024-12-08 23:59:59.999999999 JST +09:00
# whereで検索すると、日時の範囲が15:00~14:59のUTC時間になっている
Event.where(start_at: Time.current.all_week)
Event Load (46.5ms) SELECT "events".* FROM "events" WHERE "events"."start_at" BETWEEN '2024-12-01 15:00:00' AND '2024-12-08 14:59:59.999999' /* loading for pp */ LIMIT 11
前提として:タイムゾーンは東京に指定されてる状態。
code: .rb
# config/application.rb
config.time_zone = "Asia/Tokyo"
UTC理由でクエリが発行される理由
Railsアプリケーションでは、デフォルトでデータベースに保存される日時はUTCになっている。
Event.first.start_atが2024-12-24 12:00:00 JSTと返されるのは、RailsがJST(日本標準時)に変換して表示しているため。実際には、DBにはUTCで保存されている。Railsは内部的にはUTCで日時を管理し、表示する際にユーザーのタイムゾーンに合わせて変換している。
デフォルトでデータベースに保存される日時を変更するには、config.active_record.default_timezoneを追加する
code: rb
# config/application.rb
config.time_zone = "Asia/Tokyo"
# 以下を追加
config.active_record.default_timezone = :local # localは、config.time_zoneで指定したタイムゾーン
この設定でEvent.first.start_atを見ると
code: .rb
# 追加前
Event.first.start_at
Event Load (1.6ms) SELECT "events".* FROM "events" ORDER BY "events"."id" ASC LIMIT 1
=> 2024-12-24 12:00:00.000000000 JST +09:00
# 追加後
Event.first.start_at
Event Load (1.6ms) SELECT "events".* FROM "events" ORDER BY "events"."id" ASC LIMIT
=> 2024-12-24 03:00:00.000000000 JST +09:00