4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby on Rails + PostgreSQL】時刻・日付に関する型のまとめ

Posted at

この記事で扱うこと

以下の情報について、覚書としてまとめました。

  • migrationファイルで日付・時間に関する型を宣言した際、PostgreSQLデータベース上のテーブルの型は何になっているのか。
  • PostgreSQLデータベース上でタイムゾーンはどう扱われるのか。

実行バージョンは、PostgreSQL 10.6 と Ruby on Rails 5.2.4です。

PostgreSQLに用意されている日付・時刻に関する型

PostgreSQLのドキュメントには、日付・時刻に関する型は6種類あると記載されています。中でも、

  • timestamp without time zone
  • timestamp with time zone
  • date
  • time with time zone
  • time without time zone

の5つがmigrationファイルの型と対応していると想像されます。これら5つとmigrationファイルの型の対応関係をまとめました。

マイグレーションを実行してみる

以下のmigrationファイルを作成し、rails db:migrate を実行します。


class CreateSchedules < ActiveRecord::Migration[5.2]
  def change
    create_table :schedules do |t|
      t.date :begin_at_by_date_type
      t.time :begin_at_by_time_type
      t.datetime :begin_at_by_datetime_type
      t.timestamp :begin_at_by_timestamp_type
    end
  end
end

この時、PostgreSQLデータベースのテーブルのスキーマは以下です。

 begin_at_by_date_type                | date                        | 
 begin_at_by_time_type                | time without time zone      | 
 begin_at_by_datetime_type            | timestamp without time zone | 
 begin_at_by_timestamp_type           | timestamp without time zone | 

基本的に、タイムゾーンが付かない型としてスキーマが定義されるようですね。

注意すべきなのは、migrationファイルで timedatetimetimestamp 型を定義した場合にはUTCに変換されて保存される一方、date 型に関してはタイムゾーンの変換が行われず、元のタイムゾーンの日付のまま保存されるという点です。

実際に実行して試してみます。例としてJSTのタイムゾーンを指定しました。

Schedule.create(
  begin_at_by_date_type: "2020-01-01 06:00:00+09:00",
  begin_at_by_time_type: "2020-01-01 06:00:00+09:00",
  begin_at_by_datetime_type: "2020-01-01 06:00:00+09:00",
  begin_at_by_timestamp_type: "2020-01-01 06:00:00+09:00"
)

これをデータベースでみると、

| begin_at_by_date_type | begin_at_by_time_type | begin_at_by_datetime_type  | begin_at_by_timestamp_type 
| 2020-01-01            | 21:00:00              | 2019-12-31 21:00:00        | 2019-12-31 21:00:00        | 

となっています。date 型の場合のみ、JSTのタイムゾーンの日付が保存されていることがわかりますね。

タイムゾーンの情報を保持するには

設計の良し悪しについては本記事では言及しませんが、データベースに日時の値を値を保存する際はUTCに統一するケースが多いでしょう。しかし、例外的にタイムゾーンの情報も保持したい場合、次のようなmigrationファイルを作成します。

class CreateSchedules < ActiveRecord::Migration[5.2]
  def change
    create_table :schedules do |t|
      t.date :begin_at_by_date_type
      t.time :begin_at_by_time_type
      t.datetime :begin_at_by_datetime_type
      t.timestamp :begin_at_by_timestamp_type
      t.column :begin_at_by_timestamp_with_time_zone, 'timestamp with time zone'
    end
  end
end

この時、PostgreSQLデータベースのテーブルのスキーマは以下です。

 begin_at_by_date_type                | date                        | 
 begin_at_by_time_type                | time without time zone      | 
 begin_at_by_datetime_type            | timestamp without time zone | 
 begin_at_by_timestamp_type           | timestamp without time zone | 
 begin_at_by_timestamp_with_time_zone | timestamp with time zone    | 

これで、タイムゾーン付きで日時のデータを保存することができるようになります。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?