chrono — 时间库
<chrono>是 C++11 引入的类型安全时间库,提供时钟、时间点、时间段,告别time_t和gettimeofday的混乱。
时间段(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_clock。duration_cast 是时间段转换的唯一方式,会截断(不是四舍五入)。C++20 的日历和时区支持让时间处理变得完整。