C++ std::chrono Guide — duration, time_point, Clocks &
이 글의 핵심
Measure time correctly with std::chrono: duration and time_point, choosing clocks, duration_cast, benchmarks, timeouts, timestamps, and production patterns.
Introduction: “My benchmark numbers change every run”
I used time() and the results are not trustworthy
You wrote benchmark code. You measured a function with time() or clock(), but results swing wildly between runs. The system clock may be stepped by NTP, and clock() measures CPU time, which is misleading when threads or sleep are involved.
Problematic code:
// ❌ Bad: time() is second resolution — cannot measure sub-second work
#include <ctime>
void benchmark() {
time_t start = time(nullptr);
doSomething();
time_t end = time(nullptr);
printf("Elapsed: %ld sec\n", end - start); // stays 0 if under 1 second
}
// ❌ Bad: clock() is CPU time — does not advance during sleep
#include <ctime>
void benchmark() {
clock_t start = clock();
doSomething(); // inaccurate if it includes sleep
clock_t end = clock();
printf("CPU: %f sec\n", (double)(end - start) / CLOCKS_PER_SEC);
}
Fix with chrono:
// ✅ Good: steady_clock is monotonic, nanosecond-capable resolution
#include <chrono>
#include <iostream>
void benchmark() {
auto start = std::chrono::steady_clock::now();
doSomething();
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";
}
After reading this article you will:
- Understand
std::chronoduration, time_point, and clocks - Convert units with
duration_cast - Apply patterns for benchmarks, timeouts, and log timestamps
- Recognize common mistakes and production-safe habits
Analogy: one toolbox convention
Time, files, logs, and JSON are wrenches you reach for often. Pick one standard library and one convention, and the whole team shares units and formats.
Practical note: This article is grounded in real issues seen in large C++ codebases, including pitfalls that textbooks rarely emphasize.
Table of contents
- Real-world problem scenarios
- duration: a length of time
- time_point: an instant
- Clocks: system_clock, steady_clock, high_resolution_clock
- duration_cast and unit conversion
- C++20 calendar and date arithmetic
- Hands-on timing examples
- Common errors and fixes
- Best practices
- Production patterns
- Checklist
- Summary
1. Real-world problem scenarios
Scenario 1: Benchmarks always look different
Problem: Comparing algorithms A and B with time(nullptr) prints 0 seconds for both when work finishes in under a second.
// ❌ Problem: sub-second runs always show 0
time_t t1 = time(nullptr);
algorithmA();
time_t t2 = time(nullptr);
printf("A: %ld sec\n", t2 - t1); // even 50 ms of work prints 0
Fix: Use std::chrono::steady_clock and duration_cast for millisecond or microsecond resolution.
// ✅ Fix
#include <chrono>
auto start = std::chrono::steady_clock::now();
algorithmA();
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "A: " << ms.count() << " ms\n";
Scenario 2: Timeout math breaks when NTP adjusts the clock
Problem: You implement “timeout after 30 seconds” with system_clock::now() + 30s. If NTP steps the system clock backward, your deadline can end up in the past relative to a buggy loop condition, or logic can stall unexpectedly.
// ❌ Problem: system_clock follows the system wall clock
auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (std::chrono::system_clock::now() < deadline) {
doWork(); // clock steps can make comparisons misleading for elapsed-time semantics
}
Fix: For elapsed time and timeouts, use steady_clock. It is monotonic and not affected by NTP.
// ✅ Fix
auto start = std::chrono::steady_clock::now();
auto timeout = std::chrono::seconds(30);
while (std::chrono::steady_clock::now() - start < timeout) {
doWork();
}
Scenario 3: Human-readable timestamps in logs
Problem: steady_clock::now() is an implementation-defined epoch (often “since boot”). It is not a calendar time. For "2026-03-11 14:30:00" you need system_clock (and formatting).
// ❌ steady_clock is not a calendar instant
auto tp = std::chrono::steady_clock::now();
// Not directly convertible to local calendar time
// ✅ system_clock corresponds to Unix-style wall time
auto tp = std::chrono::system_clock::now();
// C++20 chrono formatting or C localtime/strftime can format it
Scenario 4: Different duration types — compile errors
Problem: Mixing units without care can be confusing; casting to a coarser unit needs duration_cast.
// Different duration types — often need explicit casts for a specific unit
auto s = std::chrono::seconds(1);
auto ms = std::chrono::milliseconds(500);
auto sum = s + ms; // ✅ C++11+ usually promotes to a common duration type
// When you need a specific unit, use duration_cast
Scenario 5: Asio timers expect chrono durations
Problem: APIs like Boost.Asio expect a chrono::duration, not a bare int.
// ❌ Ambiguous
timer.expires_after(30); // 30 what?
// ✅ Clear
timer.expires_after(std::chrono::seconds(30));
Scenario 6: “Next Monday” style date math is painful in C
Problem: With localtime and struct tm, month boundaries and leap years are easy to get wrong.
// ❌ C++17 and below: manual date math is error-prone
std::tm tm = *std::localtime(&tt);
tm.tm_mday += 7; // crosses month?
mktime(&tm); // normalization required
Fix: C++20 std::chrono calendar types (year_month_day, weekday, …) model dates more safely.
// ✅ C++20: calendar types
#include <chrono>
using namespace std::chrono;
auto today = floor<days>(system_clock::now());
year_month_day ymd = year_month_day{sys_days{today}};
// Use weekday_indexed / calendar algorithms for “next Monday”, etc.
2. duration: a length of time
Basics
std::chrono::duration represents a length of time. It is a template over a representation type (Rep) and a period (Period) as a std::ratio.
// After paste: g++ -std=c++17 -o duration_basic duration_basic.cpp && ./duration_basic
#include <chrono>
#include <iostream>
int main() {
std::chrono::nanoseconds ns(1000000000); // 10^9 ns = 1 s
std::chrono::microseconds us(1000000); // 10^6 µs = 1 s
std::chrono::milliseconds ms(1000); // 1000 ms = 1 s
std::chrono::seconds s(1); // 1 s
std::chrono::minutes m(1); // 1 min
std::chrono::hours h(1); // 1 h
std::cout << "1 s = " << ns.count() << " ns\n";
std::cout << "1 s = " << ms.count() << " ms\n";
std::cout << "1 min = " << std::chrono::duration_cast<std::chrono::seconds>(m).count() << " s\n";
auto sum = std::chrono::seconds(30) + std::chrono::milliseconds(500);
std::cout << "30.5 s = " << std::chrono::duration_cast<std::chrono::milliseconds>(sum).count() << " ms\n";
return 0;
}
Sample output:
1 s = 1000000000 ns
1 s = 1000 ms
1 min = 60 s
30.5 s = 30500 ms
Internals:
Rep: e.g.int64_t,double— stores the numeric valuePeriod: e.g.std::milli— tick size as astd::ratio
duration arithmetic
#include <chrono>
int main() {
using namespace std::chrono;
auto d1 = seconds(10);
auto d2 = milliseconds(500);
auto sum = d1 + d2;
auto diff = d1 - d2;
auto doubled = d1 * 2;
auto half = d1 / 2;
bool b = (d1 > d2);
auto ms = duration_cast<milliseconds>(sum);
std::cout << ms.count() << " ms\n";
return 0;
}
Custom durations
#include <chrono>
#include <iostream>
using Deciseconds = std::chrono::duration<int, std::ratio<1, 10>>; // 0.1 s
using FrameDuration = std::chrono::duration<double, std::ratio<1, 30>>; // 1/30 s per frame
int main() {
Deciseconds ds(5); // 0.5 s
FrameDuration fd(1); // one 1/30 s frame
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(ds);
std::cout << "5 deciseconds = " << ms.count() << " ms\n";
return 0;
}
3. time_point: an instant
Basics
std::chrono::time_point is an instant: “how far after this clock’s epoch,” stored as a duration.
// After paste: g++ -std=c++17 -o timepoint_basic timepoint_basic.cpp && ./timepoint_basic
#include <chrono>
#include <iostream>
int main() {
auto now_sys = std::chrono::system_clock::now();
auto now_steady = std::chrono::steady_clock::now();
auto future = now_sys + std::chrono::hours(24);
auto past = now_sys - std::chrono::seconds(3600);
auto elapsed = now_steady - (now_steady - std::chrono::milliseconds(100));
std::cout << "Elapsed: " << elapsed.count() << " (steady_clock tick units)\n";
auto tt = std::chrono::system_clock::to_time_t(now_sys);
std::cout << "time_t: " << tt << "\n";
return 0;
}
time_point operations
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
auto tp = steady_clock::now();
auto later = tp + seconds(10);
auto earlier = tp - milliseconds(500);
auto diff = later - tp;
auto ms = duration_cast<milliseconds>(diff);
std::cout << ms.count() << " ms\n";
return 0;
}
4. Clocks: system_clock, steady_clock, high_resolution_clock
The three standard clocks
flowchart TB
subgraph system[system_clock]
S1[Wall calendar time]
S2[Can be adjusted by NTP]
S3[to_time_t available]
end
subgraph steady[steady_clock]
T1[Monotonic]
T2[Not affected by NTP steps]
T3[Benchmarks and timeouts]
end
subgraph high[high_resolution_clock]
H1[Highest available resolution]
H2[May alias steady on some implementations]
end
| Clock | Typical use | NTP / wall clock steps | Monotonic |
|---|---|---|---|
system_clock | Real date/time, log timestamps | Yes | No |
steady_clock | Benchmarks, timeouts, elapsed time | No | Yes |
high_resolution_clock | When you need finest resolution | Implementation-defined | Implementation-defined |
system_clock
#include <chrono>
#include <ctime>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
auto tt = std::chrono::system_clock::to_time_t(now);
std::tm* tm = std::localtime(&tt);
char buf[64];
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
std::cout << "Now: " << buf << "\n";
auto tp = std::chrono::system_clock::from_time_t(tt);
return 0;
}
steady_clock
#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 << "Slept: " << elapsed.count() << " ms\n";
// steady_clock has no to_time_t — not a calendar clock
return 0;
}
high_resolution_clock
#include <chrono>
#include <iostream>
int main() {
// libstdc++/libc++: often an alias of steady_clock
// MSVC: may differ
auto start = std::chrono::high_resolution_clock::now();
volatile int x = 0;
for (int i = 0; i < 1000; ++i) x += i;
auto end = std::chrono::high_resolution_clock::now();
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
std::cout << "Loop: " << ns.count() << " ns\n";
return 0;
}
Note: If monotonicity matters, prefer steady_clock; high_resolution_clock is not guaranteed to be steady.
5. duration_cast and unit conversion
duration_cast
Use duration_cast to convert between duration units. Truncation toward zero is typical when converting to a coarser unit.
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
milliseconds ms(1500);
seconds s = duration_cast<seconds>(ms);
std::cout << "1500 ms = " << s.count() << " s (truncated)\n";
duration<double> sec(1.5);
auto ms2 = duration_cast<milliseconds>(sec);
std::cout << "1.5 s = " << ms2.count() << " ms\n";
auto sec_floor = floor<seconds>(ms);
auto sec_ceil = ceil<seconds>(ms);
auto sec_round = round<seconds>(ms);
std::cout << "floor: " << sec_floor.count() << ", ceil: " << sec_ceil.count()
<< ", round: " << sec_round.count() << "\n";
return 0;
}
floor, ceil, round (C++17)
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
milliseconds ms(1250);
auto s_floor = floor<seconds>(ms);
auto s_ceil = ceil<seconds>(ms);
auto s_round = round<seconds>(ms);
std::cout << "1250 ms -> floor: " << s_floor.count()
<< " s, ceil: " << s_ceil.count()
<< " s, round: " << s_round.count() << " s\n";
return 0;
}
6. C++20 calendar and date arithmetic
C++20 extends <chrono> with calendar and timezone facilities. Types like year, month, day, weekday, and year_month_day make many date operations type-safe.
year_month_day
#include <chrono>
#include <iostream>
#if __cplusplus >= 202002L
int main() {
using namespace std::chrono;
year_month_day ymd{year(2026), month(3), day(11)};
if (ymd.ok()) {
std::cout << "Valid date: " << ymd << "\n";
}
auto tp = sys_days{ymd};
auto ymd2 = year_month_day{floor<days>(tp)};
auto today = year_month_day{floor<days>(system_clock::now())};
std::cout << "Today: " << today << "\n";
return 0;
}
#endif
weekday, month_day_last
#if __cplusplus >= 202002L
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
year_month_day ymd{2026y, March, 11d};
std::cout << "2026-03-11: " << weekday{ymd} << "\n";
year_month_day_last ymdl{year(2026), month_day_last(month(2))};
std::cout << "Last of 2026-02: " << year_month_day{ymdl} << "\n";
return 0;
}
#endif
C++20 chrono vs C++17 and earlier
| Feature | C++17 and earlier | C++20 |
|---|---|---|
| Date representation | time_t + tm | year_month_day, etc. |
| Weekday | tm.tm_wday | weekday |
| Last day of month | manual | month_day_last |
| Formatting | strftime | std::format (with chrono types) |
| Time zones | manual / OS APIs | std::chrono::time_zone (with tzdata) |
7. Hands-on timing examples
Example 1: measure a callable
#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
template <typename Func, typename... Args>
auto measure_ms(Func&& f, Args&&... args) {
auto start = std::chrono::steady_clock::now();
std::invoke(std::forward<Func>(f), std::forward<Args>(args)...);
auto end = std::chrono::steady_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}
int main() {
auto ms = measure_ms([] { std::this_thread::sleep_for(std::chrono::milliseconds(50)); });
std::cout << "Elapsed: " << ms << " ms\n";
return 0;
}
Example 2: RAII scope timer
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
class ScopedTimer {
public:
explicit ScopedTimer(const std::string& name)
: name_(name), start_(std::chrono::steady_clock::now()) {}
~ScopedTimer() {
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start_).count();
std::cout << "[" << name_ << "] " << ms << " ms\n";
}
private:
std::string name_;
std::chrono::steady_clock::time_point start_;
};
void slowFunction() {
ScopedTimer timer("slowFunction");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
slowFunction();
return 0;
}
Example 3: timeout loop
#include <chrono>
#include <iostream>
#include <thread>
bool doWorkWithTimeout(std::chrono::milliseconds timeout) {
auto deadline = std::chrono::steady_clock::now() + timeout;
while (std::chrono::steady_clock::now() < deadline) {
if (tryDoWork()) {
return true;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return false;
}
bool tryDoWork() {
static int count = 0;
return ++count >= 5;
}
int main() {
if (doWorkWithTimeout(std::chrono::seconds(1))) {
std::cout << "Success\n";
} else {
std::cout << "Timeout\n";
}
return 0;
}
Example 4: log timestamp (system_clock)
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
std::string getTimestamp() {
auto now = std::chrono::system_clock::now();
auto tt = std::chrono::system_clock::to_time_t(now);
std::tm tm_buf;
#ifdef _WIN32
localtime_s(&tm_buf, &tt);
#else
localtime_r(&tt, &tm_buf);
#endif
std::ostringstream oss;
oss << std::put_time(&tm_buf, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
int main() {
std::cout << "[" << getTimestamp() << "] Application started\n";
return 0;
}
Example 5: mixed duration arithmetic
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
auto total = hours(1) + minutes(30) + seconds(45) + milliseconds(123);
std::cout << "Total: " << duration_cast<milliseconds>(total).count() << " ms\n";
auto fps = 60.0;
auto frame_time = duration<double, std::ratio<1>>(1.0 / fps);
auto frame_ms = duration_cast<milliseconds>(frame_time);
std::cout << "60 FPS ≈ " << frame_ms.count() << " ms per frame\n";
return 0;
}
Example 6: time() vs chrono resolution
| Approach | Typical resolution | NTP-sensitive | Counts sleep (elapsed) | Multithreading |
|---|---|---|---|---|
time() | 1 s | Yes | Poor for short waits | Coarse |
clock() | ~ms (implementation) | No | CPU time, not wall sleep | Process-wide CPU time |
steady_clock | ns–µs class | No | Yes | Per-call wall elapsed |
system_clock | ns–µs class | Yes | Yes | Yes |
#include <chrono>
#include <ctime>
#include <iostream>
#include <thread>
void compareResolution() {
auto t1 = std::time(nullptr);
std::this_thread::sleep_for(std::chrono::milliseconds(50));
auto t2 = std::time(nullptr);
std::cout << "time(): " << (t2 - t1) << " s (actual ~50 ms)\n";
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
auto end = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << "chrono: " << ms << " ms\n";
}
Sample output:
time(): 0 s (actual ~50 ms)
chrono: 50 ms
8. Common errors and fixes
Error 1: using system_clock for timeouts
Symptom: After NTP adjustments, deadlines behave oddly.
// ❌ Risky for pure elapsed-time timeouts
auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(30);
while (condition && std::chrono::system_clock::now() < deadline) { /*...*/ }
Fix: Use steady_clock for elapsed time and timeouts.
// ✅ Elapsed-time timeout
auto start = std::chrono::steady_clock::now();
auto timeout = std::chrono::seconds(30);
while (condition && (std::chrono::steady_clock::now() - start < timeout)) { /*...*/ }
Error 2: ignoring truncation in duration_cast
Symptom: 1500ms cast to seconds becomes 1s.
auto ms = std::chrono::milliseconds(1500);
auto s = std::chrono::duration_cast<std::chrono::seconds>(ms);
// s.count() == 1
Fix: Use duration<double> or round/floor/ceil when you need a specific rounding rule.
auto ms = std::chrono::milliseconds(1500);
std::chrono::duration<double> sec(ms);
auto s = std::chrono::round<std::chrono::seconds>(ms);
Error 3: steady_clock for log timestamps
Symptom: Logs show meaningless huge tick counts.
Fix: Use system_clock (or a proper logging library) for human-readable timestamps.
Error 4: count() without remembering the unit
Symptom: d.count() depends on d’s type.
auto d = std::chrono::milliseconds(1500);
std::cout << d.count(); // 1500 — milliseconds
auto d2 = std::chrono::seconds(1);
std::cout << d2.count(); // 1 — seconds
Fix: Cast to the unit you mean before printing, or print the unit in the string.
Error 5: mixing different clocks’ time_points
Symptom: You cannot subtract system_clock::time_point from steady_clock::time_point.
// ❌ Does not compile
auto tp_sys = std::chrono::system_clock::now();
auto tp_steady = std::chrono::steady_clock::now();
// auto diff = tp_sys - tp_steady;
Fix: Perform arithmetic within one clock. C++20 adds clock_cast for controlled conversions when available.
9. Best practices
1. Pick a clock by job
| Job | Preferred clock |
|---|---|
| Benchmarks | steady_clock |
| Timeouts / elapsed | steady_clock |
| Log timestamps / calendar | system_clock |
| Finest tick (after checking docs) | high_resolution_clock |
2. Readability with aliases and literals
using namespace std::chrono;
using namespace std::chrono_literals;
auto timeout = 30s;
auto delay = 100ms;
auto deadline = steady_clock::now() + timeout;
chrono_literals (C++14)
#include <chrono>
using namespace std::chrono_literals;
auto d1 = 1s;
auto d2 = 100ms;
auto d3 = 1.5min;
4. Pass duration in APIs
void setTimeout(std::chrono::milliseconds ms);
std::chrono::milliseconds getElapsed();
// Avoid: void setTimeout(int x); // seconds? milliseconds?
5. Warm up benchmarks
for (int i = 0; i < 3; ++i) {
doWork();
}
auto start = std::chrono::steady_clock::now();
for (int i = 0; i < 100; ++i) {
doWork();
}
auto end = std::chrono::steady_clock::now();
auto avg = (end - start) / 100;
10. Production patterns
Pattern 1: reusable timer class
#include <chrono>
#include <functional>
#include <iostream>
#include <thread>
class Timer {
public:
using Callback = std::function<void(std::chrono::milliseconds)>;
void start() {
start_ = std::chrono::steady_clock::now();
}
std::chrono::milliseconds elapsed() const {
auto now = std::chrono::steady_clock::now();
return std::chrono::duration_cast<std::chrono::milliseconds>(now - start_);
}
void stopAndReport(Callback cb) {
cb(elapsed());
}
private:
std::chrono::steady_clock::time_point start_;
};
int main() {
Timer t;
t.start();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
t.stopAndReport([](std::chrono::milliseconds ms) {
std::cout << "Elapsed: " << ms.count() << " ms\n";
});
return 0;
}
Pattern 2: cache TTL
#include <chrono>
#include <optional>
#include <unordered_map>
template <typename K, typename V>
class TimedCache {
public:
using Clock = std::chrono::steady_clock;
using TimePoint = Clock::time_point;
using Duration = std::chrono::seconds;
explicit TimedCache(Duration ttl) : ttl_(ttl) {}
void insert(const K& key, const V& value) {
cache_[key] = {value, Clock::now()};
}
std::optional<V> get(const K& key) {
auto it = cache_.find(key);
if (it == cache_.end()) return std::nullopt;
if (Clock::now() - it->second.second > ttl_) {
cache_.erase(it);
return std::nullopt;
}
return it->second.first;
}
private:
Duration ttl_;
std::unordered_map<K, std::pair<V, TimePoint>> cache_;
};
int main() {
TimedCache<std::string, int> cache(std::chrono::seconds(60));
cache.insert("key", 42);
if (auto v = cache.get("key")) {
std::cout << "Value: " << *v << "\n";
}
return 0;
}
Pattern 3: Boost.Asio steady timer
#include <boost/asio.hpp>
#include <chrono>
#include <iostream>
void runWithTimeout(boost::asio::io_context& io, std::chrono::seconds timeout) {
boost::asio::steady_timer timer(io, timeout);
timer.async_wait([](const boost::system::error_code& ec) {
if (!ec) {
std::cout << "Timeout!\n";
}
});
io.run();
}
Pattern 4: fixed frame rate
#include <chrono>
#include <functional>
#include <thread>
void runAtFixedRate(std::chrono::milliseconds frameTime,
std::function<void()> update,
std::function<bool()> isRunning) {
auto nextFrame = std::chrono::steady_clock::now();
while (isRunning()) {
update();
nextFrame += frameTime;
std::this_thread::sleep_until(nextFrame);
}
}
Pattern 5: subsecond in logs (C++20 sketch)
#if __cplusplus >= 202002L
#include <chrono>
#include <format>
#include <iostream>
void logWithMicroseconds() {
auto now = std::chrono::system_clock::now();
auto us = std::chrono::duration_cast<std::chrono::microseconds>(
now.time_since_epoch()) % 1000000;
auto tt = std::chrono::system_clock::to_time_t(now);
std::tm* tm = std::localtime(&tt);
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}.{:06d}\n",
*tm, static_cast<int>(us.count()));
}
#endif
11. Checklist
- Use
steady_clockfor benchmarks and timeouts - Use
system_clockfor wall-clock timestamps - Remember truncation when using
duration_cast - Prefer
chrono_literalsfor readability - Expose
std::chrono::durationin function signatures - Do not mix
time_points from different clocks blindly - When printing
count(), state the unit
12. Summary
| Concept | Summary |
|---|---|
| duration | A length of time: seconds, milliseconds, … |
| time_point | An instant on a given clock’s timeline |
| system_clock | Wall time; may step; to_time_t |
| steady_clock | Monotonic; best for benchmarks and timeouts |
| duration_cast | Unit conversion; mind truncation; floor/ceil/round in C++17 |
Rules of thumb:
- Measure elapsed / timeouts →
steady_clock - Show calendar time →
system_clock - Convert units →
duration_cast(watch truncation)
Frequently asked questions (FAQ)
Q. Where does this matter in production?
A. Anywhere you need stable elapsed time, deadlines, TTLs, or readable timestamps. Prefer typed durations over raw integers.
Q. What should I read next?
A. Follow the links at the bottom of each post, or use the C++ series index.
Q. How do I go deeper?
A. Read cppreference and experiment with C++20 calendar and timezone on a recent toolchain.
References
- cppreference: std::chrono
- cppreference: duration
- cppreference: time_point
- C++20: Calendar and timezone
Related posts
- C++ profiling — perf, gprof
- C++ logging with spdlog
- Boost.Asio introduction
Practical checklist
Before coding
- Is this the right tool for the problem?
- Will teammates understand and maintain it?
- Does it meet performance requirements?
While coding
- Warnings addressed?
- Edge cases considered?
- Errors handled appropriately?
At review
- Intent is clear?
- Tests sufficient?
- Documentation updated?
Keywords
C++, std::chrono, duration, time_point, steady_clock, system_clock, duration_cast, C++11, timing, benchmark
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Replace time() with std::chrono: duration, time_point, system_clock, steady_clock, duration_cast, benchmarks, timeouts, … 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ std::chrono::steady_clock
- C++ time_point | ‘Time Points’ Guide
- C++ duration | ‘Time Interval’ Guide
이 글에서 다루는 키워드 (관련 검색어)
C++, std::chrono, duration, time_point, steady_clock, system_clock, duration_cast 등으로 검색하시면 이 글이 도움이 됩니다.