ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

比較演算子の左右とコメントの罠

こんにちは、 id:rightgo09 です。

比較演算子の左右とコメントの罠に嵌ったのでエントリの一つとして書いてみます。



弊社のRuby on Railsのプログラムで以下のようなコードがありました(例です)。

    # @param [Date] date
    # @return [Boolean]
    def future?(date)
      date > Date.today
    end

これを以下のように変更しました。

    # @param [Date] date
    # @return [Boolean]
    def future?(date)
-     date > Date.today
+     Date.today < date
    end

すると、ステージング環境で例外が発生する事象に遭遇しました。

ArgumentError (comparison of Date with ActiveSupport::TimeWithZone failed)

デバッグしてみると、このメソッドを呼び出しているひとつが、引数に Dateオブジェクトではなく ActiveSupport::TimeWithZoneオブジェクトを渡していることがわかりました。

ActiveSupport::TimeWithZoneとDateの比較

ActiveSupport::TimeWithZoneとDateを比較する際は、左辺と右辺に注意する必要があります。

now = Time.zone.now
now.class #=> ActiveSupport::TimeWithZone

today = Date.today
today.class #=> Date

# OK
# 左辺:ActiveSupport::TimeWithZone
# 右辺:Date

now < today #=> false

# NG
# 左辺:Date
# 右辺:ActiveSupport::TimeWithZone

today < now #=> ArgumentError: comparison of Date with ActiveSupport::TimeWithZone failed

Dateオブジェクトが左辺に来る場合、右辺として比較可能なのは、以下の2つです。

  • Dateオブジェクト
  • ユリウス通日を表す数値(時刻付きならRational)


ActiveSupport::TimeWithZoneオブジェクトを左辺におくと、utcメソッドが呼ばれてTimeオブジェクトとなるため、Dateオブジェクトとも比較が可能なようです。

まとめ

今回のことから以下のことを学びました。

  • Dateオブジェクトが左辺にくるときは気をつける
  • 動的言語で、時代を感じるプログラムでは、型を示唆するコメントは信用しない

以上です。