Opened 12 years ago

Last modified 7 years ago

#4771 new Bugs

DST calculation inconsistencies

Reported by: mika.heiskanen@… Owned by: az_sw_dude
Milestone: To Be Determined Component: date_time
Version: Boost 1.44.0 Severity: Problem
Keywords: Cc:

Description

One local_date_time constructor takes as argument a date and a time duration. However, its behaviour is not consistent. First, define a date prior to a DST change in the spring (one day prior is sufficient). Then assume you have to skip N minutes into the future, where N is large enough to get past the DST change.

a) If you add floor(N/(24*60)) days to the date, and then construct a new local_date_time with the new date and N%(24*60) minutes, you get one result.

b) If you construct a local_date_time with the original date and the N minutes (>24*60) you get a second result.

The results are different by one hour for regular EU DST rules. It seems like the constructor will not inspect DST rules unless the input date coincides with the DST change date.

The effect:

Instead of looping with one origin time + advancing time_duration, we have to advance the date whenever the number of minutes exceeds 24*60 and take modulo 24*60 for the duration in minutes. This produces the correct behaviour for our application.

Change History (1)

comment:1 by meisenbraun@…, 7 years ago

Code to expose the issue:

#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <cmath>

int main(int argc, char** argv )
{
    using namespace boost;
    using namespace boost::gregorian;
    using namespace boost::local_time;
    using namespace boost::posix_time;

    ptime sourceTime;
    tz_database db;
    db.load_from_file("date_time_zonespec.csv");
    time_zone_ptr localTZ = db.time_zone_from_region("America/Chicago");

    const unsigned int n = 26 * 60 +120;

    date preDST(2016,Mar,12);
    time_duration offset0 = hours(0);
    local_date_time dt0(preDST, offset0, localTZ, local_date_time::NOT_DATE_TIME_ON_ERROR);
    
    date date2 = preDST + days(std::floor(n/(24*60)));
    time_duration offset1 = minutes(n%(24*60));
    local_date_time dt1(date2, offset1, localTZ, local_date_time::NOT_DATE_TIME_ON_ERROR);    

    time_duration offset2 = minutes(n);
    local_date_time dt2(preDST, offset2, localTZ, local_date_time::NOT_DATE_TIME_ON_ERROR);
    
    std::cout << "DT 0: " << dt0 << std::endl;
    std::cout << "DT 1: " << dt1 << std::endl; // 04:00:00 CDT reported, 05:00:00 CDT expected
    std::cout << "DT 2: " << dt2 << std::endl; // 05:00:00 CDT reported
}
Note: See TracTickets for help on using tickets.