Skip to content

chrono — 时间库

<chrono> 是 C++11 引入的类型安全时间库,提供时钟、时间点、时间段,告别 time_tgettimeofday 的混乱。

时间段(Duration)

cpp
#include <chrono>
using namespace std::chrono_literals;  // 字面量后缀

// 时间段类型
std::chrono::nanoseconds  ns{100};
std::chrono::microseconds us{100};
std::chrono::milliseconds ms{100};
std::chrono::seconds      s{10};
std::chrono::minutes      min{5};
std::chrono::hours        h{2};

// C++20 新增
std::chrono::days   d{7};
std::chrono::weeks  w{2};
std::chrono::months m{3};
std::chrono::years  y{1};

// 字面量(需要 using namespace std::chrono_literals)
auto t1 = 100ms;
auto t2 = 5s;
auto t3 = 2h + 30min + 15s;

// 转换
auto total_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t3);
std::cout << total_ms.count() << " ms\n";  // 9015000 ms

// 算术
auto sum = 1s + 500ms;  // 1500ms
auto diff = 2s - 500ms; // 1500ms
auto doubled = 2 * 1s;  // 2s

时钟(Clock)

cpp
// 三种标准时钟
// system_clock:系统时钟,可转换为日历时间
// steady_clock:单调时钟,适合计时(不会回拨)
// high_resolution_clock:最高精度(通常是 steady_clock 的别名)

// 获取当前时间点
auto now_sys = std::chrono::system_clock::now();
auto now_steady = std::chrono::steady_clock::now();

// 转换为 time_t(与 C API 互操作)
auto t = std::chrono::system_clock::to_time_t(now_sys);
std::cout << std::ctime(&t);

// C++20:直接格式化
#include <format>
auto now = std::chrono::system_clock::now();
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", now) << "\n";

性能计时

cpp
#include <chrono>

// 计时器工具类
class Timer {
    using Clock = std::chrono::steady_clock;
    Clock::time_point start_;

public:
    Timer() : start_(Clock::now()) {}

    void reset() { start_ = Clock::now(); }

    template<typename Duration = std::chrono::milliseconds>
    auto elapsed() const {
        return std::chrono::duration_cast<Duration>(Clock::now() - start_).count();
    }

    void print(const std::string& label = "") const {
        auto ms = elapsed<std::chrono::microseconds>();
        if (!label.empty()) std::cout << label << ": ";
        std::cout << ms << " μs\n";
    }
};

// 使用
Timer t;
expensive_operation();
t.print("操作耗时");  // 操作耗时: 1234 μs

// RAII 计时器(作用域结束自动打印)
class ScopedTimer {
    Timer t_;
    std::string label_;
public:
    explicit ScopedTimer(std::string label) : label_(std::move(label)) {}
    ~ScopedTimer() { t_.print(label_); }
};

{
    ScopedTimer st("数据库查询");
    db.query("SELECT ...");
}  // 自动打印耗时

睡眠与等待

cpp
#include <thread>
#include <chrono>

// 睡眠
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(100ms);  // 字面量

// 睡眠到特定时间点
auto wake_time = std::chrono::steady_clock::now() + 5s;
std::this_thread::sleep_until(wake_time);

// 条件变量超时等待
std::mutex mtx;
std::condition_variable cv;
std::unique_lock lock(mtx);

auto timeout = std::chrono::steady_clock::now() + 1s;
if (cv.wait_until(lock, timeout, []{ return ready; })) {
    std::cout << "条件满足\n";
} else {
    std::cout << "超时\n";
}

C++20 日历与时区

cpp
#include <chrono>

// 日历类型
auto today = std::chrono::year_month_day{
    std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())};

std::cout << today.year() << "-"
          << (unsigned)today.month() << "-"
          << (unsigned)today.day() << "\n";

// 构造特定日期
auto date = std::chrono::year{2026} / std::chrono::month{4} / std::chrono::day{23};
auto date2 = 2026y / std::chrono::April / 23d;

// 时区
#include <chrono>
auto tz = std::chrono::locate_zone("Asia/Shanghai");
auto local_now = std::chrono::zoned_time{tz, std::chrono::system_clock::now()};
std::cout << std::format("{:%Y-%m-%d %H:%M:%S %Z}", local_now) << "\n";

关键认知

计时用 steady_clock(单调,不受系统时间调整影响),日历时间用 system_clockduration_cast 是时间段转换的唯一方式,会截断(不是四舍五入)。C++20 的日历和时区支持让时间处理变得完整。

系统学习 C++ 生态,深入底层架构