Reputation: 2327
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.
Upvotes: 4
Views: 1895
Reputation: 218700
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);
Upvotes: 3