2010-02-11 56 views
8

我在我的項目中使用Boost's datetime library。當我發現它具有數小時,數天,數月,數年等的持續時間類型時,我感到非常高興,並且它們根據您將它們添加到的內容來更改它們的值(即,在日期的月份部分添加1個月預付款,它不只是增加30天或某些)。我認爲屬性爲日式舉行,但我決定測試它,我將它投入生產之前...boost local_date_time數學錯誤?

local_date_time t1(date(2010, 3, 14), hours(1), easternTime, false); // 1am on DST transition date 

{ 
    CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year()); 
    CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month()); 
    CPPUNIT_ASSERT_EQUAL(greg_day(14), t1.local_time().date().day()); 
    CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours()); 
    CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes()); 
    CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds()); 
} 

t1 += days(1); // the time in EST should now be 1am on the 15th 
{ 
    CPPUNIT_ASSERT_EQUAL(greg_year(2010), t1.local_time().date().year()); 
    CPPUNIT_ASSERT_EQUAL(greg_month(3), t1.local_time().date().month()); 
    CPPUNIT_ASSERT_EQUAL(greg_day(15), t1.local_time().date().day()); 
    CPPUNIT_ASSERT_EQUAL(1L, t1.local_time().time_of_day().hours()); // fails, returns 2 
    CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().minutes()); 
    CPPUNIT_ASSERT_EQUAL(0L, t1.local_time().time_of_day().seconds()); 
} 

在上面,你會看到我的CppUnit的單元測試。如果days()僅僅增加了24個小時而不是1個邏輯日(因爲DST轉換導致2010-03-14在EST中持續23個小時),那麼它會在指定的行中失敗,這是我所期望的。

我做錯了什麼?這是一個錯誤?我是否完全誤解了圖書館關於這種數學的設計目標?

+0

這是一個很好的例子,說明爲什麼我們應該全部編寫測試用例代碼 - 比較預期的實際值 – slf 2010-02-22 17:18:00

回答

5

我認爲這個問題是在一天的什麼是提問者的構想。他希望在這裏成爲'約會'日,而不是24小時,但這不是一個合理的要求。

如果在當地時間工作,一個必將遭遇奇特的效果。例如,如果在一個時鐘從凌晨1點到凌晨2點將時鐘向前移動,如果您當地時間的「添加日期」計算應該在相關的星期天早上設置(不存在的)1.30am,那麼您預期會發生什麼?

時間計算有得到 24小時向前移動 - 它必須在基礎UTC時間上運行。

要按照描述進行「跳躍一天」計算,請使用Boost的日期類型,並且只添加一天中的時間作爲最終操作。

能夠推進一個月的業務是完全不同的,因爲與一天不同,日曆月沒有具體含義作爲持續時間。而且它也會帶來麻煩:如果你從1月31日開始推出一個日曆月,然後再回到一個日曆月,那麼你最終會得到什麼日期?

+0

已上傳此。 OP的核心問題是他在當地時代期待穩定的數學,當時沒有這樣的事情存在。由於有各種財務領域明確使用30/360或變體來使某些事情變得更簡單,所以關於30天月的OP評論很有趣。 – sdg 2010-02-16 15:59:20

+0

Boost的Month和Year類型的行爲與我描述的一樣,並解決了willw和sdg正在討論的問題:http://www.boost.org/doc/libs/1_40_0/doc/html/date_time/gregorian.html#additional_duration_types。我只是期待類似的日子。時間計算不需要在UTC時間進行操作...我雖然這是爲什麼它提供了ptime(用於UTC)和local_date_time(用於本地時間)的計算。這並不意味着你錯了,但是我不打算接受你的答案,直到你用Boost文檔闡明你自己的誤解。 – rmeador 2010-02-16 16:32:27

+0

Boost的Month和Year類型引用文檔中的天數的邏輯表示 - 它們與gregorian :: date類型相關聯。在你的例子中,你的類型是local_date_time。從語義上講,您聲明對連續的時間流感興趣,而不是每日一次的粒度。因此,當您將一天添加到日期時間變量時,它會從日期持續時間轉換爲持續時間 - 從1天到24小時。其他一切都源於此。 對不起,但我認爲你的錯誤觀念和WAD類。 – willw 2010-02-22 17:34:57

0

,而不是添加date_duration對象的天,你應該創建一個boost ::了posix_time :: TIME_DURATION對象,並添加到您的本地時間,像這樣: 的boost ::了posix_time :: TIME_DURATION TD(24,0 ,0,0); // 24小時,0分鐘,秒,納米 boost :: local_time :: local_date_time later = now + td; //假設現在是你的起點// LOCAL_DATE_TIME,2010-3-14 //以後現在是本地DATE_TIME對象,充分考慮DST的!

+0

這並不解決OP的問題。用't1 + = time_duration(24,0,0,0)替換't1 + = days(1);'給出相同的結果。 – 2010-02-11 18:13:23