Durations
Location
-
Courses
/
-
Complete C++ Course
/
-
The C++ Standard Library
/
-
Date and time
/
Durations
Summary
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.
Typedef | Value of the period | Minimum size of the member count (in bits) |
---|---|---|
hours | ratio<3600, 1> | 23 |
minutes | ratio<60, 1> | 29 |
seconds | ratio<1, 1> | 35 |
milliseconds | ratio<1, 1000> | 45 |
microseconds | ratio<1, 1000000> | 55 |
nanoseconds | ratio<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;
}
