【Ruby】 DateTimeとTimeの挙動の違い

DateTimeとTimeの違い

はじめに

会社のRails案件で日付/時間に関係した処理をいじることになったが、
日付/時間に関するクラスが多いため、どれを使っていいかわからなかった。
いろいろ調査や検証をしていると挙動が違うことが判明したため、記録として残す。

環境

Ruby 2.6.4

引っかかった点

DateTime.parseとTime.parseでは、挙動が変わってしまう。
これの結果を利用してDBへの問い合わせをやったら思ったとおりの挙動にならなかった。
下記の通りに挙動が違う。

1
2
3
4
5
6
# Time.parseはタイムゾーンを考慮したパース
Time.parse("2020-06-30 00:00:00")
=> 2020-06-30 00:00:00 +0900

# DateTimeはタイムゾーンは考慮されない
=> #<DateTime: 2020-06-30T00:00:00+00:00 ((2459031j,0s,0n),+0s,2299161j)>

ナルホド…タイムゾーンを考慮したTimeクラスを使用しよう!
さらに日付を計算するとまた違いが出てくる。

1
2
3
4
5
6
7
8
9
# Timeクラスで1を加算すると1秒が加算される
t = Time.parse("2020-06-30 00:00:00")
p t + 1
=> 2020-06-30 00:00:01 +0900

# DateTimeクラスで1を加算すると1日が加算される
d = DateTime.parse("2020-06-30 00:00:00")
p d + 1
=> #<DateTime: 2020-07-01T00:00:00+00:00 ((2459032j,0s,0n),+0s,2299161j)>

Timeを使いたいが加算をどう解決するか

1
2
3
4
5
6
7
8
9
10
11
# Railsであれば、ActiveSupport::Durationにday, week, month, year等の関数が存在
t = Time.parse("2020-06-30 00:00:00")
p t + 1.day
=> 2020-07-01 00:00:00 +0900

# Rubyであれば、普通に計算?
# うるう秒などを扱えるTimeクラスなのに自前で計算するとなると誤差が出そう
t = Time.parse("2020-06-30 00:00:00")
t = t + (60 * 60 * 24)
p t
=> 2020-07-01 00:00:00 +0900

参考