C++ Chrono and Time
- Description: A note on
<chrono>— durations, time points, clocks, calendar (C++20), time zones, formatting, and timing patterns - My Notion Note ID: K2A-B1-22
- Created: 2020-04-15
- Updated: 2026-02-28
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1. Durations
- 2. Time Points and Clocks
- 3. Calendar Types (C++20)
- 4. Time Zones (C++20)
- 5. Formatting and Parsing
- 6. Sleeping and Waiting
- 7. Timing Code
1. Durations
std::chrono::duration<Rep, Period> represents a length of time as a Rep count of Period-sized ticks. The standard library provides typedefs for common durations.
#include <chrono>
using namespace std::chrono;
nanoseconds ns{500};
microseconds us{250};
milliseconds ms{100};
seconds s{5};
minutes m{2};
hours h{1};
days d{7}; // C++20
weeks w{2}; // C++20
months mo{6}; // C++20 (not constant length — average)
years y{1}; // C++20 (not constant length — average)
// Conversions are implicit when no precision is lost
milliseconds total = h + s; // 3605000 ms
seconds approx = duration_cast<seconds>(total); // explicit cast for lossy conversions
// Arithmetic
auto x = 5s + 200ms; // 5200 ms
auto y = 3min / 30; // 6 s
auto z = 1h - 30min; // 30 min
// Literals (C++14)
using namespace std::chrono_literals;
auto t = 250ms + 5s;
2. Time Points and Clocks
A clock is a source of time — it produces time points (instants).
| Clock | Properties | Use for |
|---|---|---|
std::chrono::system_clock |
Wall clock; can jump, may go backward (NTP, DST) | Storing dates/times, displaying time |
std::chrono::steady_clock |
Monotonic; never goes backward | Measuring elapsed time |
std::chrono::high_resolution_clock |
Highest available resolution; alias for one of the above | Avoid — use the explicit ones |
std::chrono::utc_clock (C++20) |
UTC; leap seconds explicit | Storing UTC timestamps |
std::chrono::file_clock |
Filesystem timestamps | Pair with std::filesystem::last_write_time |
auto now = std::chrono::system_clock::now(); // time_point<system_clock>
auto epoch = now.time_since_epoch();
auto sec_since_epoch = duration_cast<seconds>(epoch).count();
// Converting between clocks (C++20)
auto utc_now = std::chrono::utc_clock::now();
auto sys_now = std::chrono::clock_cast<std::chrono::system_clock>(utc_now);
Always use steady_clock for measuring durations — system_clock may jump and produce negative durations:
auto t0 = std::chrono::steady_clock::now();
do_work();
auto t1 = std::chrono::steady_clock::now();
auto elapsed = duration_cast<milliseconds>(t1 - t0);
3. Calendar Types (C++20)
C++20 added a calendar system with named types and operator chaining.
using namespace std::chrono;
year_month_day today = 2026y/February/28;
year_month_day_last eom = 2026y/February/last; // last day of February 2026
// Computing dates
auto next_week = sys_days{today} + days{7};
auto next_year = today + years{1};
// Day-of-week
weekday wd{sys_days{today}};
std::cout << wd; // e.g. "Sat"
// Validity
bool ok = today.ok(); // false for impossible dates like 2026/Feb/30
sys_days is a duration of days from the system epoch — useful for arithmetic between dates.
4. Time Zones (C++20)
using namespace std::chrono;
const time_zone* la = locate_zone("America/Los_Angeles");
zoned_time<seconds> now_la{la, system_clock::now()};
std::cout << now_la; // formatted in LA local time
zoned_time pairs a clock time with a zone, doing all conversions automatically.
The IANA time zone database is required for full support; most platforms ship it, but check on Windows.
5. Formatting and Parsing
#include <format>
using namespace std::chrono;
auto now = system_clock::now();
std::string s = std::format("{:%Y-%m-%d %H:%M:%S}", now);
// "2026-02-28 14:30:45"
std::string iso = std::format("{:%FT%TZ}", floor<seconds>(now));
// "2026-02-28T14:30:45Z"
Format specifiers come from strftime. Key codes:
| Code | Meaning |
|---|---|
%Y |
4-digit year |
%m, %d |
2-digit month, day |
%H, %M, %S |
2-digit hour (24h), min, sec |
%F |
%Y-%m-%d |
%T |
%H:%M:%S |
%A, %a |
weekday name (full / abbreviated) |
%Z, %z |
time zone name / offset |
6. Sleeping and Waiting
#include <thread>
using namespace std::chrono_literals;
std::this_thread::sleep_for(500ms);
std::this_thread::sleep_until(system_clock::now() + 2s);
Used with condition_variable::wait_for and wait_until for timeouts:
std::unique_lock<std::mutex> lock(m);
if (cv.wait_for(lock, 500ms, [&] { return ready; })) {
// condition satisfied
} else {
// timed out
}
7. Timing Code
A small helper for measuring elapsed time:
template <typename Fn>
auto time_it(Fn&& fn) {
auto t0 = std::chrono::steady_clock::now();
fn();
auto t1 = std::chrono::steady_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0);
}
auto elapsed = time_it([] { do_work(); });
std::cout << elapsed.count() / 1e6 << " ms\n";
For benchmarks, prefer Google Benchmark or nanobench — they handle warm-up, repetition, and statistical variance correctly. chrono alone is fine for ad-hoc timing or instrumentation.