Following this thread nanoseconds-run-into-an-overflow, it was my intention to transit from nanoseconds and seconds freely but without losing any information (given the fact that nanoseconds is 64 bits according to std::chrono::nanoseconds). Basically, the following code will lose much information:
std::chrono::nanoseconds t1(1705218518267805576);
std::chrono::seconds t2(std::chrono::duration_cast<std::chrono::seconds>(t1));
std::chrono::nanoseconds t3(std::chrono::duration_cast<std::chrono::nanoseconds>(t2));
EXPECT_EQ(t1,t3);
The last line will return false. So, I thought about adding type such as long_data_seconds which can hold the lost information, but I don't know exactly how much has been lost and how can I store it for future use of transition. I would love to hear ideas.
The issue you are facing is not (really) due to the fact that the
std::chrono::secondstype is not wide enough (i.e. does not have sufficient bits) to hold the full data of thenanosecondsvalue1; rather, it is because thatsecondstype is an integer. Thus, when you convert nanoseconds to seconds, all information on the fractional part of that value (i.e. data less than 109) is lost, due to truncation.In your case, what you will need is to define a floating-point duration type for your intermediate 'seconds' data. For the example you have given (1,705,218,518,267,805,576 ns), the IEEE-754
doubletype will not be sufficiently precise, so you will need a platform that supports an extended precisionlong doubletype, and use that.Here's a short example code:
And here is a demonstration on Compiler Explorer.
If you have a platform on which
long doubleis equivalent todouble(like MSVC/Windows), then you will need to use a third-party extended-precision library.1 In fact, the Standard specifies that
std::chrono::secondshave at least 35 bits – and many (most) current platforms don't have an in-built integer type larger than 32 bits but smaller than 64 bits, so it is likely to be anint64_ton those systems.