learnvst
learnvst

Reputation: 16193

Most simple way to get string containing time interval

I'm new to std::chrono and I'm looking for a simple way to construct a string containing a time interval formatted hhh:mm:ss (yes, 3 hour figures), indicating the difference between a start time point and now.

How would I go about this using a steady_clock? The examples on Cppreference don't quite fit this problem.

Upvotes: 4

Views: 2105

Answers (2)

sasha.sochka
sasha.sochka

Reputation: 14715

As Joachim Pileborg noted higher in the comments there is no function for format a string from a duration object. But you can do it using duration_cast to convert time difference first to hours and then minutes and seconds.

After that using C++11 to_string function you can concatenate them to get the resulting string.

#include <chrono>
#include <string>
#include <sstream>
#include <iomanip>

int main() {
    using namespace std::chrono;
    steady_clock::time_point start = /* Some point in time */;
    steady_clock::time_point now = steady_clock::now();

    int hhh = duration_cast<hours>(now - start).count();
    int mm = duration_cast<minutes>(now - start).count() % 60;
    int ss = duration_cast<seconds>(now - start).count() % 60;

    std::ostringstream stream;
    stream << std::setfill('0') << std::setw(3) << hhh << ':' <<
        std::setfill('0') << std::setw(2) << mm << ':' << 
        std::setfill('0') << std::setw(2) << ss;
    std::string result = stream.str();

}

Upvotes: 5

Howard Hinnant
Howard Hinnant

Reputation: 219345

Any time you find yourself manually applying conversion factors among units with the <chrono> library, you should be asking yourself:

Why am I converting units manually? Isn't this what <chrono> is supposed to do for me?!

A "conversion factor" is 60, or 1000, or 100, or whatever. If you see it in your code, you're opening yourself up to conversion factor errors.

Here is sasha.sochka's code rewritten without these conversion factors. And just to throw in how general this technique is, milliseconds are added for flare:

#include <chrono>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>

int main() {
    using namespace std::chrono;
    steady_clock::time_point start;
    steady_clock::time_point now = steady_clock::now();

    auto d = now -start;
    auto hhh = duration_cast<hours>(d);
    d -= hhh;
    auto mm = duration_cast<minutes>(d);
    d -= mm;
    auto ss = duration_cast<seconds>(d);
    d -= ss;
    auto ms = duration_cast<milliseconds>(d);

    std::ostringstream stream;
    stream << std::setfill('0') << std::setw(3) << hhh.count() << ':' <<
        std::setfill('0') << std::setw(2) << mm.count() << ':' << 
        std::setfill('0') << std::setw(2) << ss.count() << '.' <<
        std::setfill('0') << std::setw(3) << ms.count();
    std::string result = stream.str();
    std::cout << result << '\n';
}

There are other ways to do this without exposed conversion factors, this way is only an example. My main point is: avoid hardcoding unit conversion factors in your code. They are error prone. Even if you get it right when you first code it, conversion factors are vulnerable to future code maintenance. You can future-proof your code by demanding that all unit conversions happen within the <chrono> library.

Upvotes: 7

Related Questions