9
7

More than 3 years have passed since last update.

【Rails】DateTimeで日付と時間を比較をする際の注意点

Last updated at Posted at 2020-05-25

経緯を書いているとポエムになってしまったので、結論を先に書いておきます。

環境
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する」というもの。

    return if last_tweet.tweeted_at > DateTime.yesterday

というわけで、調べてみました。

デバッグ

[2] pry(#<RegisteredTag>)> DateTime.yesterday
=> Thu, 21 May 2020

うんうん、合ってる。

[3] pry(#<RegisteredTag>)> DateTime.yesterday.to_time
=> 2020-05-21 00:00:00 +0900

よかろう。

[4] pry(#<RegisteredTag>)> last_tweet.tweeted_at.to_time
=> 2020-05-21 00:30:02 +0900

そうだよね、では比較してみよう。

[6] pry(#<RegisteredTag>)> last_tweet.tweeted_at > DateTime.yesterday.to_time
=> true

比較したらそうなるはずなんだ。では、元のコードに戻してみよう。

[5] pry(#<RegisteredTag>)> last_tweet.tweeted_at > DateTime.yesterday
=> false

ファファファ????

ということで、改めて確認してみます。

日付の比較

[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でもやってみた

[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と同じ挙動をします。

クラスを見てみる

[31] pry(main)> Date.yesterday.class
=> Date
[32] pry(main)> DateTime.yesterday.class
=> Date

あ、DateTimeで作ってもインスタンスのクラスはDateになるんですね。
つまり、Date.yesterdayDateTime.yesterdayは同じもののようです。

9
7
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
9
7