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

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 durationssystem_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.