C++ Chrono Literals | 'Time Literals' Guide
이 글의 핵심
How to write duration readably with C++14 chrono literals (1s, 500ms, 2h, etc.). Covers std::chrono_literals, unit operations, and practical examples.
Introduction
C++14 chrono literals allow expressing time values concisely and readably. You can write 500ms instead of std::chrono::milliseconds(500).
Reality in Production
When learning development, everything is clean and theoretical. But production is different. You wrestle with legacy code, chase tight deadlines, and face unexpected bugs. The content covered in this guide was initially learned as theory, but I realized “ah, that’s why it’s designed this way” while applying it to actual projects.
What stands out in my memory is the trial and error from my first project. I did it as I learned from books but spent days not knowing why it didn’t work. Eventually, I found the problem through a senior developer’s code review and learned a lot in the process. This guide covers not only theory but also pitfalls you may encounter in practice and their solutions.
1. chrono Literals Basics
Literal Types
Here is detailed implementation code using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
using namespace std::chrono_literals;
int main() {
// Time literals
auto ns = 100ns; // nanoseconds
auto us = 100us; // microseconds
auto ms = 100ms; // milliseconds
auto s = 5s; // seconds
auto min = 10min; // minutes
auto h = 2h; // hours
std::cout << "5 seconds: " << s.count() << "s" << std::endl;
std::cout << "10 minutes: " << min.count() << "min" << std::endl;
std::cout << "2 hours: " << h.count() << "h" << std::endl;
}
Literal Types Table
| Literal | Type | Description |
|---|---|---|
100ns | std::chrono::nanoseconds | Nanoseconds (10⁻⁹s) |
100us | std::chrono::microseconds | Microseconds (10⁻⁶s) |
100ms | std::chrono::milliseconds | Milliseconds (10⁻³s) |
5s | std::chrono::seconds | Seconds |
10min | std::chrono::minutes | Minutes |
2h | std::chrono::hours | Hours |
Key Concepts:
- namespace:
std::chrono_literalsrequired - Type safety: Type checking at compile time
- Readability: Clear and concise code
2. Time Operations
Basic Operations
Here is detailed implementation code using C++. Import the necessary modules and perform branching with conditionals. Understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
using namespace std::chrono_literals;
int main() {
// Addition
auto total = 1h + 30min + 45s;
// Subtraction
auto diff = 2h - 30min;
// Multiplication
auto doubled = 5s * 2;
// Division
auto half = 10min / 2;
// Comparison
if (500ms < 1s) {
std::cout << "500ms is shorter than 1 second" << std::endl;
}
}
Unit Conversion
Here is the main implementation:
#include <iostream>
#include <chrono>
using namespace std::chrono_literals;
int main() {
auto total = 1h + 30min + 45s;
// Convert to seconds
auto totalSeconds = std::chrono::duration_cast<std::chrono::seconds>(total);
std::cout << "Total " << totalSeconds.count() << " seconds" << std::endl;
// Output: Total 5445 seconds
// Convert to milliseconds
auto totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(total);
std::cout << "Total " << totalMs.count() << "ms" << std::endl;
// Output: Total 5445000ms
// Convert to minutes (truncate decimal)
auto totalMin = std::chrono::duration_cast<std::chrono::minutes>(total);
std::cout << "Total " << totalMin.count() << " minutes" << std::endl;
// Output: Total 90 minutes
}
3. Practical Examples
Example 1: sleep
Here is detailed implementation code using C++. Import the necessary modules and process data with loops. Understand the role of each part while examining the code.
#include <iostream>
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
int main() {
std::cout << "Start" << std::endl;
// Old way (complex)
// std::this_thread::sleep_for(std::chrono::seconds(2));
// Using literals (concise)
std::this_thread::sleep_for(2s);
std::cout << "After 2 seconds" << std::endl;
// Millisecond unit
std::this_thread::sleep_for(500ms);
std::cout << "After 0.5 seconds" << std::endl;
}
Example 2: Timeout
Here is detailed implementation code using C++. Import the necessary modules, process data with loops, and perform branching with conditionals. Understand the role of each part while examining the code.
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std::chrono_literals;
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::this_thread::sleep_for(1s);
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
}
int main() {
std::thread t(worker);
std::unique_lock<std::mutex> lock(mtx);
// Wait 500ms
if (cv.wait_for(lock, 500ms, []{ return ready; })) {
std::cout << "Ready" << std::endl;
} else {
std::cout << "Timeout (500ms)" << std::endl;
}
// Wait 2s
if (cv.wait_for(lock, 2s, []{ return ready; })) {
std::cout << "Ready" << std::endl;
}
t.join();
}
Example 3: Timer Class
Here is detailed implementation code using C++. Import the necessary modules, define a class to encapsulate data and functionality, process data with loops, and perform branching with conditionals. Understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std::chrono_literals;
class Timer {
std::chrono::steady_clock::time_point start;
public:
Timer() : start(std::chrono::steady_clock::now()) {}
// Check elapsed time
template<typename Duration>
bool elapsed(Duration timeout) const {
auto now = std::chrono::steady_clock::now();
return now - start >= timeout;
}
// Return elapsed time
auto getElapsed() const {
auto now = std::chrono::steady_clock::now();
return now - start;
}
// Reset
void reset() {
start = std::chrono::steady_clock::now();
}
};
int main() {
Timer timer;
int count = 0;
// Work for 5 seconds
while (!timer.elapsed(5s)) {
std::this_thread::sleep_for(100ms);
count++;
if (count % 10 == 0) {
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
timer.getElapsed()
);
std::cout << elapsed.count() << " seconds elapsed..." << std::endl;
}
}
std::cout << "5 seconds elapsed, executed " << count << " times" << std::endl;
}
4. C++20 Date Literals
Using Date Literals
Here is detailed implementation code using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
using namespace std::chrono;
using namespace std::chrono_literals;
int main() {
// Date literals (C++20)
auto year = 2026y;
auto day = 29d;
// Create date
auto date = 2026y / March / 29d;
std::cout << date << std::endl;
// 2026-03-29
// Combine time and date
auto datetime = sys_days{2026y / March / 29d} + 14h + 30min;
}
Date Operations
Here is detailed implementation code using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
using namespace std::chrono;
using namespace std::chrono_literals;
int main() {
auto today = 2026y / March / 29d;
// Date addition
auto nextWeek = sys_days{today} + days{7};
auto nextMonth = sys_days{today} + months{1};
// Date difference
auto date1 = sys_days{2026y / March / 1d};
auto date2 = sys_days{2026y / March / 29d};
auto diff = date2 - date1;
std::cout << "Difference: " << diff.count() << " days" << std::endl;
// Difference: 28 days
}
5. Common Issues
Issue 1: Missing namespace
Below is an implementation example using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <chrono>
int main() {
// ❌ No namespace
// auto sec = 5s; // Compile error
// ✅ Use namespace
using namespace std::chrono_literals;
auto sec = 5s;
// ✅ Or explicit call
auto sec2 = std::chrono_literals::operator""s(5);
}
Error message:
error: unable to find numeric literal operator 'operator""s'
Issue 2: Type Inference
Here is detailed implementation code using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <chrono>
using namespace std::chrono_literals;
int main() {
// auto: accurate type inference
auto ms = 100ms; // std::chrono::milliseconds
// Explicit type
std::chrono::milliseconds ms2 = 100ms;
// Implicit conversion
std::chrono::seconds sec = 1000ms; // 1 second
// ❌ Precision loss
// std::chrono::seconds sec2 = 1500ms; // Compile error (1.5 seconds)
// ✅ Use duration_cast
auto sec3 = std::chrono::duration_cast<std::chrono::seconds>(1500ms);
std::cout << sec3.count() << " seconds" << std::endl; // 1 second (truncated)
}
Issue 3: Overflow
Here is detailed implementation code using C++. Import the necessary modules and understand the role of each part while examining the code.
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
int main() {
// ❌ Beware of large values (overflow possible)
// auto days = 365 * 24h; // int overflow
// ✅ Use explicit type
auto hours = std::chrono::hours(365 * 24);
// ✅ Or use literal first
auto oneDay = 24h;
auto year = oneDay * 365;
auto totalHours = std::chrono::duration_cast<std::chrono::hours>(year);
std::cout << "1 year: " << totalHours.count() << " hours" << std::endl;
}
Issue 4: Mixed Operations
Here is detailed implementation code using C++. Import the necessary modules and perform branching with conditionals. Understand the role of each part while examining the code.
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
int main() {
// Different unit operations (automatic conversion)
auto total = 1h + 30min + 45s;
// Automatically converted to smallest unit (seconds)
std::cout << "Type: " << typeid(total).name() << std::endl;
// Explicit conversion
auto totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(total);
std::cout << totalMs.count() << "ms" << std::endl;
// Comparison operations (automatic conversion)
if (500ms < 1s) {
std::cout << "500ms is shorter than 1 second" << std::endl;
}
}
6. Readability Improvement Patterns
Old Way vs Literals
Here is detailed implementation code using C++. Import the necessary modules and process data with loops. Understand the role of each part while examining the code.
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
int main() {
// ❌ Old way (hard to read)
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::this_thread::sleep_for(std::chrono::seconds(2));
std::this_thread::sleep_for(std::chrono::minutes(5));
// ✅ Using literals (concise and clear)
std::this_thread::sleep_for(500ms);
std::this_thread::sleep_for(2s);
std::this_thread::sleep_for(5min);
// ❌ Complex calculation
auto timeout = std::chrono::seconds(60 * 5);
// ✅ Clear intent
auto timeout2 = 5min;
// ✅ Complex time expression
auto duration = 1h + 30min + 45s;
}
Practical Usage
Here is detailed implementation code using C++. Import the necessary modules, ensure stability through error handling, process data with loops, and perform branching with conditionals. Understand the role of each part while examining the code.
#include <iostream>
#include <chrono>
#include <thread>
// Import necessary modules
using namespace std::chrono_literals;
// Retry logic
template<typename Func>
bool retryWithTimeout(Func func, std::chrono::milliseconds timeout) {
auto start = std::chrono::steady_clock::now();
while (true) {
if (func()) {
return true;
}
auto elapsed = std::chrono::steady_clock::now() - start;
if (elapsed >= timeout) {
return false;
}
std::this_thread::sleep_for(100ms);
}
}
int main() {
int attempt = 0;
bool success = retryWithTimeout([&]() {
attempt++;
std::cout << "Attempt " << attempt << std::endl;
return attempt >= 3; // Succeed on 3rd attempt
}, 5s);
if (success) {
std::cout << "Success!" << std::endl;
} else {
std::cout << "Timeout" << std::endl;
}
}
Summary
Key Points
- Literal types:
ns,us,ms,s,min,h - namespace:
std::chrono_literalsrequired - Operations: Addition, subtraction, multiplication, division, comparison
- Conversion: Unit conversion with
duration_cast - C++20: Date literals (
y,d)
chrono Literals Pros and Cons
| Pros | Cons |
|---|---|
| Improved readability | Namespace declaration required |
| Type safety | C++14 or higher required |
| Concise code | Caution with using in headers |
| Compile-time checking | Beware of large value overflow |
Practical Tips
-
namespace usage
- Use
using namespaceonly inside functions or cpp files - Use explicit calls in header files
- Use
-
Type conversion
- Beware of precision loss (
1500ms→seconds) - Explicit conversion with
duration_cast
- Beware of precision loss (
-
Performance
- Literals processed at compile time
- No runtime overhead
Next Steps
- C++ Chrono Guide
- C++ Duration
- C++ Calendar and Timezone
Related Articles
- View All C++ Series
- C++ Adapter Pattern Complete Guide | Interface Conversion and Compatibility
- C++ ADL |
- C++ Aggregate Initialization |