shashashamti2008
shashashamti2008

Reputation: 2327

Convert std::string to std::chrono::duration

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

Answers (1)

Howard Hinnant
Howard Hinnant

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 ints:

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

Related Questions