How can I change just the hour of an existing std::chrono::system_clock::time_point
?
For example, say I wanted to implement this function:
void set_hour(std::chrono::system_clock::time_point& tp, int hour) {
// Do something here to set the hour
}
std::chrono::system_clock::time_point midnight_jan_1_2022{std::chrono::seconds{1640995200}};
set_hour(midnight_jan_1_2022, 11);
// midnight_jan_1_2022 is now 11am on Jan 1 2022
....
CodePudding user response:
The answer depends on exactly what you mean. The simplest interpretation is that you want to take whatever date tp
points to (say yyyy-mm-dd hh:MM:ss.fff...
), and create: yyyy-mm-dd hour:00:00.000...
.
Another possible interpretation is that yyyy-mm-dd hh:MM:ss.fff...
is transformed into yyyy-mm-dd hour:MM:ss.fff...
.
In either event C 20 makes this easy, and if you don't yet have access to C 20 <chrono>
, then there exists a free, open-source header-only library that emulates C 20 <chrono>
and works with C 11/14/17.
If you want to zero the minute, second and subsecond fields as described in the first interpretation that is:
void
set_hour(std::chrono::system_clock::time_point& tp, int hour)
{
using namespace std::chrono;
auto day = floor<days>(tp);
tp = day hours{hour};
}
I.e. you simply floor the time_point
to days-precision and then add the desired hours.
The second interpretation is slightly more complicated:
void
set_hour(std::chrono::system_clock::time_point& tp, int hour)
{
using namespace std::chrono;
auto day = floor<days>(tp);
hh_mm_ss hms{tp - day};
tp = day hours{hour} hms.minutes() hms.seconds() hms.subseconds();
}
Here you have to discover and recover the {minutes, seconds, subseconds} fields to re-apply them to the desired date (along with the desired hour
). hh_mm_ss
is a C 20 {hours, minutes, seconds, subseconds}
data structure that automates the conversion from a duration into a field structure so that you can more easily replace the hours field.
Both of these solutions will give the same answer for your example input:
2022-01-01 11:00:00.000000
since the input has zeroed minutes, seconds and subseconds fields already.