C++ Date and Time (chrono)
The header chrono measures and handles time in a type-safe way: a duration of 5 seconds and one of 5 milliseconds are different types, so they cannot be mixed up by accident.
Durations
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
seconds s(90);
minutes m = duration_cast<minutes>(s);
milliseconds ms = s; // exact: converts automatically
std::cout << s.count() << " s = " << m.count() << " min (rounded down) = "
<< ms.count() << " ms\n";
auto total = hours(1) + minutes(30);
std::cout << duration_cast<minutes>(total).count() << " minutes\n";
return 0;
}90 s = 1 min (rounded down) = 90000 ms 90 minutes
Conversions that cannot lose information (seconds to milliseconds) happen automatically; conversions that can (seconds to minutes) need duration_cast, which cuts off the remainder.
Measuring how long code takes
steady_clock never jumps (unlike the wall clock, which can be changed), so it is the right clock for measuring:
#include <chrono>
#include <iostream>
int main() {
auto start = std::chrono::steady_clock::now();
volatile long long sum = 0;
for (long long i = 0; i < 10000000; i++) sum += i;
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "sum " << sum << " took " << ms.count() << " ms\n";
return 0;
}The time differs on every run and every computer, so this example has no fixed output.
The current date and time
system_clock::now() gives the current time. C++20 can print it directly with std::format, or you can convert it to C's time_t and use std::put_time:
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::cout << "Now: " << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S") << "\n";
return 0;
}Calendar dates (C++20)
C++20 adds calendar types: years, months, days and weekdays, with checks for valid dates.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
year_month_day d{year{2024}, month{1}, day{26}};
weekday w{sys_days{d}};
std::cout << "valid: " << std::boolalpha << d.ok() << ", weekday number " << w.c_encoding() << "\n";
year_month_day bad{year{2023}, month{2}, day{29}};
std::cout << "2023-02-29 valid: " << bad.ok() << "\n";
auto later = sys_days{d} + days{10};
std::cout << "10 days later: " << year_month_day{later}.day() << "\n";
return 0;
}valid: true, weekday number 5 2023-02-29 valid: false 10 days later: 05
Weekday number 5 is Friday (Sunday is 0), and 10 days after 26 January is 5 February.
Good practice
Keep time values in chrono types for as long as possible and call count() only when printing; a function that takes std::chrono::milliseconds cannot be called with seconds by mistake. Use steady_clock to measure, system_clock for the date and time shown to people. To pause a program, std::this_thread::sleep_for(std::chrono::milliseconds(500)) from the thread header takes a duration directly.
Practice exercises
- Convert 3725 seconds into hours, minutes and seconds with
duration_cast. - Measure how long it takes to sort a vector of a million random numbers.
- Check whether 29 February is a valid date in 2024, 2100 and 2000.