My goal is to convert one single string
in the form "%H:%M:%S"
to chrono::duration
in C++11
.
As an example, in order to convert "00:15:00"
,
I came up with the following indirect solution where I calculate two timepoints (1) "00:15:00"
and (2) "00:00:00"
, which are with respect to the system_clock
or steady_clock
: I then subtract them from each other to get the duration.
std::tm tm0 = {}, tm1{};
std::stringstream ss0("00:00:00"), ss1("00:15:00");
ss0 >> std::get_time(&tm0, "%H:%M:%S");
ss1 >> std::get_time(&tm1, "%H:%M:%S");
auto t0 = std::chrono::system_clock::from_time_t(std::mktime(&tm0));
auto t1 = std::chrono::system_clock::from_time_t(std::mktime(&tm1));
auto d = t1-t0;
std::cout << std::chrono::duration_cast<std::chrono::seconds>(d).count();
It does the conversion but I was wondering if there is an elegant way or direct way of achieving this.
Your current solution has the potential to very rarely give you incorrect answers. If your two local times happen to straddle a UTC offset change in your local time zone (e.g. a daylight saving shift), then the amount of that shift is going to be included in the subtraction, subsequently giving you the wrong answer.
I recommend doing your own parsing to get the value of hours, minutes and seconds into int
s:
int h0, h1;
int m0, m1;
int s0, s1;
and then you can very simply convert them to the proper units and add/subtract them:
auto d = (hours{h1} + minutes{m1} + seconds{s1})
- (hours{h0} + minutes{m0} + seconds{s0});
The type of d
is seconds
.
You have several options for parsing in C++11, and here is one of the simplest:
ss0 >> h0 >> c >> m0 >> c >> s0;
ss1 >> h1 >> c >> m1 >> c >> s1;
(where c
is a char
to parse the :
)
In C++20 there will be a std::chrono::parse
function that can be used like this:
seconds d;
ss0 >> parse("%H:%M:%S", d);
Or one can use "%T"
as a shortcut for "%H:%M:%S"
. I mention this knowing you are using C++11, not C++20. But there exists a free, open-source preview of C++20 chrono that works with C++11/14/17. For this part, you only need the header date.h, which is a header-only library.
#include "date/date.h"
// ...
seconds d;
ss0 >> date::parse("%T", d);