Durations

The header chrono

The C++ Standard Library, since C++11, provides tools to handle time. The classes/functions used for that purpose are declared in the header file <chrono>. Everything declared in this header is part of the namespace std::chrono.

Ratio

The class std::ratio<intmax_t N, intmax_t D = 1>, declared in the header file <ratio>, is used to represent a ratio/fraction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <ratio> int main() { // Ratio of 1/2 (0.5). std::ratio<1, 2> ratio; // Ratio of 6/1 (6). std::ratio<6> ratio2; // Ratio of 2/5 (0.4). std::ratio<2, 5> ratio3; return 0; }

We can retrieve the numerator and the denominator of a fraction of type std::ratio by accessing its members num and den.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream> #include <ratio> int main() { std::ratio<3, 7> ratio; std::cout << "Numerator: " << ratio.num << ".\n"; std::cout << "Denominator: " << ratio.den << ".\n"; return 0; }

In the header file <chrono>, the class std::ratio is used to represent a fraction of a second, called a period. For example, std::ratio<1> represents a period of one second, std::ratio<1, 2>, half a second, and std::ratio<60>, a minute.

Duration

The class used to represent a duration is std::chrono::duration<class T, class P=ratio<1>>. An object of this class possesses 2 members: A period, representing a fraction of a second, and a count, representing the number of periods that has elapsed.

The first template argument is the type of the member representing the count and the second one is a std::ratio type representing the length (In seconds) of a period. The type of the member representing the count may be a floating-point or integer type.

If we give a numerical value to the constructor of an object of type std::chrono::duration, it will be assigned to its member representing the count.

We can retrieve the value of the count (Number of periods elapsed) of an object of type std::chrono::duration by calling its method T std::chrono::duration::count() const.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream> #include <chrono> int main() { std::chrono::duration<float> dur; unsigned count = 5; // Period of 1/1000 of a second. std::chrono::duration<unsigned, std::ratio<1, 1000>> dur2(count); // Period of 1/1000000 of a second. std::chrono::duration<double, std::ratio<1, 1000 * 1000>> dur3(10.45); std::cout << "Duration of " << dur.count() << " period of 1 second.\n\n"; std::cout << "Duration of " << dur2.count() << " periods of 1 millisecond "; std::cout << '(' << dur2.count() << " milliseconds).\n\n"; std::cout << "Duration of " << dur3.count() << " periods of 1 microsecond "; std::cout << '(' << dur3.count() << " microseconds).\n"; return 0; }

Duration typedefs

There are some typedefs of the class std::chrono::duration<class T, class P=ratio<1>> defined in the header file <chrono>, with specific template argument values. For all of them, the type of the count is of (signed) integer type.

TypedefValue of the periodMinimum size of the member count (in bits)
hoursratio<3600, 1>23
minutesratio<60, 1>29
secondsratio<1, 1>35
millisecondsratio<1, 1000>45
microsecondsratio<1, 1000000>55
nanosecondsratio<1, 1000000000>64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream> #include <chrono> int main() { std::chrono::nanoseconds dur(123456789); std::chrono::hours dur2(2); std::cout << dur.count() << " nanoseconds.\n\n"; std::cout << dur2.count() << " hours.\n"; return 0; }

Operations with durations as operands

We can use the assignment, mathematical and logical operators with objects of type std::chrono::duration as operands. The operands may be of different std::chrono::duration type (Different template arguments). In that case, they are automatically converted for the operation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream> #include <chrono> int main() { std::chrono::seconds sec(60); std::chrono::minutes min(1); if(sec == min) std::cout << sec.count() << " seconds == " << min.count() << " minute.\n"; sec += std::chrono::minutes(3); min++; if(sec > min) std::cout << sec.count() << " seconds > " << min.count() << " minutes.\n"; sec = min; std::cout << sec.count() << " seconds.\n"; return 0; }

The period and count type of a duration type

By accessing the static members rep and period of a duration type, we can retrieve the type it uses for its count (representation) and the fraction of a second it uses as a period.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream> #include <chrono> int main() { std::chrono::minutes min(33); // Retrieves the size of the type used for the count. std::cout << sizeof(std::chrono::minutes::rep) << "\n\n"; // We may define a variable using the type the duration uses for the count. std::chrono::minutes::rep count = min.count(); std::cout << "The ratio of the period used by the duration type std::chrono::minutes: " << std::chrono::minutes::period::num << '/' << std::chrono::minutes::period::den << ".\n"; return 0; }

Converting (Casting) duration types

Using the function constexpr T std::chrono::duration_cast (const duration<R, P>& dur), we can convert a duration object into an other type of duration, with a different period and/or count type. It takes, in argument, the duration object to convert and it takes, in template argument, the duration type to convert it to. The converted duration is returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream> #include <chrono> // Typedef of a duration with a period of 1/3 seconds and a count of type 'double'. typedef std::chrono::duration<double, std::ratio<1, 3>> OneThirdsOfSec; int main() { std::chrono::minutes min(3); // Converts a duration with a period of 1 minute to a duration with a period of 1 second. std::chrono::seconds sec = std::chrono::duration_cast<std::chrono::seconds>(min); std::cout << min.count() << " minutes == "; std::cout << sec.count() << " seconds.\n\n"; // Converts a duration of 2 hours into a duration in milliseconds. std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::hours(2)); std::cout << "2 hours == "; std::cout << ms.count() << " milliseconds.\n\n"; // Converts a duration with a period of 1 minute to a duration with a period of (1/3) seconds. OneThirdsOfSec dur = std::chrono::duration_cast<OneThirdsOfSec>(std::chrono::minutes(53)); std::cout << "53 minutes == "; std::cout << dur.count() << " (1/3) seconds.\n"; return 0; }

Note that there may be precision loss if a duration object is converted to a duration with a bigger period and/or different count type. There is also data loss if a duration is converted to a duration type that can not hold the amount of period elapsed (Smaller period and/or count type).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream> #include <chrono> int main() { std::chrono::seconds sec(83); std::chrono::minutes min = std::chrono::duration_cast< std::chrono::minutes>(sec); std::cout << sec.count() << " seconds converted to "; std::cout << min.count() << " minute.\n\n"; std::chrono::duration<double, std::ratio<60>> minDouble(30.25); std::chrono::duration<int, std::ratio<60>> minInt = std::chrono::duration_cast<std::chrono::duration<int, std::ratio<60>>>(minDouble); std::cout << minDouble.count() << " minutes ==> " << minInt.count() << " minutes.\n"; return 0; }