RailsでDBのマイグレーションファイルを作成するとtimeとdatetimeがあります。timeは時刻を持つため項目ですが日付情報を持つことができません。しかし、プログラム中からInsertを投げても、”2000年1月1日”として登録されてエラーになりません。
私の場合のドハマリ例
私の場合はdatetimeとすべきだったところをtimeとしていたため、画面から”2019/01/01 5:00″や”2019/01/01″を登録しても、”2000/01/01″になってしまう事例に頭を悩ませていました。すでに修正した部分があるので、下記には、time項目に日付付きデータを登録した場合の挙動を示します。発生する事象
TimeDetail.create(
ymd: Time.zone.parse("2019/06/01")
, user_id: 1
, time_from: Time.zone.parse("2019/06/01 09:00")
, time_to: Time.zone.parse("2019/06/01 18:00")
, exclusion: Time.parse("2019/06/01 01:00")
, time_result:Time.parse("2019/06/01 08:00")
)
コンソールで1行取得した結果
<TimeDetail
id: 4
, ymd: "2019-06-01"
, user_id: 1
, time_from: "2019-06-01 00:00:00"
, time_to: "2019-06-01 09:00:00"
, exclusion: "2000-01-01 01:00:00"
, time_result: "2000-01-01 08:00:00"
, created_at: "2019-11-03 15:40:43"
, updated_at: "2019-11-03 15:40:43"
>
exclusionとtime_resultは「time」でマイグレーションした項目です。登録時には2019/6/1 1:00と2019/6/1 8:00で、エラーになっていません。しかし登録データを見てみると、2000/1/1になっています。明確に「時刻だけを持つ」ケースではtimeでマイグレーションしてもよいですが、日付とともに時刻を持つ場合にはdatetimeとする必要があります。
Rails上の型
下記のように試してみました。マイグレーション時がtime、datetimeであるかを問わず、Rails上の方はActiveSupport::TimeWithZoneとなっているようです。そのためRails上までは「日時」で持っているのかもしれませんが、DBに登録以降、日付が切り捨てられてしまっていると思われます。>> TimeDetail.last.id.class
=> Integer
>> TimeDetail.last.ymd.class
=> Date
>> TimeDetail.last.user_id.class
=> Integer
>> TimeDetail.last.time_from.class
=> ActiveSupport::TimeWithZone
>> TimeDetail.last.time_to.class
=> ActiveSupport::TimeWithZone
>> TimeDetail.last.exclusion.class
=> ActiveSupport::TimeWithZone
>> TimeDetail.last.time_result.class
=> ActiveSupport::TimeWithZone
>> TimeDetail.last.created_at.class
=> ActiveSupport::TimeWithZone
>> TimeDetail.last.updated_at.class
=> ActiveSupport::TimeWithZone
time項目への登録例
見直し後もtimeでよさそうな項目はあったので、登録処理部分のサンプルとして残しておきます。TimeDetail.create(
ymd: Time.zone.parse("2019/05/01")
, user_id: 1
, time_from: Time.zone.parse("2019/05/01 09:00")
, time_to: Time.zone.parse("2019/05/01 18:00")
, exclusion: Time.parse("01:00")
, time_result:Time.parse("08:00")
)
Insert部分のトレース
INSERT INTO "time_details" (
"ymd"
, "user_id"
, "time_from"
, "time_to"
, "exclusion"
, "time_result"
, "created_at"
, "updated_at"
) VALUES (? , ? , ? , ? , ? , ? , ? , ?) [
["ymd", "2019-05-01"]
, ["user_id", 1]
, ["time_from", "2019-05-01 00:00:00"]
, ["time_to", "2019-05-01 09:00:00"]
, ["exclusion", "2000-01-01 01:00:00"]
, ["time_result", "2000-01-01 08:00:00"]
, ["created_at", "2019-11-03 09:02:54.160615"]
, ["updated_at", "2019-11-03 09:02:54.160615"]
]
コンソールで1行取得した結果
<TimeDetail
id: 4
, ymd: "2019-06-01"
, user_id: 1
, time_from: "2019-06-01 00:00:00"
, time_to: "2019-06-01 09:00:00"
, exclusion: "2000-01-01 01:00:00"
, time_result: "2000-01-01 08:00:00"
, created_at: "2019-11-03 15:40:43"
, updated_at: "2019-11-03 15:40:43"
>