Random Numbers, Dates and Times

The <random> library generates random numbers properly — with a choice of engine and distribution — and <chrono> handles durations, clocks, dates and time zones with types that make unit mistakes impossible.

Random numbers

Random generation has two parts: an engine that produces raw random bits, and a distribution that shapes them into the numbers you want:

C++
#include <iostream>
#include <random>

int main() {
    std::random_device seed_source;                    // non-deterministic seed from the OS
    std::mt19937 engine{seed_source()};                // Mersenne Twister engine

    std::uniform_int_distribution<int> die{1, 6};
    std::uniform_real_distribution<double> unit{0.0, 1.0};
    std::normal_distribution<double> height{170.0, 8.0};   // mean 170, std. deviation 8

    for (int i = 0; i < 5; ++i) std::cout << die(engine) << ' ';
    std::cout << '\n' << unit(engine) << ' ' << height(engine) << '\n';
}

Create the engine once and reuse it — creating a new engine for every number is slow and less random. The old C rand() has poor quality and a small range; prefer <random>.

Reproducible sequences

Seeding with a fixed number gives the same sequence every time — ideal for tests, simulations and games with replayable levels. The engines' raw output is specified exactly by the standard:

C++
#include <iostream>
#include <random>

int main() {
    std::mt19937 engine{42};
    for (int i = 0; i < 3; ++i) std::cout << engine() << ' ';
    std::cout << '\n';
}
Output
1608637542 3421126067 4083286876

These three numbers are the same with every compiler. Distributions, however, are implemented differently by each standard library, so uniform_int_distribution results from a fixed seed can differ between GCC, Clang and MSVC. If you need identical results everywhere, derive values from the raw engine output yourself.

Shuffling and sampling

C++
#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>

int main() {
    std::mt19937 engine{std::random_device{}()};
    std::vector<std::string> deck{"A", "K", "Q", "J", "10", "9"};
    std::shuffle(deck.begin(), deck.end(), engine);
    for (const auto& c : deck) std::cout << c << ' ';
    std::cout << '\n';
}

None of these generators are suitable for passwords or security tokens — use your operating system's cryptographic random source or a crypto library for that.

Durations

<chrono> represents time spans as durations with units in their type, so mixing seconds and milliseconds can't go wrong:

C++
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;
    auto film = 2h + 15min;
    auto ad_break = 90s;
    auto total = film + ad_break;                                   // converted automatically
    std::cout << total << '\n';
    std::cout << std::chrono::duration_cast<std::chrono::minutes>(total) << '\n';
    std::cout << std::chrono::duration<double, std::ratio<3600>>(total).count() << " hours\n";
}
Output
8190s
136min
2.275 hours

Conversions that don't lose precision happen implicitly; those that would (seconds to minutes) need duration_cast.

Measuring elapsed time

steady_clock never jumps backwards, so it's the right clock for timing code:

C++
#include <chrono>
#include <iostream>

int main() {
    auto start = std::chrono::steady_clock::now();
    long long sum = 0;
    for (int i = 0; i < 50'000'000; ++i) sum += i % 7;
    auto elapsed = std::chrono::steady_clock::now() - start;
    std::cout << sum << " computed in "
              << std::chrono::duration_cast<std::chrono::milliseconds>(elapsed) << '\n';
}

For wall-clock time ("what time is it?"), use system_clock::now().

Calendar dates

C++20 adds calendar types: years, months, days, weekdays and dates, with checked arithmetic and formatting:

C++
#include <chrono>
#include <format>
#include <iostream>

int main() {
    using namespace std::chrono;
    year_month_day launch{year{2026}, October, day{8}};
    sys_days launch_day = launch;

    std::cout << std::format("{:%A %d %B %Y}\n", launch_day);
    std::cout << "30 days later: " << year_month_day{launch_day + days{30}} << '\n';

    auto christmas = sys_days{2026y / December / 25};
    std::cout << (christmas - launch_day).count() << " days until Christmas\n";

    year_month_day bad{year{2026}, February, day{30}};
    std::cout << std::boolalpha << "2026-02-30 valid? " << bad.ok() << '\n';
    std::cout << "2028 is a leap year? " << year{2028}.is_leap() << '\n';
}
Output
Thursday 08 October 2026
30 days later: 2026-11-07
78 days until Christmas
2026-02-30 valid? false
2028 is a leap year? true

C++20 also includes time-zone support (std::chrono::zoned_time), though not every standard library implements it fully yet.

Try it yourself

Work out how old someone is in days and which weekday they were born on.

Try it yourself · main.cpp
Edit the code, copy it into main.cpp, then compile and run it with c++ -std=c++20 -Wall main.cpp -o main && ./main. How to set up a C++ compiler
Output
Born on a Sunday, 10070 days ago (about 27 years)