2010-01-18 152 views
1

我正在讀Bob的叔叔「The Craftsman」系列,並且已經到了#29(PDF)。在這裏面,有這個片段在測試代碼,用於斷言日期非常接近:使用GregorianCalendar.setGregorianChange計算時差

private boolean DatesAreVeryClose(Date date1, Date date2) { 
    GregorianCalendar c1 = new GregorianCalendar(); 
    GregorianCalendar c2 = new GregorianCalendar(); 
    c1.setGregorianChange(date1); 
    c2.setGregorianChange(date2); 
    long differenceInMS = c1.getTimeInMillis() - c2.getTimeInMillis(); 
    return Math.abs(differenceInMS) <= 1; 
} 

我閱讀文檔,卻無法弄清楚,爲什麼簡單地使用Date.getTime()不夠好,而不是引入日曆等我錯過了一些角落案件?

回答

1

宇宙飛船上的時間與我們世界的時間不同。此外,宇宙飛船上的Java API與我們的世界中的API略有不同。該方法setGrogorianChange與宇宙飛船世界中的朱利安日期無關。相反,這是一種設置GregorianCalendar實例時間的方法。在宇宙飛船世界中,Date.getTime()不返回毫秒。它返回一個散列值,以某種方式表示時間,但不能被減去或添加。

所以那裏。

+0

這個答案與問題中的代碼和鏈接的pdf中的代碼在宇宙飛船上的含義差不多。 – 2010-01-18 21:36:32

+0

那麼,鑑於他寫了他們兩個,我認爲這是他的權利。 – abyx 2010-01-18 21:45:27

0

沒有理由不使用Date.getTime()。最有可能的是,作者正在重新熟悉使用GregorianCalendar對象進行日期/時間操作。

在附註中,使用setGregorianChange來獲取此信息似乎...濫用了API。該方法用於設置「從儒略日期到公曆日期切換的時間點,默認爲1582年10月15日(格里高利)。」(javadoc)它可能用於進行給定的計算,但它使事情變得非常困難從代碼維護的角度來理解。

1

我會咬:那個代碼是完全垃圾。如果使用setGregorianChange()有任何目的(我懷疑),它就是那種在現實世界代碼附近沒有任何業務的聰明黑客。但我強烈懷疑,誰寫了這個可愛的故事誰不知道日期/日曆API非常好,真的打算使用Calendar.setTime()

針對直接在assertEquals()比較Date實例的情況下,似乎是,各實例的內部時間戳可以通過毫秒不同,即使在右上的另一後 - 從而在Math.abs(differenceInMS) <= 1形式引進了‘模糊比較’。但是這兩者都不需要通過GregorianCalendar繞行,它也不足夠模糊 - 一個完整的GC或甚至只是時鐘的粒度可能很容易導致兩個日期相距10或更多ms的日期。

真正的問題是在Java中缺少「日期日期」數據類型 - 使日間粒度相當詳細(必須使用Calendar將所有時間字段設置爲0)進行比較。 Joda Time的DateMidnight班是這裏真正需要的。