比较 ruby 中相同的 DateTime 对象——为什么这两个 DateTime.now 不相等? [英] Comparing identical DateTime objects in ruby -- why are these two DateTime.now's not equal?
问题描述
在 rails 应用程序中,我有以下形式的模型代码:
In a rails app, I have model code of the form:
def do_stuff(resource)
models = Model.where(resource: resource)
operated_at = DateTime.now
models.each { |model| some_operation(model, operated_at) }
some_other_operation models, operated_at
end
def some_operation(model, operated_at)
model.date_time_field = operated_at
model.save
end
def some_other_operation(models, operated_at)
models.each do |model|
if model.date_time_field < operated_at
# do something
end
end
end
在这种情况下,some_other_operation 的做某事"块将始终被执行.更奇怪的是,如果我在没有定义所有函数的情况下在控制台中设置它,则比较会按预期进行.示例:
The 'do something' block of some_other_operation will always be executed, in this situation. Even stranger, if I set this up in the console without all the defined functions, the comparison works as expected. Example:
> model = Model.first
> time_var = DateTime.now
> model.last_imported_at = time_var
=> Fri, 25 Oct 2013 21:14:06 +0000
> model.save
=> true
> model.last_imported_at < time_var
=> false
> model.last_imported_at == time_var
=> true
最后,如果在 some_other_operation
中,我改为按以下方式进行比较:
Finally, if, in some_other_operation
I instead compare in the following way:
if model.date_time_field.to_i < operated_at.to_i
# do something
end
做某事"块仅在预期时到达.我怀疑这是因为 to_i
方法会删除 DateTime 对象上定义的秒的分数,而 operated_at
变量实际上被重新定义为 DateTime.now
每个方法的范围.如果是这种情况,那么我想我的问题是如何强制 operated_at
不为每个范围重新定义?
the 'do something' block is reached only when expected. I suspect this is because the to_i
method will drop the fractions of a second defined on the DateTime object, and the operated_at
variable is actually being redefined as DateTime.now
for each methods' scope. If this is the case, then I guess my question is how do I force operated_at
to not be redefined for each scope?
推荐答案
可能的线索;保存和重新加载的行为会截断 DateTime 的 seconds_fraction
部分.日期字段成为ActiveSupport::TimeWithZone
的一个实例.仅保存而不重新加载不会执行此操作;真正的 DateTime 对象仍然存在.
Possible clue; the act of saving and reloading truncates the seconds_fraction
part of the DateTime. The date field becomes an instance of ActiveSupport::TimeWithZone
. Just saving without reloading doesn't do this; the real DateTime object is still there.
2.0.0-p195 :001 > dt = DateTest.create
2.0.0-p195 :002 > right_now = DateTime.now
2.0.0-p195 :004 > dt.created_at = right_now
2.0.0-p195 :005 > dt.created_at == right_now
=> true
2.0.0-p195 :006 > dt.save
2.0.0-p195 :007 > dt.created_at == right_now
=> true
2.0.0-p195 :008 > dt = DateTest.find(dt.id)
2.0.0-p195 :009 > dt.created_at == right_now
=> false
当然调用 models.each
将在那里加载模型,然后因为延迟加载行为.给另一个回答者的道具.作为实验,尝试将 models
设置为 Model.where(resource: resource).to_a
.
of course calling models.each
is going to load the models there and then because of the lazy loading behaviour. Props to the other answerer. As an experiment, try setting models
to Model.where(resource: resource).to_a
.
这篇关于比较 ruby 中相同的 DateTime 对象——为什么这两个 DateTime.now 不相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!