在 C++ 中处理日期和时间:从 <ctime> 到现代 <chrono>
处理日期和时间是任何严肃应用程序中的关键任务之一:从日志和备份到定时器和财务计算。在 C++ 中,历史上形成了两种方法:通过头文件 <ctime> 的经典 C 风格,以及通过 C++11 中引入并在 C++20 中显著扩展的 <chrono> 库的现代、类型安全的方法。在本文中,我们将分析这两种方法,学习如何获取当前时间、测量时间间隔、格式化日期以及避免典型错误。
1. 经典方法:<ctime> 和 std::time_t
在 C++11 之前,处理时间的唯一标准方法是 C 语言的函数:time()、localtime()、strftime()。这种方法至今仍用于遗留代码和简单任务中。
获取当前时间
std::time(nullptr) 函数返回自 1970 年 1 月 1 日(Unix 纪元)以来的秒数,形式为整数 std::time_t。
#include <iostream>#include <ctime>
int main() { std::time_t now = std::time(nullptr); std::cout << "当前时间(自纪元以来的秒数): " << now << std::endl; return 0;}转换为可读格式
要获取包含各组成部分(年、月、日、小时等)的结构,请使用 std::localtime() 或 std::gmtime()。
#include <iostream>#include <ctime>
int main() { std::time_t now = std::time(nullptr); std::tm* local = std::localtime(&now);
std::cout << "年: " << (local->tm_year + 1900) << std::endl; std::cout << "月: " << (local->tm_mon + 1) << std::endl; std::cout << "日: " << local->tm_mday << std::endl; return 0;}使用 strftime 格式化字符串
std::strftime() 函数允许根据给定的模板灵活地将日期格式化为字符串。
#include <iostream>#include <ctime>
int main() { std::time_t now = std::time(nullptr); std::tm* local = std::localtime(&now);
char buffer[80]; std::strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M:%S", local); std::cout << "当前日期和时间: " << buffer << std::endl; return 0;}⚠️ 重要提示: std::localtime() 和 std::gmtime() 返回指向静态缓冲区的指针——这不是线程安全的。在 C++11 中,出现了可重入版本 localtime_s(Windows)或 localtime_r(POSIX)。
2. 现代 C++:<chrono> 库
<chrono> 库提供了强类型化、处理不同时间单位的能力以及高精度。主要组件:
- 时钟 (clocks):
system_clock、steady_clock、high_resolution_clock - 时间点 (time_point): 绑定到特定时刻
- 时长 (duration): 时间间隔(秒、毫秒等)
获取当前时刻
#include <iostream>#include <chrono>#include <ctime> // 用于 std::time_t
int main() { auto now = std::chrono::system_clock::now(); std::time_t now_time = std::chrono::system_clock::to_time_t(now); std::cout << "当前时间: " << std::ctime(&now_time); return 0;}测量时间间隔(定时器)
最常见的任务之一是测量代码执行时间。为此,