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.
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 of ctime
out of the water. Try removing a leading F
:
dur_s time_since_start(0x000'0000F'FFFF'FFFF);
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:
typedef std::chrono::duration<int64_t, std::ratio<1,1>> dur_s;
with:
using dur_s = std::chrono::seconds;
It won't change anything, but you might find it more readable.
If you upgrade to C++20, you can also:
std::cout << "date_since_start 2: " << time_point_since_start << '\n';
Which would output:
date_since_start 2: 4147-08-20 07:32:15
(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
std::time_t date_since_start = system_clock::to_time_t(time_point_since_start);
with:
std::time_t date_since_start = time_point_since_start.time_since_epoch().count();
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 to system_clock::duration
. And on libstdc++ this is nanoseconds
. And 64 bit nanoseconds will overflow on 2262-04-11 23:47:16.854775807.