2038 is coming…I have to think date time in 64 bit! I’m trying to understand how to do this in C++, with chrono library, but I’m failing miserably so far.
I will have to communicate a date time format to a device that will receive 8 bytes to set its date and will return me the same 8 bytes when requested.
These my experiments so far:
#include <iostream>
#include <chrono>
#include <ratio>
#include <ctime>
using namespace std::chrono;
int main()
{
typedef std::chrono::duration<int64_t, std::ratio<1,1>> dur_s;
dur_s time_since_start(0x000000FFFFFFFFFF);
std::cout << "time_since_start: " << time_since_start.count() << std::endl;
time_point <system_clock, dur_s> time_point_since_start(time_since_start);
std::cout << "time_point_since_start: " <<
time_point_since_start.time_since_epoch().count() << std::endl;
std::time_t date_since_start = system_clock::to_time_t(time_point_since_start);
std::cout << "date_since_start 0: " << date_since_start << std::endl;
std::cout << "date_since_start 1: " << ctime(&date_since_start) << std::endl;
return 0;
}
This is the output:
time_since_start: 1099511627775
time_point_since_start: 1099511627775
date_since_start 0: -7293016647
date_since_start 1: Sun Nov 23 02:52:29 1738
My intent is that to create a duration stored in an int64_t, with the precision of seconds (don’t need any more resolution). From that I want to define a time_point and finally represent it as time_t. For my purpose I’m defining a duration that is bigger than 32bit, but something is not working. When I do the system_clock::to_time_t the time_point gets truncated and the result is a date back in time.
I’m missing something obvious here.
I’m working on a recent Linux Mint on a 64bit VM. Code is with standard C++ 17 (can move up to 20 if needed). Compiler is gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0.
2
Answers
Your code looks correct except that your sample time stamp (
0x0000'00FF'FFFF'FFFF
) is in the year 36,812. And that is likely blowing your implementation ofctime
out of the water. Try removing a leadingF
:This gets you down to the year 4147. That is still ridiculously far in the future, but your
ctime
is more likely to be able to handle it.Also, if you want, you can replace:
with:
It won’t change anything, but you might find it more readable.
If you upgrade to C++20, you can also:
Which would output:
(with
0x000'0000F'FFFF'FFFF
)Printing out (and telling us)
sizeof(std::time_t)
would be assuring.If you are dealing with a buggy implementation of, you can replace:system_clock::to_time_t
with:
While the above replacement is correct, this does not represent a libstdc++ bug. It is an overflow caused by the fact that
to_time_t
will do an intermediate conversion of units tosystem_clock::duration
. And on libstdc++ this isnanoseconds
. And 64 bit nanoseconds will overflow on 2262-04-11 23:47:16.854775807.system_clock::time_point
is generally implemented as the number of nanoseconds since the unix epoch stored in a 64-bit integer.0x0000'00FF'FFFF'FFFF
seconds is0x3B'9AC9'FFFF'C465'3600
nanoseconds which overflows a signed 64-bit integer, you’ll need to stick to seconds values less than around0x2'25C1'7D04
to avoid overflows.https://godbolt.org/z/xfc1oE3x5