Reputation: 2208
The problem I'm trying to solve is given a date by day
, month
and year
and days_to_add
, add days_to_add
to the given date.
I was able to convert the date into std::chrono::time_point<system_clock, ...>
. Now I want to add given days to it:
template <typename Clock, typename Duration>
auto add_days(const std::chrono::time_point<Clock, Duration>& timepoint,
int days_to_add)
{
constexpr unsigned int seconds_in_day = 60 * 60 * 24;
// mm hh dd
return timepoint + Duration(seconds_in_day * days_to_add);
}
But the result is unchanged timepoint
. Here is the full program to reproduce:
#include <iostream>
#include <chrono>
#include <iomanip>
template <typename Clock, typename Duration>
std::ostream& operator<<(std::ostream& os, const std::chrono::time_point<Clock, Duration>& timep)
{
auto converted_timep = Clock::to_time_t(timep);
os << std::put_time(std::localtime(&converted_timep), "%Y %b %d %H:%M:%S");
return os;
}
template <typename Clock, typename Duration>
auto add_days(const std::chrono::time_point<Clock, Duration>& timepoint,
int days_to_add)
{
constexpr unsigned int seconds_in_day = 60 * 60 * 24;
// mm hh dd
return timepoint + Duration(seconds_in_day * days_to_add);
}
int main()
{
auto today = std::chrono::system_clock::now();
auto tomorrow = add_days(today, 1);
std::cout << tomorrow;
return 0;
}
Wandbox link for gcc and for clang.
2017 Jun 17 16:23:18
2017 Jun 17 16:23:18
Upvotes: 1
Views: 601
Reputation: 48948
The problem is that std::system_clock
doesn't store its time in seconds, nor in milliseconds. Did you think microseconds? Nope. It stores its time in nanoseconds (at least on gcc, which you also seem to be using)! Actually, the time is implementation defined, so it is better to use portable solutions like the last one here.
You only think that the time point is not changing, but actually, it is, but in the time scale way smaller than milliseconds.
If you calculate the nanoseconds in a day, you'll get the correct answer:
template <typename Clock, typename Duration>
auto add_days(const std::chrono::time_point<Clock, Duration>& timepoint,
int days_to_add)
{
constexpr auto nano_seconds_in_day = 1'000'000'000ul * 60 * 60 * 24;
// (ns in s) mm hh dd
return timepoint + Duration(nano_seconds_in_day * days_to_add);
}
But that would only work if you pass a time point from std::system_clock
. Other clocks can have a different duration
and thus a different value needs to be added. You should use this version instead (which is also clearer):
<typename Clock, typename Duration>
auto add_days(const std::chrono::time_point<Clock, Duration>& timepoint,
int days_to_add)
{
return timepoint + 24h * days_to_add;
}
Upvotes: 3