【发布时间】:2016-08-28 19:28:33
【问题描述】:
以下查询给出不同的结果,两者的结果都应该是两个。我在我的数据库(postgres)中使用时间戳列,并且正在搜索其 end_at 列小于或等于给定 UNIX 时间戳的对象。
puts object.time_records.where('time_records.end_at <= ?', object.time_records.second.end_at).count #=> 2 (Correct)
puts object.time_records.where('time_records.end_at <= ?', DateTime.strptime(object.time_records.second.end_at.to_i.to_s, '%s')).count # => 1 (Incorrect)
puts object.time_records.where('time_records.end_at <= ?', Time.at(object.time_records.second.end_at.to_i)).count # => 1 (Incorrect)
如果我播种一些数据,查询中使用的时间戳可能是,例如:
1473024092
如果我打印对象的时间戳:
puts object.time_records.pluck(:end_at).map(&:to_i)
我得到以下结果:
1472419292
1473024092
1473628892
1474233692
从这些可以看出,正确的结果应该是两个。如果有人遇到类似的事情,我会很感激一个正确方向的指针。
对于它的价值,这发生在我为 gem 编写的规范中。我尝试了 in_time_zone 和 .utc 的不同组合来解析和转换为时间戳,它们都提供了相同的结果。当to_s 对两者相等时,即使转换为时间戳并直接返回时间,并且测试相等性也会导致错误。
我在 irb 中运行了一个示例:
2.3.0 :001 > now = Time.now
=> 2016-08-28 21:58:43 +0100
2.3.0 :002 > timestamp = now.to_i
=> 1472417923
2.3.0 :003 > parsed_timestamp = Time.at(timestamp)
=> 2016-08-28 21:58:43 +0100
2.3.0 :004 > now.eql?(parsed_timestamp)
=> false
2.3.0 :005 > now == parsed_timestamp
=> false
2.3.0 :006 > now === parsed_timestamp
=> false
2.3.0 :007 > now.class
=> Time
2.3.0 :008 > parsed_timestamp.class
=> Time
【问题讨论】:
-
你的数据库处理小数时间吗?
-
您可以使用 my.custom.activerecord.query.to_sql 找出实际执行的 SQL 查询是什么
-
@FrederickCheung 这就是问题所在。
-
@Bustkiller 感谢您的指点。
标签: ruby-on-rails ruby ruby-on-rails-4 rubygems