2015-02-11 33 views
0

在Ruby 2.1.2,我可以成功地比較Time.parseTime.utc在同一時間的結果,它返回預期true爲什麼某些時間比較具有違反直覺的結果?

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

然而,這同樣比較直覺相反返回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 

爲什麼會這樣呢?這是一個錯誤,還是我錯過了什麼?

+1

請更改您的措辭。這是誤導/混亂。如果您聲稱比較失敗,那麼它並不是失敗,它正在成功並正在返回'false'。 – sawa 2015-02-11 18:04:01

+0

這似乎是一個純粹的Ruby問題,在這種情況下,您應該刪除對Rails的所有引用,特別是Rails標記。 – 2015-02-11 18:47:26

回答

5

Ruby在比較時間時比較了小數秒和秒。由於某些原因,您的時間會收到不同的小數秒數:

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

聽起來像通常的浮點shenanigans- 43.1不能完全表示。 – 2015-02-11 18:27:31

+0

I.e.精確。當比較兩個數字時,只要它們「足夠接近」(即浮點和時間值),就必須確保它們在可接受範圍內。 – 2015-02-12 12:08:52

-1

我相信您遇到了精度問題。整數秒比較工作的原因是由於整數的精度,Ruby對解析後的版本執行了.to_i

底層的Time類是一個整數,它表示一個非常精確的整數,而解析和顯式值可能會被處理得足夠不同以致導致問題。如果亞秒級的精度並不對你很重要的話,那將是最好的比較秒:

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日)

另一個選項將創建一個函數來在一定的精度內比較兩次。許多單元測試框架提供了該功能。本質上,如果在0.1秒內T1 == T2,那就夠了。

做一個「內」相比,會是這樣的最簡單方法:

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

注:上述作品隨着時間的推移,浮點,和分數。

+0

任何人都在關注爲什麼我的答案是downvoted?它是正確的。 'Time.parse'和'Time.utc'方法在邏輯上相似,但由於精度和舍入問題有不同的分數值。但是,如果您需要0.1秒的粒度,那麼如果您爲此進行了測試,它們將是等效的。 – 2015-02-12 12:11:14