C++ duration | "Time Interval" Guide
이 글의 핵심
std::chrono::duration: typed time intervals, unit conversions, and arithmetic—stop mixing raw milliseconds ints in C++11+.
What is duration?
std::chrono::duration is a type that represents a time interval. It serves as one of the fundamental units in the chrono library, alongside time_point, especially when converting units as discussed in Time Conversion.
#include <chrono>
std::chrono::seconds sec(10);
std::chrono::milliseconds ms(1000);
std::chrono::minutes min(1);
Basic Usage
using namespace std::chrono;
seconds s(10);
milliseconds ms(10000);
// Get value
auto count = s.count(); // 10
Practical Examples
Example 1: Time Conversion
using namespace std::chrono;
seconds s(10);
// Higher unit -> Lower unit (implicit)
milliseconds ms = s; // OK: 10000ms
// Lower unit -> Higher unit (explicit)
seconds s2 = duration_cast<seconds>(ms); // 10s
Example 2: Time Operations
using namespace std::chrono;
seconds s1(10);
seconds s2(5);
auto sum = s1 + s2; // 15s
auto diff = s1 - s2; // 5s
auto mul = s1 * 2; // 20s
auto div = s1 / 2; // 5s
if (s1 > s2) {
std::cout << "s1 is longer" << std::endl;
}
Example 3: Literals
using namespace std::chrono_literals;
auto d1 = 10s; // seconds
auto d2 = 500ms; // milliseconds
auto d3 = 100us; // microseconds
auto d4 = 1min; // minutes
auto d5 = 2h; // hours
auto total = 1h + 30min + 45s;
Example 4: Custom duration
using days = std::chrono::duration<int, std::ratio<86400>>;
using weeks = std::chrono::duration<int, std::ratio<604800>>;
days d(7);
weeks w = std::chrono::duration_cast<weeks>(d); // 1 week
Example 5: Timeout Implementation
#include <chrono>
#include <thread>
#include <iostream>
using namespace std::chrono;
class Timer {
steady_clock::time_point start_;
milliseconds timeout_;
public:
Timer(milliseconds timeout)
: start_(steady_clock::now()), timeout_(timeout) {}
bool expired() const {
auto elapsed = steady_clock::now() - start_;
return elapsed >= timeout_;
}
milliseconds remaining() const {
auto elapsed = steady_clock::now() - start_;
auto remaining = timeout_ - elapsed;
return remaining > milliseconds::zero() ? remaining : milliseconds::zero();
}
};
int main() {
Timer timer(5s); // 5 second timeout
while (!timer.expired()) {
std::cout << "Remaining: " << timer.remaining().count() << "ms\n";
std::this_thread::sleep_for(1s);
}
std::cout << "Timeout!\n";
}
Example 6: Rate Limiting
#include <chrono>
#include <thread>
class RateLimiter {
steady_clock::time_point last_call_;
milliseconds min_interval_;
public:
RateLimiter(milliseconds interval)
: last_call_(steady_clock::now()), min_interval_(interval) {}
void wait_if_needed() {
auto now = steady_clock::now();
auto elapsed = now - last_call_;
if (elapsed < min_interval_) {
auto wait_time = min_interval_ - elapsed;
std::this_thread::sleep_for(wait_time);
}
last_call_ = steady_clock::now();
}
void call() {
wait_if_needed();
// ... perform rate-limited operation ...
}
};
int main() {
RateLimiter limiter(100ms); // Max 10 calls per second
for (int i = 0; i < 5; ++i) {
limiter.call();
std::cout << "Call " << i << '\n';
}
}
duration_cast
When converting between durations of different units, use duration_cast, floor, ceil, or round, as explained in the Time Conversion Guide.
using namespace std::chrono;
milliseconds ms(1500);
// Truncate
auto s = duration_cast<seconds>(ms); // 1s
// Round (C++17)
auto s2 = round<seconds>(ms); // 2s
// Ceiling
auto s3 = ceil<seconds>(ms); // 2s
// Floor
auto s4 = floor<seconds>(ms); // 1s
Common Issues
Issue 1: Precision Loss
using namespace std::chrono;
milliseconds ms(1500);
seconds s = duration_cast<seconds>(ms); // 1s (500ms lost)
// ✅ Use rounding
auto s2 = round<seconds>(ms); // 2s
Issue 2: Type Mismatch
void func(std::chrono::seconds s) {}
// ❌ Type mismatch
// func(1000); // Error
// ✅ Explicit construction
func(std::chrono::seconds(10));
// ✅ Using literals
using namespace std::chrono_literals;
func(10s);
Issue 3: Negative duration
using namespace std::chrono;
seconds s1(5);
seconds s2(10);
auto diff = s1 - s2; // -5s
std::cout << diff.count() << std::endl; // -5
Issue 4: Zero duration
using namespace std::chrono;
seconds s = seconds::zero(); // 0s
milliseconds ms = milliseconds::zero();
if (s == seconds::zero()) {
std::cout << "0 seconds" << std::endl;
}
Defined Time Units
// Standard units (C++11)
std::chrono::hours
std::chrono::minutes
std::chrono::seconds
std::chrono::milliseconds
std::chrono::microseconds
std::chrono::nanoseconds
// Added in C++20
std::chrono::days
std::chrono::weeks
std::chrono::months
std::chrono::years
Practical Patterns
Pattern 1: Configurable Timeout
class NetworkClient {
milliseconds timeout_ = 30s; // Default 30 seconds
public:
void set_timeout(milliseconds timeout) {
timeout_ = timeout;
}
bool connect() {
auto start = steady_clock::now();
while (true) {
if (try_connect()) return true;
auto elapsed = steady_clock::now() - start;
if (elapsed > timeout_) {
return false; // Timeout
}
std::this_thread::sleep_for(100ms);
}
}
};
// Usage
NetworkClient client;
client.set_timeout(10s); // 10 second timeout
client.connect();
Pattern 2: Retry with Backoff
#include <chrono>
#include <thread>
#include <iostream>
using namespace std::chrono;
template<typename Func>
bool retry_with_backoff(Func f, int max_attempts = 5) {
milliseconds backoff = 100ms;
for (int attempt = 0; attempt < max_attempts; ++attempt) {
if (f()) return true;
std::cout << "Attempt " << attempt + 1 << " failed, "
<< "waiting " << backoff.count() << "ms\n";
std::this_thread::sleep_for(backoff);
backoff *= 2; // Exponential backoff
}
return false;
}
// Usage
bool result = retry_with_backoff([]() {
return try_connect_to_server();
}, 5);
Pattern 3: Performance Measurement
#include <chrono>
#include <iostream>
template<typename Func>
auto measure_time(Func f) {
auto start = steady_clock::now();
f();
auto end = steady_clock::now();
return duration_cast<milliseconds>(end - start);
}
// Usage
auto elapsed = measure_time([]() {
// ... some work ...
std::this_thread::sleep_for(2s);
});
std::cout << "Elapsed: " << elapsed.count() << "ms\n";
Time Zones and Calendar
C++20 Time Zones
C++20 adds timezone support through std::chrono::time_zone and related types.
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
// Current time in UTC
auto now = system_clock::now();
// Convert to local time
auto local_time = zoned_time{current_zone(), now};
std::cout << "Local: " << local_time << '\n';
// Convert to specific timezone
auto ny_time = zoned_time{"America/New_York", now};
std::cout << "New York: " << ny_time << '\n';
auto tokyo_time = zoned_time{"Asia/Tokyo", now};
std::cout << "Tokyo: " << tokyo_time << '\n';
}
Calendar Operations
#include <chrono>
#include <iostream>
using namespace std::chrono;
int main() {
// Current date
auto today = floor<days>(system_clock::now());
auto ymd = year_month_day{today};
std::cout << "Today: " << ymd << '\n';
// Add duration
auto next_week = today + weeks{1};
auto next_week_ymd = year_month_day{next_week};
std::cout << "Next week: " << next_week_ymd << '\n';
// Specific date
auto christmas = year{2026}/December/25;
auto christmas_tp = sys_days{christmas};
auto days_until = duration_cast<days>(christmas_tp - today);
std::cout << "Days until Christmas: " << days_until.count() << '\n';
}
FAQ
Q1: What is duration?
A: A time interval.
Q2: How to convert units?
A:
- Higher -> Lower: Implicit
- Lower -> Higher: duration_cast
Q3: Can I perform operations?
A: Yes, you can use +, -, *, /, and comparisons.
Q4: What about literals?
A: Use using namespace std::chrono_literals.
Q5: Precision loss?
A: duration_cast truncates. Use round/ceil/floor for alternatives.
Q6: How do I work with time zones?
A: Use C++20’s zoned_time and time_zone:
auto now = system_clock::now();
auto ny_time = zoned_time{"America/New_York", now};
auto tokyo_time = zoned_time{"Asia/Tokyo", now};
Q7: Can I use duration for dates?
A: C++20 adds days, weeks, months, and years for calendar operations. Use year_month_day for date arithmetic.
Q8: What’s the difference between duration and time_point?
A:
- duration: Time interval (e.g., “5 seconds”)
- time_point: Specific point in time (e.g., “2026-03-12 14:30:00”)
Q9: How do I implement a timeout?
A: Compare elapsed time with timeout duration:
auto start = steady_clock::now();
while (true) {
if (steady_clock::now() - start > timeout) {
break; // Timeout
}
}
Q10: What about negative durations?
A: Negative durations are valid and useful for representing time differences:
auto past = steady_clock::now() - 5s;
auto diff = past - steady_clock::now(); // Negative duration
Q11: Where can I learn more about duration?
A:
- “C++ Primer” by Lippman, Lajoie, Moo
- “Effective Modern C++” by Scott Meyers
- cppreference.com - std::chrono::duration
- Howard Hinnant’s date library (basis for C++20 calendar)
Related Posts: Time Conversion: duration_cast and time_point_cast, time_point: Representing Points in Time, Overview of chrono, Stopwatch and Benchmarking.
One-line summary: std::chrono::duration represents time intervals with type-safe unit conversions, arithmetic operations, and C++20 timezone support.
## 같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- [C++ 시간 변환 | chrono duration_cast와 시계 변환](/blog/cpp-time-conversion/)
- [C++ time_point | "시간 지점" 가이드](/blog/cpp-time-point/)
- [C++ Chrono | "시간 라이브러리" 가이드](/blog/cpp-chrono/)
- [C++ 스톱워치와 벤치마크 | chrono으로 실행 시간 측정하기](/blog/cpp-stopwatch-benchmark/)
---
---
## 이 글에서 다루는 키워드 (관련 검색어)
C++, duration, chrono, time, C++11 등으로 검색하시면 이 글이 도움이 됩니다.