Time#
The <chrono> library, introduced in C++11, provides a type-safe way to
work with time durations, clocks, and time points. It eliminates common errors
from mixing time units and offers high-resolution timing for performance
measurement. C++20 added calendar and time zone support, making <chrono>
a complete solution for date and time handling.
Getting Current Timestamp#
- Source:
The system_clock provides wall-clock time that can be converted to calendar
time. The time_since_epoch() method returns the duration since the Unix
epoch (January 1, 1970). Use duration_cast to convert between time units.
#include <chrono>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch());
std::cout << ms.count() << "\n"; // Milliseconds since epoch
}
Duration and Time Arithmetic#
- Source:
Durations represent time spans with compile-time unit safety. The library
provides predefined durations (hours, minutes, seconds, milliseconds,
microseconds, nanoseconds) and supports arithmetic operations. C++14
added user-defined literals for convenient duration creation.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono_literals;
auto duration = 2h + 30min + 45s; // 2 hours, 30 minutes, 45 seconds
auto total_seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
std::cout << total_seconds.count() << " seconds\n"; // Output: 9045 seconds
// Time arithmetic
auto now = std::chrono::system_clock::now();
auto future = now + 24h; // 24 hours from now
}
Measuring Elapsed Time (Profiling)#
- Source:
Use steady_clock for measuring elapsed time because it is monotonic and
not affected by system clock adjustments. system_clock can jump forward
or backward due to NTP synchronization or manual changes, making it unsuitable
for benchmarking.
#include <chrono>
#include <iostream>
#include <thread>
int main() {
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "Elapsed: " << elapsed.count() << " ms\n";
}
Converting to time_t#
- Source:
The to_time_t function converts a time_point to the C-style time_t
type, enabling interoperability with legacy C time functions like gmtime,
localtime, and strftime.
#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 << std::put_time(std::gmtime(&t), "%Y-%m-%d %H:%M:%S UTC") << "\n";
}
Converting from Timestamp to time_point#
- Source:
To convert a Unix timestamp (milliseconds or seconds since epoch) back to a
time_point, construct a duration and use it to initialize the time point.
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
int main() {
using namespace std::chrono_literals;
// Convert milliseconds timestamp to time_point
auto timestamp_ms = 1602207217323ms;
std::chrono::system_clock::time_point tp(timestamp_ms);
std::time_t t = std::chrono::system_clock::to_time_t(tp);
std::cout << std::put_time(std::gmtime(&t), "%FT%TZ") << "\n";
}
ISO 8601 Date Format#
- Source:
ISO 8601 is the international standard for date and time representation.
Use std::put_time with format specifiers to produce ISO 8601 compliant
strings. The %F specifier is equivalent to %Y-%m-%d and %T is
equivalent to %H:%M:%S.
#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);
// ISO 8601 formats
std::cout << std::put_time(std::gmtime(&t), "%Y-%m-%dT%H:%M:%SZ") << "\n";
std::cout << std::put_time(std::gmtime(&t), "%FT%TZ") << "\n"; // Shorthand
}
Formatting with Time Zones#
- Source:
Before C++20, time zone handling required platform-specific code or the
TZ environment variable. Use gmtime for UTC and localtime for
the system’s local time zone.
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
int main() {
std::time_t t = std::time(nullptr);
std::cout << "UTC: " << std::put_time(std::gmtime(&t), "%F %T") << "\n";
std::cout << "Local: " << std::put_time(std::localtime(&t), "%F %T %Z") << "\n";
}
C++20 Calendar and Time Zones#
C++20 introduced comprehensive calendar support with year, month,
day, year_month_day, and time zone handling via std::chrono::zoned_time.
This eliminates the need for C-style time functions and environment variables.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// Calendar types (C++20)
auto today = year{2024}/month{3}/day{15};
std::cout << today << "\n"; // 2024-03-15
// Time zones (C++20)
auto now = system_clock::now();
zoned_time zt{"America/New_York", now};
std::cout << zt << "\n";
}
Clock Types Comparison#
C++ provides three clock types for different use cases:
system_clock: Wall-clock time, can be converted to calendar time. May jump due to NTP or manual adjustments.steady_clock: Monotonic clock, never decreases. Best for measuring elapsed time and timeouts.high_resolution_clock: Highest available resolution. May be an alias forsystem_clockorsteady_clockdepending on implementation.
#include <chrono>
#include <iostream>
int main() {
// Check clock properties
std::cout << "system_clock is steady: "
<< std::chrono::system_clock::is_steady << "\n"; // Usually false
std::cout << "steady_clock is steady: "
<< std::chrono::steady_clock::is_steady << "\n"; // Always true
}
Duration Rounding: floor, ceil, round (C++17)#
- Source:
C++17 added floor, ceil, and round functions for rounding durations
to specific units. Unlike duration_cast which truncates toward zero, these
functions provide explicit control over rounding behavior.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
using namespace std::chrono_literals;
auto d = 2700ms; // 2.7 seconds
auto floored = floor<seconds>(d); // 2s (round down)
auto ceiled = ceil<seconds>(d); // 3s (round up)
auto rounded = round<seconds>(d); // 3s (round to nearest)
std::cout << "floor: " << floored.count() << "s\n";
std::cout << "ceil: " << ceiled.count() << "s\n";
std::cout << "round: " << rounded.count() << "s\n";
}
hh_mm_ss: Breaking Down Duration (C++20)#
- Source:
The hh_mm_ss class template splits a duration into hours, minutes, seconds,
and subseconds. This is useful for displaying durations in human-readable format
without manual arithmetic.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
using namespace std::chrono_literals;
auto d = 3h + 25min + 45s + 123ms;
hh_mm_ss hms{d};
std::cout << hms.hours().count() << "h "
<< hms.minutes().count() << "m "
<< hms.seconds().count() << "s "
<< hms.subseconds().count() << "ms\n";
// Output: 3h 25m 45s 123ms
}
Timer Utility Class#
- Source:
A reusable RAII-based timer class simplifies profiling by automatically measuring elapsed time. This pattern is commonly used for benchmarking code sections.
#include <chrono>
#include <iostream>
#include <string>
class Timer {
public:
Timer(std::string name) : name_(std::move(name)), start_(std::chrono::steady_clock::now()) {}
~Timer() {
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start_);
std::cout << name_ << ": " << ms.count() << " ms\n";
}
private:
std::string name_;
std::chrono::steady_clock::time_point start_;
};
int main() {
{
Timer t("loop");
volatile int sum = 0;
for (int i = 0; i < 1000000; ++i) sum += i;
} // Timer prints elapsed time when destroyed
}
C++20 Formatting with std::format#
C++20 introduced std::format support for chrono types, providing a modern
alternative to std::put_time. The format specifiers follow the same pattern
as strftime but with cleaner syntax.
#include <chrono>
#include <format>
#include <iostream>
int main() {
using namespace std::chrono;
auto now = system_clock::now();
// Format time_point directly (C++20)
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", now) << "\n";
std::cout << std::format("{:%F %T}", now) << "\n";
// Format duration
auto d = 3h + 25min + 10s;
std::cout << std::format("{:%H:%M:%S}", d) << "\n"; // 03:25:10
}
C++20 Additional Clocks#
C++20 added several new clock types for specialized use cases:
utc_clock: UTC time including leap secondstai_clock: International Atomic Timegps_clock: GPS timefile_clock: File system time (forstd::filesystem)
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
auto sys_now = system_clock::now();
auto utc_now = utc_clock::now();
// Convert between clocks
auto utc_from_sys = utc_clock::from_sys(sys_now);
std::cout << "System: " << sys_now << "\n";
std::cout << "UTC: " << utc_now << "\n";
}