I have two std::chrono::time_point instances in variables exp
and time
. exp
has a time in the future and time
is the current time. But when I compare them as in this snippet:
std::time_t t_exp = std::chrono::system_clock::to_time_t(exp);
std::time_t t_time = std::chrono::system_clock::to_time_t(time);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;
I get output:
Sat Apr 26 01:39:43 4758
Fri May 29 18:11:59 2020
1
Which is wrong because exp
is in the year 4758 and time
is in the year 2020.
Where am I going wrong?
t_exp
is-4243023785
This value of time_t
corresponds to 1835-07-18 22:16:55 (assuming the Unix epoch and a precision of seconds, neither of which are specified by the standard, but are common).
Apparently the implementation of ctime
on your platform can't handle dates this far in the past, which is a little surprising as 1835 is not very far in the past.
The value of exp
is -4243023785
times a million or a billion (depending on the precision of system_clock
on your platform) and is stored with a signed 64 bit integer (there is no overflow). Thus time > exp == 1
is correct (time
is 1590775919s
converted to the precision of system_clock
).
Sat Apr 26 01:39:43 4758 corresponds to a time_t
of 87990716383.
I see nothing wrong with your use of the chrono
library in the above code.
Update
The value 87990716383 is being converted to a
time_point
usingfrom_time_t()
Ah, this combined with the knowledge that on your platform the precision of system_clock
is nanoseconds
tells me that you are experiencing overflow on the construction of exp
.
This is not the code you have:
std::time_t t_exp = std::chrono::system_clock::to_time_t(exp);
std::time_t t_time = std::chrono::system_clock::to_time_t(time);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;
The code you have looks something like:
// ...
std::time_t t_exp = 87990716383;
auto exp = std::chrono::system_clock::from_time_t(t_exp);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;
On your platform, system_clock
stores nanoseconds
since 1970-01-01 00:00:00 UTC in a signed 64 bit integer. The maximum storable date (system_clock::time_point::max()
) on your platform is:
2262-04-11 23:47:16.854775807
Beyond this, the underlying storage of nanoseconds
overflows.
When 87990716383 (seconds) is converted in from_time_t
, it is multiplied by a billion which overflows. The overflowed value is -4243003985547758080 which corresponds to the date 1835-07-19 03:46:54.452241920.
You can get a larger range by using a coarser precision, for example:
std::time_t t_exp = 87990716383;
time_point<system_clock, microseconds> exp{seconds{t_exp}};
// exp == 4758-04-26 01:39:43.000000