Home > Software design >  Replace hour of chrono::time_point?
Replace hour of chrono::time_point?

Time:04-14

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.

  • Related