8

Using std::chrono

 2 years ago
source link: https://akrzemi1.wordpress.com/2022/04/11/using-stdchrono/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Using std::chrono

The goal of this post is to show how the <chrono> library can be used to solve a practical but not that obvious problem. There is a lot of good material in the Internet where one can learn <chrono> from, for instance a series of lectures by Howard Hinnant — the author of the library:

And you probably know <chrono> already. But knowing the library may still not be enough to appreciate its power, scope and design. So the goal here is to start with the problem, and see which parts of the library need to be employed to solve it.

The task is this. We want to display the current system time, but rounded (down) to 20 minutes, so that 14:55 is displayed as 14:40.

Let’s introduce a namespace alias to make the examples shorter:

namespace krn = std::chrono;

We start from measuring the current time using the system clock:

krn::time_point p = krn::system_clock::now();

There is a number of clocks that we could choose from:

  • system_clock — this is the system-wide real time wall clock; its measurements can be mapped on the C-style time_t. Its epoch used to be unspecified in C++11 but since C++ 20 the clock actually represents the Unix Time. However, it is not monotonic, as system time can be adjusted by the admin at any point. So this is not a good candidate for measuring time intervals.
  • steady_clock — this clock is intended for handling interval measurements. It guarantees that clock ticks have identical time duration, and that its values constantly increase. On the other hand, it does not have to correspond to the wall-clock: it could be implemented as a tick count from the last system reboot.
  • high_resolution_clock — this is the clock with the highest resolution provided by the implementation. However, it is not guaranteed to be either monotonic or associated with a wall-clock time (in fact, implementations make it an alias on either system_clock or steady_clock), so it cannot be used portably.

C++20 has widened the range of options:

  • utc_clock — represents Coordinated Universal Time (UTC), which includes leap seconds.
  • tai_clock — represents International Atomic Time (TAI), does not include leap seconds.
  • gps_clock — represents Global Positioning System (GPS) time, does not include leap seconds.
  • file_clock — this is used for file times in the filesystem.

A clock is a type that assigns interpretation to numeric values representing time. The type of the clock encodes information such as:

  • epoch — the starting point from which the passage of time is measured.
  • period — the time interval of a single clock tick.

For our exercise it is enough to use the system time, so we have:

krn::time_point p = krn::system_clock::now();

krn::time_point represents the time elapsed since the clock’s epoch. The question is how. It probably stores a single integer, we have to know how to interpret it. krn::time_point looks like a type, but it is in fact a class template with its arguments deduced. The type is really:

krn::time_point<krn::system_clock, krn::system_clock::duration>

So, the time_point is parametrized by the clock and the duration. From the clock we can figure out the epoch; and we could also figure out the duration, but instead it is a separate template parameter: this is in case we want to change the resolution of time points. And this is exactly what we need to solve our task.

A word about duration types in C++. They are all instances of class template std::chrono::duration:

template<
class Rep,
class Period = std::ratio<1>
> class duration;

Rep is a numeric type (integral or floating-point) that is used to store the number of ticks. Period is trickier: it is technically also a type, but in fact this type encodes a value. This value is a “tick period”: it says what fraction of the second one tick represents. This means that the following duration declaration represents time interval with 1 second resolution:

krn::duration<int, std::ratio<1>>;

And the following duration declarations represent time intervals with 1 millisecond resolution:

krn::duration<int, std::ratio<1, 1000>>;
krn::duration<int, std::milli>;

So, what duration is krn::system_clock::duration actually? It is unspecified. The implementation will choose something reasonable and appropriate for your platform; but you cannot rely on these choices in portable programs. But this will not be our concern anyway, because we will create our own — portable — resolution: a 20-minute resolution:

using TwentyMins = krn::duration<int, std::ratio<20 * 60>>;

Now when our system_clock returns type

krn::time_point<krn::system_clock, krn::system_clock::duration>

We will convert it to

krn::time_point<krn::system_clock, TwentyMins>

And we will be rounding down. For this, the <chrono> has function floor:

krn::time_point p1 =
krn::floor<TwentyMins>(krn::system_clock::now());

Now we have the count of 20-minute intervals from the Unix Time epoch till now. The only remaining task is to print it out. In C++20 this is easy with the <format>:

std::cout << std::format("{:%Y-%m-%d %H:%M}\n", p1);

In C++11 the library is not present, so we would have to call a number of additional functions to achieve a similar effect. But what we could do instead is to use the open source {fmt} library by Victor Zverovich, which was used as a reference implementation for <format>:

#include <fmt/chrono.h>
// ...
std::cout << fmt::format("{:%Y-%m-%d %H:%M}\n", p1);

An that’s it. You can find a full working example here. I would like to thank my colleague Darek Chlipała for sharing this interesting use case with me.

Rate this:

Share this:

Loading...

Related

Local TimeApril 24, 2022In "programming"

A customizable frameworkJanuary 16, 2016In "programming"

Your own error codeJuly 12, 2017In "programming"


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK