Dillon Shotwell
Dillon Shotwell

Reputation: 11

c++ chrono Clock in HH:MM:SS when it needs to be in seconds.milliseconds

So right now, the code im using is

using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t (system_clock::now());
struct std::tm * ptm = std::localtime(&tt);
std::cout << "Current time: " << std::put_time(ptm,"%X") << '\n';
std::this_thread::sleep_for (std::chrono::seconds(7));

It is simple in that this is in a loop, and chrono sleep_for delays the system for however many seconds. The problem is that it is in the HH:MM:SS format when I really need seconds.milliseconds to show the system clock transaction time. How would I do this? I really just need someone to explain the code, why is it making a struct? And what should I do to change the format? Thanks!

Upvotes: 0

Views: 1919

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 218700

I've got two answers for you:

  1. How to do this next year (in C++20), which isn't implemented today, and

  2. How you can do it today with some minor syntax changes and an open-source 3rd party library.

First 1:

#include <chrono>
#include <iostream>
#include <thread>

int
main()
{
    using namespace std::chrono;
    auto tp = system_clock::now();
    while (true)
    {
        zoned_time zt{current_zone(), floor<milliseconds>(system_clock::now())};
        cout << "Current time: " << std::format("{:%T}", zt) << '\n';
        tp += 7s;
        std::this_thread::sleep_until (tp);
    }
}

This creates a local time using the computer's currently set time zone, with a precision of milliseconds. And then just prints it out with the desired format (%T). I'm using sleep_until instead of sleep_for so that each iteration of the loop doesn't drift off of the desired 7s interval due to loop overhead.

Second 2:

Nobody has C++20 chrono yet, but you can approximate it today with Howard Hinnant's free open source date/time library:

#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <thread>

int
main()
{
    using namespace date;
    using namespace std::chrono;
    auto tp = system_clock::now();
    while (true)
    {
        zoned_time zt{current_zone(), floor<milliseconds>(system_clock::now())};
        cout << "Current time: " << format("%T", zt) << '\n';
        tp += 7s;
        std::this_thread::sleep_until (tp);
    }
}

The difference is that the format statement is slightly different, and the library lives in namespace date instead of namespace std::chrono. And there's an extra header to include. And some installation is required to handle the time zones.

If you're happy with a UTC time stamp, instead of a local time stamp, then you can use a header-only version of the same library like this (no installation required):

#include "date/date.h"
#include <iostream>
#include <thread>

int
main()
{
    auto tp = std::chrono::system_clock::now();
    while (true)
    {
        using namespace date;
        using namespace std::chrono;
        std::cout << "Current time: "
                  << format("%T", floor<milliseconds>(system_clock::now())) << '\n';
        tp += 7s;
        std::this_thread::sleep_until (tp);
    }
}

Upvotes: 4

Related Questions