2010-02-11 11 views
8

Używam w moim projekcie Boost's datetime library. Byłem bardzo szczęśliwy, gdy odkryłem, że ma on typy czasu trwania na godziny, dni, miesiące, lata itp., I zmieniają one swoją wartość w oparciu o to, do czego je dodajesz (np. Dodawanie 1 miesiąca przesuwa miesiąc o część daty , nie dodaje tylko 30 dni lub somesuch). I myślał tej nieruchomości przeznaczone do typu dni, ale postanowiłem go przetestować przed I umieścić go w produkcji ...boost local_date_time math wrong?

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()); 
} 

Powyżej zobaczysz moje testów jednostkowych CppUnit. Nie powiedzie się we wskazanej linii przez 2, czego oczekiwałbym, gdyby days() tylko dodał 24 godziny, zamiast 1 logicznego dnia (ponieważ przejście DST powoduje, że 2010-03-14 trwa 23 godziny w EST).

Czy robię coś nie tak? Czy to błąd? Czy całkowicie błędnie zrozumiałem cel projektu biblioteki w odniesieniu do tego rodzaju matematyki?

+0

jest to doskonały przykład, dlaczego wszyscy powinniśmy napisać kod wiązki przewodów testowych - porównanie oczekiwanych do rzeczywistych – slf

Odpowiedz

5

Myślę, że problem tkwi w koncepcji pytającego, czym jest dzień. Chce, żeby był tu dzień "randkowy", a nie 24-godzinny, ale nie jest to rozsądne.

Jeśli pracujesz w czasie lokalnym, na pewno spotkasz się z dziwnymi efektami. Na przykład, jak można się spodziewać, jeśli w strefie czasowej, w której zegary przesuwane są od 1 do 2 rano, czy obliczanie czasu lokalnego w dniu dodatkowym spowoduje ustawienie (nieistniejącego) dnia 1.30 rano w niedzielny poranek?

Wyliczenie czasu ma dostanie, aby przejść do przodu 24 godziny - musi działać w czasie bazowym UTC.

Aby wykonać obliczenia "skoku jednego dnia" zgodnie z opisem, należy pracować z typem daty "Zwiększ" i dodawać tylko porę dnia jako ostatnią akcję.

Przedsięwzięcie polegające na zaliczaniu miesiąca jest zupełnie inne, ponieważ w przeciwieństwie do dnia miesiąc kalendarzowy nie ma określonego znaczenia jako czasu trwania. A także powoduje kłopoty: jeśli awansujesz o jeden miesiąc kalendarzowy od 31 stycznia, a następnie powrócisz o jeden miesiąc kalendarzowy, o jakiej randce skończysz?

+0

Wznowienie tego. Podstawowym problemem OP jest to, że spodziewa się stabilnej matematyki w czasach lokalnych, kiedy takie rzeczy nie istnieją. Komentarze OP na temat 30-dniowych miesięcy są zabawne, biorąc pod uwagę, że istnieją różne domeny finansowe, które jawnie używają 30/360 lub odmiany, aby uprościć niektóre rzeczy. – sdg

+0

Typy miesiąca i roku w Boost zachowują się tak, jak to opisałem i rozwiązuję problem, o którym mówią willw i sdg: http://www.boost.org/doc/libs/1_40_0/doc/html/date_time/gregorian.html#additional_duration_types. Po prostu spodziewałem się tego samego od typu dnia. Obliczenia czasowe nie muszą działać w czasie UTC ... Dlatego właśnie dostarczałem obliczenia ptime (dla UTC) i local_date_time (dla czasu lokalnego). To nie znaczy, że się mylisz, ale nie zamierzam zaakceptować twojej odpowiedzi, dopóki nie rozwiążesz swoich własnych nieporozumień z dokumentami Boost. – rmeador

+0

Typy Miesiąca i Roku w Boostu są, by zacytować dokumentację, logiczną reprezentacją rozpiętości dni - są powiązane z gregorian :: date type. W twoim przykładzie twój typ to local_date_time. Semantycznie deklarujesz zainteresowanie nieprzerwanym przepływem czasu, a nie szczegółową datą jednego dnia. Więc jeśli dodasz jeden dzień do zmiennej czasu daty, zostanie ona przekształcona z daty na czas trwania - od 1 dnia do 24 godzin. Wszystko inne wynika z tego. Przykro mi, ale myślę, że błędne przekonanie należy do ciebie, a klasy WAD. – willw

0

Zamiast dodawania date_duration dni obiektów, należy utworzyć obiekt posix_time boost :: :: TIME_DURATION i dodać to do czasu lokalnego, tak jak poniżej: boost :: td posix_time :: TIME_DURATION (24, 0 , 0, 0); // 24 godziny, 0 minut, sekundy, nano boost :: local_time :: local_date_time later = now + td; // zakładając, że teraz jest twój początek // local_date_time, 2010-3-14 // później będzie teraz lokalny obiekt date_time, który w pełni uwzględnia DST!

+0

Nie rozwiąże to problemu PO. Zastępując 't1 + = dni (1);' z 't1 + = time_duration (24, 0, 0, 0);' daje ten sam wynik. –

Powiązane problemy