Ruby on Railsの話です。
まとめ
Date.today
はRubyのDateクラスの特異メソッド- https://docs.ruby-lang.org/ja/latest/method/Date/s/today.html
- 環境変数もしくはシステムに設定されたタイムゾーンに基づいている
Date.yesterday
はRailsでDateクラスを拡張して作られたメソッド- https://api.rubyonrails.org/classes/Date.html#method-c-yesterday
- RailsというかActiveSupport
- アプリケーションに設定されたタイムゾーンに基づいている
- 参照しているタイムゾーンの設定値が異なる場合、
設定によってはDate.today == Date.yesterday
となる時間帯が発生し得る
もうすこし詳しく
Date.today
に関してはまとめに書いた以上の説明は特になし。
Date.yesterday
に関して少しだけ。
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date). def yesterday ::Date.current.yesterday end
Date.current
に対してyesterdayを呼んでる。Date.current
はこう。
# Returns Time.zone.today when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns Date.today. def current ::Time.zone ? ::Time.zone.today : ::Date.today end
アプリケーションでタイムゾーンが設定されている場合は Time.zone.today
を返す。
気づいたきっかけ
お仕事。
%m/%d
のようなフォーマットで渡されるStringをDateに変換し、その日付が今日より前だった場合に特定の処理を実施する、というロジックがあった。
date_string = '01/29' # 外部から渡される(CSVファイルとか... if date_string.to_date < Date.today # do something end
対象のシステムはUTCで動いているので、この処理をJSTの1月30日00:00~08:59に実行すると Date.today
は「1月29日」になる。
そのため date_string.to_date < Date.today
は false
になる。
これは想定した挙動ではなかった。
気づいたのはたまたま朝9時前にテストコードを実行した日があり、CIがfailしていたからだった。
テストコードでは date_string
を Date.yesterday.strftime('%m/%d')
で生成していた。
アプリケーションのタイムゾーンの設定はJSTになっているため、このテストをJSTの1月30日00:00~08:59に実行すると、タイムゾーンが考慮されてDate.yesterday
は1月29日になる。
気づけてラッキーだった〜。
で、こういう修正をした。
- if date_string.to_date < Date.today + if date_string.to_date < Time.zone.today # do something end
アプリケーションのタイムゾーンを考慮して「今日」を判定できるようになったのでおっけ。
ひとこと
Date.today > Date.yesterday
が真とは言い切れないの、時空が歪んでいる感じがしてすごい。
おしまい。