8

I'm using Boost's datetime library in my project. I was very happy when I discovered that it has time duration types for hours, days, months, years, etc, and they change their value based on what you're adding them to (i.e. adding 1 month advances the month part of the date, it doesn't just add 30 days or somesuch). I thought this property held for the days type, but I decided to test it before I put it into production...

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

Above you'll see my CPPUNIT unit test. It fails at the indicated line with 2, which is what I would expect if days() merely added 24 hours, instead of 1 logical day (since the DST transition causes 2010-03-14 to be 23 hours long in EST).

Am I doing something wrong? Is this a bug? Did I just completely misunderstand the design goal of the library with respect to this sort of math?

4

2 に答える 2

5

I think the problem is in the asker's conception of what a day is. He wants it to be a 'date' day here, rather than 24 hours, but that is not a reasonable thing to ask for.

If working in local time, one is bound to encounter peculiar effects. For example, what do you expect to happen if, in a timezone that puts clocks forward from 1am to 2am, if your local time 'add date day' calculation should set the (non existent) 1.30am on the relevant Sunday morning?

A time calculation has got to move forward 24 hours - it must operate on the underlying UTC time.

To make the 'jump one day' calculation as described, work with Boost's date type, and only add in the time-of-day as the final action.

The business of being able to advance a month is quite different, because, unlike a day, a calendar month has no specific meaning as a duration. And it causes troubles too: if you advance one calendar month from 31st January, and then go back one calendar month, what date do you end up with?

于 2010-02-16T12:13:33.063 に答える
0

Instead of adding the date_duration object days , you should create a boost::posix_time::time_duration object and add this to your local time , like so: boost::posix_time::time_duration td ( 24 , 0 , 0 , 0 ) ; //24 hours, 0 minutes, seconds, nano boost::local_time::local_date_time later = now + td ; //assuming that now is your starting //local_date_time , 2010-3-14 //later will now be a local date_time object that takes full account of DST !

于 2010-02-11T17:07:02.010 に答える