Skip to content
C++
Library
since C++11
Intermediate

std::chrono

Type-safe time and duration library — durations, clocks, time points, and C++20 calendar and timezone types.

std::chronosince C++11

A type-safe time library that models durations (quantities of time), time points (moments anchored to a clock), and clocks (sources of time), extended in C++20 with civil-calendar types, IANA timezone support, and additional precision clocks.

Overview

std::chrono is built on three orthogonal concepts:

  • duration<Rep, Period> — a tick count of type Rep where each tick spans Period (a std::ratio) seconds. Arithmetic between durations of different periods compiles only when the conversion is lossless, or when you explicitly call duration_cast.
  • time_point<Clock, Duration> — a point in time measured from a clock's epoch, statically bound to that clock. Subtracting two time_points of the same clock yields a duration; subtracting across clocks is a compile error.
  • Clocks — tag types exposing now() and a duration typedef. C++11 introduced three; C++20 added four more with precisely specified epochs.

C++20 substantially extended the library: civil-calendar types (year_month_day, weekday, month_day, …), IANA timezone support (time_zone, zoned_time), parsing via std::chrono::parse, and new clocks.

Syntax

Duration template and predefined aliases

cpp
// Primary template
template<class Rep, class Period = std::ratio<1>>
class std::chrono::duration;

// C++11 predefined aliases
std::chrono::nanoseconds   // duration<long long, std::nano>
std::chrono::microseconds  // duration<long long, std::micro>
std::chrono::milliseconds  // duration<long long, std::milli>
std::chrono::seconds       // duration<long long>
std::chrono::minutes       // duration<long long, std::ratio<60>>
std::chrono::hours         // duration<long long, std::ratio<3600>>

// C++20 predefined aliases
std::chrono::days          // duration<int, std::ratio<86400>>
std::chrono::weeks         // duration<int, std::ratio<604800>>
std::chrono::months        // duration<int, std::ratio<2629746>> // 30.436875 days
std::chrono::years         // duration<int, std::ratio<31556952>> // 365.2425 days

User-defined literals require using namespace std::chrono_literals; (C++11):

cpp
auto t = 2h + 30min + 15s;  // chrono::hours, minutes, seconds
auto d = 500ms + 250us;     // chrono::milliseconds, microseconds
auto n = 100ns;             // chrono::nanoseconds

C++20 literal trap: 15d creates std::chrono::day{15} — a calendar day number, not a days duration. 2025y creates std::chrono::year{2025} — a calendar year, not a years duration. There are no UDL suffixes for days, weeks, months, or years durations; construct them directly: std::chrono::days{7}.

Duration operations

cpp
using namespace std::chrono;

// Implicit conversion is allowed only when lossless
seconds s = 5min;            // OK: minutes → seconds is exact
// minutes m = 90s;          // Error: potential loss of precision

// Explicit conversion truncates toward zero
auto m = duration_cast<minutes>(90s);  // 1min, not 1.5

// C++17: directed rounding
floor<seconds>(1500ms).count();  // 1
round<seconds>(1500ms).count();  // 2  (nearest)
ceil<seconds>(1500ms).count();   // 2
abs(-500ms).count();             // 500  // C++17

// Raw tick value
milliseconds{2500}.count();      // 2500
duration<double, std::ratio<1>>{0.5}.count(); // 0.5 — fractional seconds

Clock comparison

ClockMonotonicEpochC++ version
steady_clockYesUnspecifiedC++11
system_clockNoUnix epoch (C++20: guaranteed)C++11
high_resolution_clockImpl-definedImpl-definedC++11
utc_clockYesUnix epoch + leap secondsC++20
tai_clockYes1958-01-01 (TAI)C++20
gps_clockYes1980-01-06 (GPS)C++20
file_clockImpl-definedImplementation-definedC++20

high_resolution_clock is an alias for steady_clock on most implementations (GCC/libstdc++, recent MSVC). Never assume its epoch or monotonicity; prefer steady_clock explicitly.

Examples

Timing a block of code

cpp
#include <chrono>
#include <print>  // C++23

template<class F>
std::chrono::microseconds timed(F&& f) {
    auto start = std::chrono::steady_clock::now();
    f();
    return std::chrono::duration_cast<std::chrono::microseconds>(
        std::chrono::steady_clock::now() - start);
}

auto us = timed([] { process_batch(); });
std::println("elapsed: {} µs", us.count());

// C++20: duration types are directly formattable
std::println("elapsed: {}", us);  // "12345µs"

Sleeping with steady deadlines

cpp
#include <chrono>
#include <thread>
using namespace std::chrono_literals;

std::this_thread::sleep_for(100ms);

// Absolute deadline prevents drift accumulation in loops
auto next = std::chrono::steady_clock::now();
for (int i = 0; i < 10; ++i) {
    next += 200ms;
    do_periodic_work();
    std::this_thread::sleep_until(next);
}

Wall-clock timestamps and formatting (C++20)

cpp
#include <chrono>
#include <format>  // C++20

auto now = std::chrono::system_clock::now();

// Truncate to seconds resolution
auto now_s = std::chrono::floor<std::chrono::seconds>(now);

// ISO 8601 UTC
auto utc = std::format("{:%Y-%m-%dT%H:%M:%SZ}", now_s);
// "2026-05-22T14:23:05Z"

// Local civil time via IANA timezone database (C++20)
auto zt = std::chrono::zoned_time{
    std::chrono::current_zone(),
    std::chrono::system_clock::now()
};
auto local = std::format("{:%Y-%m-%d %H:%M:%S %Z}", zt);
// "2026-05-22 16:23:05 CEST"

Calendar date arithmetic (C++20)

cpp
#include <chrono>
using namespace std::chrono;

// Construct a specific date
year_month_day launch{year{2026}, June, day{1}};

// Convert a system_clock time_point to a calendar date
year_month_day today = floor<days>(system_clock::now());

// Duration between two dates — convert to sys_days first
days diff = sys_days{launch} - sys_days{today};

// Day of week
weekday wd{sys_days{today}};
bool is_friday = (wd == Friday);

// Last day of a month (C++20)
year_month_day_last last_feb = year{2026} / February / last;
year_month_day end_of_feb{last_feb};  // 2026-02-28

Parsing a date string (C++20)

cpp
#include <chrono>
#include <sstream>

std::chrono::sys_days date;
std::istringstream ss("2026-06-01");
ss >> std::chrono::parse("%Y-%m-%d", date);
// date == sys_days for 2026-06-01

Converting between clocks (C++20)

cpp
#include <chrono>

auto sys_now = std::chrono::system_clock::now();

// system_clock ignores leap seconds; utc_clock counts them
auto utc_now = std::chrono::clock_cast<std::chrono::utc_clock>(sys_now);

// time_point_cast: change duration granularity, keep the clock
auto at_second = std::chrono::time_point_cast<std::chrono::seconds>(sys_now);

Best Practices

Always use steady_clock for measuring elapsed time. Only use system_clock when you need a wall-clock value to display or store as a timestamp. The two are not substitutable: system_clock can jump backward on NTP corrections or forward on DST transitions.

Pass duration objects across API boundaries, never raw integers. A parameter typed std::chrono::milliseconds self-documents its unit and rejects unit mismatches at the call site. An int64_t timeout_ms parameter is a latent bug.

Know which rounding mode you need. duration_cast truncates; floor, round, and ceil (C++17) give directed rounding. For display, round is usually correct. For deadline computation, ceil avoids delivering early.

Seed RNGs with steady_clock, not time(0). time(0) has one-second resolution; two processes spawned in the same second get identical sequences.

cpp
auto seed = std::chrono::steady_clock::now().time_since_epoch().count();
std::mt19937_64 rng{static_cast<uint64_t>(seed)};

For calendar date arithmetic, use C++20 types. Do not implement leap-year logic or month-end arithmetic manually. year_month_day handles these correctly; converting to sys_days for duration arithmetic is the idiomatic approach.

Common Pitfalls

system_clock for elapsed time

cpp
// Bad: can go backward or jump
auto start = std::chrono::system_clock::now();
do_work();
auto elapsed = std::chrono::system_clock::now() - start; // may be negative

// Good
auto start = std::chrono::steady_clock::now();
do_work();
auto elapsed = std::chrono::steady_clock::now() - start; // always >= 0

C++20 calendar literals are not durations

cpp
using namespace std::chrono_literals;

auto x = 7d;    // std::chrono::day{7}  — a calendar day number, NOT a duration
auto y = 2025y; // std::chrono::year{2025} — a calendar year, NOT a duration

// To construct durations for days/weeks/months/years:
auto seven_days = std::chrono::days{7};
auto two_years  = std::chrono::years{2};

duration_cast truncates, not rounds

cpp
// duration_cast truncates toward zero
std::chrono::duration_cast<std::chrono::seconds>(999ms).count(); // 0, not 1

// When nearest-value is needed:
std::chrono::round<std::chrono::seconds>(999ms).count();  // 1
std::chrono::round<std::chrono::seconds>(500ms).count();  // 0 (round to even)

Month overflow in calendar arithmetic

cpp
using namespace std::chrono;

year_month_day d{year{2026}, January, day{31}};
// Adding one month naively produces an invalid date
auto next = d.year() / (d.month() + months{1}) / d.day();
next.ok(); // false — 2026-02-31 does not exist

// Converting to sys_days normalises the overflow (Feb 31 → Mar 3)
year_month_day normalised{sys_days{next}};

// For end-of-month clamping, use year_month_day_last explicitly
auto eom = d.year() / (d.month() + months{1}) / last; // 2026-02-28

Comparing .count() values of different duration types

cpp
std::chrono::seconds s{1};
std::chrono::milliseconds ms{1000};

s.count() == ms.count(); // false: 1 == 1000
s == ms;                 // true: implicit conversion, then compare

Never compare .count() values across duration types. Compare the duration objects directly; the library applies the appropriate unit conversion.

See Also

  • <ctime>time_t, tm, strftime for C-style time and legacy API interop
  • std::format / std::print (C++20/23) — {:%Y-%m-%d %H:%M:%S} format specifiers work directly on duration, time_point, zoned_time, and calendar types
  • std::this_thread::sleep_for / sleep_until (<thread>) — chrono-aware thread blocking
  • std::filesystem::file_time_typefile_clock::time_point returned by std::filesystem::last_write_time
  • std::condition_variable::wait_for / wait_until — chrono-aware condition variable blocking