はじめに
Ruby on Railsの開発では、日付や時間情報を扱う際に、date型やdatetime型を使うことが多いです。
その時に、date型からdatetime型、datetime型からdate型に型変更したときにタイムゾーンによって値がどのように変更されるのかを残します。
前提
- Ruby on Rails:7.0
- PostgreSQL:14.9 (MySQLでも同様の結果になると予想されます)
- アプリケーション側(Rails)のタイムゾーンはJSTで、DBサーバ(PostgreSQL)のタイムゾーンはUTC
カラムの型をdate型からdatetime型に変更する
DBのカラムの型をdate型からdatetime型に変更すると、どうなるのでしょうか。
今回は例として、ユーザの誕生日に時間情報を追加したいと思います。(自分の誕生時間を知ってる人がいるかは置いておきます)
usersテーブルとbirthdayカラムを作成します。
create_table :users do |t|
t.date :birthday
end
データを見ると、Rails側では以下のようなデータになります。
birthday: Sat, 02 Dec 2023
PostgreSQL側では以下のようなデータになります。
birthday: 2023-12-02
同じ日付になってますね。
では、マイグレーションでdate型からdatetime型を変えます。
change_column :users, :birthday, :datetime, precision: 6
このとき、birthdayカラムには日付情報しかなかったレコードに時間情報が追加されます。
データを見ると、Rails側では以下のようなデータになり、「09:00」が追加されています。
birthday: Sat, 02 Dec 2023 09:00:00.000000000 JST +09:00
PostgreSQL側では以下のようなデータになり、「00:00」が追加されています。
birthday: 2023-12-02 00:00:00
結果
表にまとめると、以下のようになりました。
カラム型 | アプリケーション側(JST) | DB側(UTC) |
---|---|---|
date型 | 2023-12-02 | 2023-12-02 |
datetime型 | 2023-12-02 09:00:00 | 2023-12-02 00:00:00 |
DBのカラムの型をdate型からdatetime型に変更すると、データベース側で自動で00:00が追加されます。
DBサーバのタイムゾーンはUTCなので、JSTでは9時の時間となります。
カラムの型をdatetime型からdate型に変更する
新しくデータを入れ、datetime型のbirthdayカラムに、JSTで「12/02 00:00」を入れました。
birthday: Sat, 02 Dec 2023 00:00:00.000000000 JST +09:00
そして、PostgreSQLから見ると、タイムゾーンはUTCなので「12/01 15:00」になっています。
birthday: 2023-12-01 15:00:00
このdatetime型のbirthdayカラムをdate型に変更します。
すると、Rails側から見ると、datetime型では「12/02」だったのに対し、「12/01」になっています。
birthday: Sat, 01 Dec 2023
そして、PostgreSQL側から見ると、「12/01」のままで日付に変更はなく、時間情報のみなくなっています。
birthday: 2023-12-01
結果
表にまとめると、以下のようになりました。
カラム型 | アプリケーション側(JST) | DB側(UTC) |
---|---|---|
datetime型 | 2023-12-02 00:00:00 | 2023-12-01 15:00:00 |
date型 | 2023-12-01 | 2023-12-01 |
DBのカラムの型をdatetime型からdate型に変更すると、時間情報がなくなり、日付情報だけが残るようになります。
このとき、タイムゾーンはDBサーバのタイムゾーンを元に変更されるため、JSTでは0時を超えていても、UTCでは0時を超えていないという状況が発生します。
まとめ
date型→datetime型では、「DBサーバのタイムゾーンでの00:00が追加」され、
dattime型→date型では、「DBサーバのタイムゾーンで時間情報のみなくなる」という結果になりました。
設定したタイムゾーンによってはインシデントやデータの不整合につながるため、型変更する際は既存データの値を修正する作業が必要になると思います。
おわりに
date型、datetime型の型変更での値の変化について見てみました。タイムゾーンと型変換は割とトラブルが起きやすいところだと思うので注意が必要ですね。