経緯を書いているとポエムになってしまったので、結論を先に書いておきます。
環境
Rails 5.2.4.2
Ruby 2.6.6
結論
- DateTimeで日付を指定すると、インスタンスはDateクラスになる。
- Dateクラスはタイムゾーンの情報を持っていないため、+0000になる。
- DateクラスはDateTime/Timeクラスになった時点でタイムゾーンを持つ。
- DateクラスとDateTime/Timeクラス(Railsだと
ActiveSupport::TimeWithZone
クラス)を比較するときはDateクラスをDateTimeクラスへ変換する必要がある。
ポエム
ことの起こりは深夜0時も回った頃。RSpecを走らせたところ、実装と関係のないところが落ちる。
調べてみたところ、どうやろ本当はreturnしないといけないところがreturnしていないようです。
してほしい挙動としては、「最後にツイートした日時が昨日より最近のときにreturnする」というもの。
1
|
return if last_tweet.tweeted_at > DateTime.yesterday
|
というわけで、調べてみました。
デバッグ
1
2
|
[2] pry(#<RegisteredTag>)> DateTime.yesterday
=> Thu, 21 May 2020
|
うんうん、合ってる。
1
2
|
[3] pry(#<RegisteredTag>)> DateTime.yesterday.to_time
=> 2020-05-21 00:00:00 +0900
|
よかろう。
1
2
|
[4] pry(#<RegisteredTag>)> last_tweet.tweeted_at.to_time
=> 2020-05-21 00:30:02 +0900
|
そうだよね、では比較してみよう。
1
2
|
[6] pry(#<RegisteredTag>)> last_tweet.tweeted_at > DateTime.yesterday.to_time
=> true
|
比較したらそうなるはずなんだ。では、元のコードに戻してみよう。
1
2
|
[5] pry(#<RegisteredTag>)> last_tweet.tweeted_at > DateTime.yesterday
=> false
|
ファファファ????
ということで、改めて確認してみます。
日付の比較
1
2
3
4
5
6
7
8
9
10
|
[33] pry(main)> DateTime.yesterday
=> Thu, 21 May 2020
[34] pry(main)> after_9
=> Thu, 21 May 2020 09:21:38 +0900
[35] pry(main)> DateTime.yesterday < after_9
=> true
[37] pry(main)> before_9
=> Thu, 21 May 2020 08:31:48 +0900
[38] pry(main)> DateTime.yesterday < before_9
=> false
|
8時台 < DateTime.yesterday < 9時台
ということで、DateTime.yesterday
にはタイムゾーンが適用されていないようです。
Date.yesterdayでもやってみた
1
2
3
4
5
6
|
[22] pry(main)> Date.yesterday
=> Thu, 21 May 2020
[23] pry(main)> Date.yesterday < before_9
=> false
[24] pry(main)> Date.yesterday < after_9
=> true
|
DateTimeと同じ挙動をします。
クラスを見てみる
1
2
3
4
|
[31] pry(main)> Date.yesterday.class
=> Date
[32] pry(main)> DateTime.yesterday.class
=> Date
|
あ、DateTimeで作ってもインスタンスのクラスはDateになるんですね。
つまり、Date.yesterday
とDateTime.yesterday
は同じもののようです。