我在当前项目中的DateTime比较时经历了一个可怕的时间(无双关语),特别是比较了ActiveSupport :: TimeWithZone的两个实例。问题是我的两个TimeWithZone实例都具有相同的值,但是所有比较都表明它们是不同的。
在执行调试期间暂停(使用RubyMine),我可以看到以下信息:
timestamp = {ActiveSupport::TimeWithZone} 2014-08-01 10:33:36 UTC
started_at = {ActiveSupport::TimeWithZone} 2014-08-01 10:33:36 UTC
timestamp.inspect = "Fri, 01 Aug 2014 10:33:36 UTC +00:00"
started_at.inspect = "Fri, 01 Aug 2014 10:33:36 UTC +00:00"
比较结果表明值不相等:
timestamp <=> started_at = -1
我在搜索中找到的最接近答案(两个ActiveSupport :: TimeWithZone对象之间的比较失败)在此处表示相同的问题,并且我尝试了适用的解决方案,但未成功(尝试db:test:prepare,并且我没有运行Spring) 。
而且,即使我尝试转换为显式类型,比较时它们仍然不相等。
到时间:
timestamp.to_time = {Time} 2014-08-01 03:33:36 -0700
started_at.to_time = {Time} 2014-08-01 03:33:36 -0700
timestamp.to_time <=> started_at.to_time = -1
to_datetime:
timestamp.to_datetime = {Time} 2014-08-01 03:33:36 -0700
started_at.to_datetime = {Time} 2014-08-01 03:33:36 -0700
timestamp.to_datetime <=> started_at.to_datetime = -1
到目前为止,我发现的唯一“解决方案”是使用to_i
,比较来转换两个值,但是在我想进行比较的任何地方编写代码都是非常尴尬的(而且,似乎应该没有必要):
timestamp.to_i = 1406889216
started_at.to_i = 1406889216
timestamp.to_i <=> started_at.to_i = 0
任何建议将不胜感激!
如上面的乔恩·斯基特(Jon Skeet)所述,由于时间存在毫秒级差异,因此比较失败:
timestamp.strftime('%Y-%m-%d %H:%M:%S.%L') = "2014-08-02 10:23:17.000"
started_at.strftime('%Y-%m-%d %H:%M:%S.%L') = "2014-08-02 10:23:17.679"
这一发现使我走上了一条奇怪的道路,即最终发现了最终导致问题的原因。这是仅在测试期间以及使用MySQL作为我的数据库时才出现的此问题的组合。
问题仅在测试中显示,因为在测试中,我针对包含上述字段的几个关联模型运行了一些测试。测试期间,一个模型的实例必须保存到数据库中-包含timestamp
值的模型。但是,另一个模型正在执行处理,因此正在自引用在测试代码中创建的自身实例。
这导致了第二个罪魁祸首,这就是我使用MySQL作为数据库的事实,该数据库在存储datetime
值时不存储毫秒信息(与PostgreSQL不同)。
始终,这意味着timestamp
从MySQL数据库检索其ActiveRecord之后正在读取的变量实际上已被四舍五入并削减了毫秒数据,而started_at
在测试过程中该变量仅保留在内存中,因此原始毫秒仍当下。
我自己的(低于标准的)解决方案实际上是在测试中强制两个模型(而不只是一个模型)从数据库中检索自己。
TLDR;如果可以,请尽可能使用PostgreSQL!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句