C++ Chrono Literals | 'Time Literals' Guide

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

LiteralTypeDescription
100nsstd::chrono::nanosecondsNanoseconds (10⁻⁹s)
100usstd::chrono::microsecondsMicroseconds (10⁻⁶s)
100msstd::chrono::millisecondsMilliseconds (10⁻³s)
5sstd::chrono::secondsSeconds
10minstd::chrono::minutesMinutes
2hstd::chrono::hoursHours

Key Concepts:

  • namespace: std::chrono_literals required
  • 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

  1. Literal types: ns, us, ms, s, min, h
  2. namespace: std::chrono_literals required
  3. Operations: Addition, subtraction, multiplication, division, comparison
  4. Conversion: Unit conversion with duration_cast
  5. C++20: Date literals (y, d)

chrono Literals Pros and Cons

ProsCons
Improved readabilityNamespace declaration required
Type safetyC++14 or higher required
Concise codeCaution with using in headers
Compile-time checkingBeware of large value overflow

Practical Tips

  1. namespace usage

    • Use using namespace only inside functions or cpp files
    • Use explicit calls in header files
  2. Type conversion

    • Beware of precision loss (1500msseconds)
    • Explicit conversion with duration_cast
  3. Performance

    • Literals processed at compile time
    • No runtime overhead

Next Steps