0
0

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 1 year has passed since last update.

あまねAdvent Calendar 2022

Day 20

Railsで日時比較をする際に型が違って焦った話

Posted at

この記事で伝えたいこと

Railsで日時比較をするときには日付の型を確認しようと言う話をします。

日時に応じて挙動が変わる処理の実装

WEBアプリケーションを開発していると、特定期間のみキャンペーンのバナーを表示させたいというような、期間などの時刻で動作する機能を開発する必要があります。
かつての僕は「その時間になったら手動でデプロイするのかな」と思っていたこともあったのですが、コードの中に時間による分岐を入れれば自動で機能がアクティブになることを教えてもらいました。

そんな僕が書いたコードが下記のような分岐です。

  Time.zone.now.between?(Date.new(2022, 12, 01), Date.new(2022, 12, 31))

しかし、2022年12月1日0:00(JST)になってもこれではうまく動作しませんでした。

[2] pry(main)> Time.zone.now.between?(Date.new(2022, 12, 01), Date.new(2022, 12, 31))
=> false

RubyとRailsぞれぞれの日時の型

どうしてこうなるのか少し調べてみると、RailsやRubyにはそれぞれたくさんの日時の型があることがわかりました。

Railsアプリケーションでは「システムまたは環境変数に設定されたタイムゾーン」と「application.rbに設定されたタイムゾーン」の2種類があります。
どちらも同じ設定になっている場合は問題が起きることは少ないですが、設定が異なっていると予期せぬ結果になる場合があります。

冒頭の処理で使ったTime.zone.nowDateの型をそれぞれ見てみると異なる型を使っていました。

[1] pry(main)> Time.zone.class
=> ActiveSupport::TimeZone
[2] pry(main)> Date.new(2022,12,01).class
=> Date

型を揃えた分岐にすることで解消

比較する型をどちらかにそろえれば解消できました。

Time.zone.localに合わせる

Time.zone.nowに合わせてActiveSupport::TimeWithZoneを使うようにすれば解消できました。

[1] pry(main)>  Time.zone.now.between?(Time.zone.local(2022, 12, 01), Time.zone.local(2022, 12, 31)
=> true
[2] pry(main)> Time.zone.local(2022, 12, 01).class
=> ActiveSupport::TimeWithZone

Dateに合わせる

またはDateに合わせる方法もあります。

[1] pry(main)> Time.zone.today.between?(Date.new(2022, 12, 01), Date.new(2022, 12, 31))
=> true
[2] pry(main)> Time.zone.today.class
=> Date

こうしてどちらかに揃えたことで意図するシステムの動作を担保することができました。

感想

今回はタイムゾーンがDate型に反映されなかったためエラーになってしまったようですが、どこでその分岐が起きたのかはまだ調査中になります。
仮説としてRailsのTimeWithZoneでのbetweenメソッド内部でutcによる比較になっている可能性がありそうでした。

ちょっとこのあたりだいぶ複雑でまだまだ理解ができていないと感じています。
もしもこのあたりご知見があるかたいらっしゃればコメントいただけると幸いですmm

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?