日期与 ActiveSupport::TimeWithZone 的比较失败

日期与 ActiveSupport::TimeWithZone 的比较失败

问题描述:

我的 Waiver 模型中有一个 age 方法,如下所示:

I have an age method on my Waiver model that looks like:

  def age(date = nil)

    if date.nil?
      date = Date.today
    end
    age = 0
    unless date_of_birth.nil?
      age = date.year - date_of_birth.year
      age -= 1 if date < date_of_birth + age.years #for days before birthday
    end
    return age
  end

然后我有一个看起来像这样的规范:

I then have a spec that looks like:

it "calculates the proper age" do
 waiver = FactoryGirl.create(:waiver, date_of_birth: 12.years.ago)
 waiver.age.should == 12
end

当我运行这个规范时,我得到 Date 与 ActiveSupport::TimeWithZone 的比较失败.我做错了什么?

When I run this spec I get comparison of Date with ActiveSupport::TimeWithZone failed. What am I doing wrong?

Failures:

  1) Waiver calculates the proper age
     Failure/Error: waiver.age.should == 12
     ArgumentError:
       comparison of Date with ActiveSupport::TimeWithZone failed
     # ./app/models/waiver.rb:132:in `<'
     # ./app/models/waiver.rb:132:in `age'
     # ./spec/models/waiver_spec.rb:23:in `block (2 levels) in <top (required)>'

您正在将表达式 Date 的实例与 ActiveSupport::TimeWithZone 的实例进行比较代码>日期;ActiveSupport::TimeWithZone 是,根据文档,一个类时间类可以代表任何时区的时间.您根本无法在不执行某种转换的情况下比较 DateTime 对象.尝试 Date.today 在控制台上;您会看到类似的错误.

You are comparing an instance of Date with an instance of ActiveSupport::TimeWithZone in the expression date < date_of_birth + age.years; ActiveSupport::TimeWithZone is, according to the docs, a Time-like class that can represent a time in any time zone. You simply can't compare Date and Time objects without performing some kind of conversion. Try Date.today < Time.now on a console; you'll see a similar error.

12.years.ago 这样的表达式和典型的 ActiveRecord 时间戳是 ActiveSupport::TimeWithZone 的实例.您最好确保在此方法中只处理 Time 对象或 Date 对象,但不要同时处理两者.为了使您的比较保持最新,表达式可以写为:

Expressions like 12.years.ago and typical ActiveRecord timestamps are instances of ActiveSupport::TimeWithZone. You are best off ensuring that you deal only with Time objects or Date objects, but not both in this method. To make your comparison date-to-date, the expression could instead be written as:

age -= 1 if date < (date_of_birth + age.years).to_date