Converting time_duration to DATE

后端 未结 2 1172
孤街浪徒
孤街浪徒 2021-01-25 12:47

I want to convert a time_duration to a DATE format, which is the number of days since 1899, 12, 30.

DATE date_from_duration(time_duration td)
{
   double days =          


        
相关标签:
2条回答
  • 2021-01-25 13:41

    That kind of depends on your circumstances.

    The general problem is that 1 / (24. * 60. * 60.) is not exactly representable as a binary float (because 86400 is not a power of two). The DATE you get is very nearly exact, but there will be a rounding error. Sometimes this means that it is very little more, sometimes very little less, but there's really not a lot you can do to make it more precise; it is as perfectly alright as you can get. That you see a discrepancy of a second is arguably a problem with your check, in that you stop looking at seconds -- if you check the milliseconds, you're likely to get 999, making the rounding error look a lot less extreme. This will continue for microseconds and possibly nanoseconds, depending on the resolution of time_duration.

    So quite possibly there's nothing to do because the data is alright. If, however, you don't care about milliseconds and beyond and only want the seconds value to be stable in conversions back and forth, the simplest way to achieve that is to add an epsilon value:

    DATE date_from_duration(time_duration td)
    {
       double days =
           td.hours  () /  24.
         + td.minutes() / (24. * 60.)
         + td.seconds() / (24. * 60. * 60.)
         + 1e-8; // add roughly a millisecond
       return days;
    }
    

    This increases the overall rounding error but ensures that the error is in a "safe" direction, i.e., that converting it back to time_duration will give the same seconds() value and the visible changes will be at the milliseconds() level.

    0 讨论(0)
  • 2021-01-25 13:41

    I might be missing some of the complexity, but it seems really simple to me:

    Live On Coliru

    #include <boost/date_time/posix_time/posix_time.hpp>
    #include <iostream>
    using DATE = double;
    
    boost::posix_time::ptime pTime_from_DATE(double date)
    {
        static const boost::posix_time::ptime::date_type base_date(1899, boost::gregorian::Dec, 30);
        return boost::posix_time::ptime(
                base_date, 
                boost::posix_time::milliseconds(date * 1000 * 60 * 60 * 24));
    }
    
    int main() {
        boost::posix_time::time_duration duration(1007645, 15, 0);
    
        DATE date = duration.total_milliseconds() / 1000.0 / 60 / 60 / 24;
    
        std::cout << date << ": " << pTime_from_DATE(date);
    }
    

    Prints

    41985.2: 2014-Dec-12 05:15:00
    

    See it Live On Coliru

    0 讨论(0)
提交回复
热议问题