为什么某些时间比较会产生违反直觉的结果?

Why do certain Time comparisons have counterintuitive results?

在Ruby 2.1.2中,我可以成功地同时比较Time.parseTime.utc的结果,returns预期的[=16] =]:

Time.parse("2015-02-09T22:38:43Z") == Time.utc(2015, 2, 9, 22, 38, 43)
=> true

然而,当第二个值不是整数时,这个相同的比较违反直觉 returns false

Time.parse("2015-02-09T22:38:43.1Z") == Time.utc(2015, 2, 9, 22, 38, 43.1)
=> false

尽管第二个值仍然是整数并且仍然等价:

Time.parse("2015-02-09T22:38:43.1Z").sec
=> 43
Time.utc(2015, 2, 9, 22, 38, 43.1).sec
=> 43
Time.parse("2015-02-09T22:38:43.1Z").sec == Time.utc(2015, 2, 9, 22, 38, 43.1).sec
=> true

此外,相同方法的连续调用之间的比较结果 true

Time.parse("2015-02-09T22:38:43.1Z") == Time.parse("2015-02-09T22:38:43.1Z")
=> true
Time.utc(2015, 2, 9, 22, 38, 43.1) == Time.utc(2015, 2, 9, 22, 38, 43.1)
=> true

为什么会这样?这是一个错误,还是我遗漏了什么?

Ruby比较时间时比较小数秒和秒。出于某种原因,您的时间收到不同的小数秒:

Time.parse("2015-02-09T22:38:43.1Z").subsec
# => (1/10)
Time.utc(2015, 2, 9, 22, 38, 43.1).subsec
# => (14073748835533/140737488355328)

我相信您 运行 陷入了一个精确的问题。整数秒比较起作用的原因是整数的精度,Ruby 为您对解析后的版本执行了 .to_i

时间的底层 class 是一个表示非常精确的整数的整数,解析值和显式值的处理方式可能完全不同,足以引起问题。如果亚秒精度对你来说不重要,那么最好比较秒:

Time.parse("2015-02-09T22:38:43.1Z").to_i == Time.utc(2015, 2, 9, 22, 38, 43.1).to_i

在上述情况下,您比较的是自 Unix 纪元(1970 年 1 月 1 日)以来的秒数

另一种选择是创建一个函数以在一定精度内比较两次。许多单元测试框架都提供了该功能。本质上,如果 T1 == T2 在 0.1 秒内,就足够了。

进行 "within" 比较的最简单方法如下:

def within(time1, time2, precision)
    return (time1 - time2).abs < precision
end

注意:以上适用于时间、浮点数和分数。