输入关键词开始搜索

C++ chrono — 时间处理

三类核心

#include <chrono>

// ① duration — 时间间隔
chrono::seconds sec(10);
chrono::milliseconds ms(500);
chrono::microseconds us = chrono::duration_cast<chrono::microseconds>(ms);

// ② time_point — 时间点
auto now = chrono::system_clock::now();
auto later = now + chrono::hours(2);

// ③ clock — 时钟源
// system_clock: 系统时间(可调,适合显示时间)
// steady_clock: 单调递增(用于计时,不受系统时间调整影响)
// high_resolution_clock: 最高精度(通常是 steady_clock 别名)

计时器

auto t1 = chrono::steady_clock::now();
doExpensiveWork();
auto t2 = chrono::steady_clock::now();

auto elapsed = chrono::duration_cast<chrono::milliseconds>(t2 - t1);
cout << "耗时: " << elapsed.count() << "ms\n";

// 通用计时器类
class Timer {
    chrono::steady_clock::time_point start;
public:
    Timer() : start(chrono::steady_clock::now()) {}
    double elapsedMs() const {
        return chrono::duration<double, milli>(
            chrono::steady_clock::now() - start).count();
    }
};

字面量(C++14)

using namespace chrono_literals;

auto halfSec = 500ms;
auto twoSec  = 2s;
auto tenMin  = 10min;
auto oneHour = 1h;

// 算术运算
auto total = 1h + 30min + 15s;  // 自动转换

// 与线程配合
this_thread::sleep_for(100ms);
this_thread::sleep_until(chrono::steady_clock::now() + 500ms);

duration_cast 规则

chrono::milliseconds ms(1500);

// 向下取整(截断)
chrono::seconds s = chrono::duration_cast<chrono::seconds>(ms);  // 1s

// 向上取整(C++17)
chrono::seconds s2 = chrono::ceil<chrono::seconds>(ms);        // 2s

// 四舍五入(C++17)
chrono::seconds s3 = chrono::round<chrono::seconds>(ms);       // 2s (1.5→2)

// 浮点 duration(不丢失精度)
chrono::duration<double> d = ms;  // 不需要 cast

时间与字符串转换

// C++20 之前 — 用 C API(繁琐)
auto now = chrono::system_clock::now();
time_t t = chrono::system_clock::to_time_t(now);
cout << ctime(&t);  // 或 strftime

// C++20 — 现代格式化(推荐)
#include <format>   // C++20
cout << format("{:%Y-%m-%d %H:%M:%S}", now);  // "2024-04-10 14:30:00"

// 解析字符串为时间点(C++20)
chrono::sys_days date;
istringstream("2024-04-10") >> chrono::parse("%F", date);

日期运算(C++20)

using namespace chrono;

// 日期类型
year_month_day ymd = 2024y / April / 10d;   // 2024-04-10
auto lastDay = 2024y / February / last;      // 2024-02-29(闰年自动)

// 日期运算
auto tomorrow = sys_days{ymd} + days{1};
auto nextMonth = ymd + months{1};

// 星期几
auto wd = weekday{sys_days{ymd}};
cout << wd;  // Wednesday

// 检查有效性
if (auto d = 2024y / February / 30d; d.ok())
    cout << "valid date";
else
    cout << "invalid date";  // 2 月没有 30 日

常见陷阱

// 陷阱 1: system_clock 计时 → 可能不准
auto t1 = chrono::system_clock::now();   // ❌ NTP 时间调整会影响
// 计时用 steady_clock ✅

// 陷阱 2: duration_cast 精度丢失
chrono::milliseconds ms(1499);
auto s = chrono::duration_cast<chrono::seconds>(ms);
cout << s.count();  // 1(不是 1.499)

// 陷阱 3: 纳秒溢出
chrono::nanoseconds ns = chrono::duration_cast<chrono::nanoseconds>(
    chrono::hours(1000));  // ⚠️ 1000h 转为 ns 可能溢出 64 位

// 陷阱 4: high_resolution_clock 不一定是 steady
// 跨平台时用 steady_clock 或显式检查 is_steady
static_assert(chrono::high_resolution_clock::is_steady);