Rails 5.1 から time 型の列もタイムゾーン考慮するようになるとのこと

経緯

Rails 5 で time 型の列をもつレコードを操作していたところ、以下のようなメッセージが表示された。

DEPRECATION WARNING: Time columns will become time zone aware in Rails 5.1. This
still causes `String`s to be parsed as if they were in `Time.zone`,
and `Time`s to be converted to `Time.zone`.

To keep the old behavior, you must add the following to your initializer:

    config.active_record.time_zone_aware_types = [:datetime]

To silence this deprecation warning, add the following:

    config.active_record.time_zone_aware_types = [:datetime, :time]
 (called from require at bin/rails:4)

Rails 5.1 からデフォルトの挙動が変わるからねー、ということらしい。

Time columns will be aware of application time zone In Rails 5.1 your time columns will adhere to the time zone of your Rails application. To make the upgrade path smoother, the config.active_record.time_zone_aware_types option has been added. See the deprecation warning here for help.

http://weblog.rubyonrails.org/2015/1/16/This-week-in-Rails-tokens-migrations-method-source-and-more/

該当のPR: https://github.com/rails/rails/pull/15726

何が変わるのか

create_table "foos", force: :cascade do |t|
  t.time "start_at"
end
= form_for @foo do |f|
  = f.time_field :start_at
  = f.submit

なときに、「09:00」と入力して submit すると

Parameters: {"foo"=>{"start_at"=>"09:00"}}

のようなパラメータでリクエストが飛ぶ。

このとき、

今までの挙動

config.time_zone = 'Tokyo'
config.active_record.time_zone_aware_types = [:datetime]

だと

irb(main):001:0> Foo.first
#<Foo id: 1, start_at: "2000-01-01 09:00:00", created_at: "2016-07-18 04:07:26", updated_at: "2016-07-18 04:07:26">
irb(main):002:0> Foo.first.start_at
=> 2000-01-01 09:00:00 UTC

のように UTC で 9:00 だったのが、

新しい挙動

config.time_zone = 'Tokyo'
config.active_record.time_zone_aware_types = [:datetime, :time]

だと

irb(main):001:0> Foo.first
#<Foo id: 1, start_at: "2000-01-01 00:00:00", created_at: "2016-07-18 04:07:26", updated_at: "2016-07-18 04:07:26">
irb(main):002:0> Foo.first.start_at
=> Sat, 01 Jan 2000 09:00:00 JST +09:00

のように JST で 9:00 になる。

対応

Deprecation warning 抑えるためには適当な initializer 内(config/application.rb とか)で config.active_record.time_zone_aware_types を設定する。

既存の挙動(タイムゾーン考慮しない)を保つ場合は

config.active_record.time_zone_aware_types = [:datetime]

新しい挙動(タイムゾーン考慮する)にする場合は

config.active_record.time_zone_aware_types = [:datetime, :time]

にする。