Opened 13 years ago
Last modified 6 years ago
#3109 new Bugs
time_duration::total_seconds() - overflow
Reported by: | Owned by: | az_sw_dude | |
---|---|---|---|
Milestone: | To Be Determined | Component: | date_time |
Version: | Boost 1.41.0 | Severity: | Problem |
Keywords: | year 2038 problem | Cc: |
Description
time_duration::total_seconds() overflow value
minimal sample (based on boost example) #include <string> #include <boost/date_time/local_time/local_time.hpp>
int main() {
using namespace boost::gregorian; using namespace boost::local_time; using namespace boost::posix_time;
date in_date(2039, 10, 04); time_duration td(12,14,32); std::string z("PST-8PDT,M4.1.0,M10.1.0"); time_zone_ptr zone(new posix_time_zone(z)); local_date_time my_time(in_date, td, zone, local_date_time::NOT_DATE_TIME_ON_ERROR); std::cout << my_time << std::endl; ptime time_t_epoch( date(1970,1,1) ); std::cout << time_t_epoch << std::endl; time_duration diff = my_time.utc_time() - time_t_epoch; std::cout << "Seconds diff: " << diff.total_seconds() << std::endl; return 0;
}
Change History (4)
comment:1 by , 13 years ago
Version: | Boost 1.39.0 → Boost 1.41.0 |
---|
comment:2 by , 11 years ago
This problem still applies to Boost version 1.47 (I didn't check even newer versions)
The following code:
using namespace boost::posix_time; using namespace boost::gregorian; using namespace boost::local_time; local_date_time now(local_sec_clock::local_time(time_zone_ptr())); local_date_time baseADTime( date(1601, 1, 1), hours(0), time_zone_ptr(), local_date_time::NOT_DATE_TIME_ON_ERROR); time_duration timeInterval(now.utc_time() - baseADTime.utc_time()); cout << "BaseTime: " << baseADTime << endl; cout << "Time: " << now << endl; cout << "MicroSeconds: " << timeInterval.total_microseconds() << endl; cout << "MilliSeconds: " << timeInterval.total_milliseconds() << endl; cout << "Seconds: " << timeInterval.total_seconds() << endl;
produces the following output:
BaseTime: 1601-Jan-01 00:00:00 UTC Time: 2012-Feb-08 12:36:54 UTC MicroSeconds: 12973178214000000 MilliSeconds: 12973178214000 Seconds: 88276326
In case you're wondering why it would be interesting to calculate the time interval between 01-01-1601 and now: the time representation in Microsoft Active Directory uses a time representation based on the time between 1601 and now.
It is at least counterintuitive that types with a higher resolution/precision are able to store larger intervals. According to the documentation documentation, all "total_x" methods should return the same type, that doesn't seem to be the case.
It is probably possible to use type traits to set the internal representation, but this is somewhat complex to do. (Thanks to Andrei Korostelev for pointing out this possibility). In any case as far as I know it cannot be done in an obvious/self-explanatory way.
Another proposed solution would be to add a template parameter to total_seconds and similar methods so you can explicitly specify the representation type. For example:
int_fast64_t numSeconds = timeInterval.total_seconds<int_fast64_t>()
This way a user explicitly states what he wants and will not run into surprises.
comment:3 by , 6 years ago
This problem still exists in Boost version 1.61. It may also cause confusion in calculating total milliseconds from epoch(1/1/1970).
comment:3 by , 6 years ago
This problem still exists in Boost version 1.61. It may also cause confusion in calculating total milliseconds from epoch(1/1/1970).
platform: MSVC 8, Windows XP Boost 1.41
time_duration::total_seconds should be returning 64bit int instead of 32bit int. All underlying code is correct, only the return type of time_duration::total_seconds() is only a 32bit int, which is not wide enough for time durations lasting several decades or a century. When changed to 64bit int, total_seconds() works as expected. The problem possibly applies to other total_* methods as well.
Proposed fix: time_duration.hpp