C++开发基础之日期处理的全面指南:从C库到Chrono

📚 目录
一、C语言时代的日期处理:<ctime>
早期C++主要沿用C语言的时间接口,定义在头文件 <ctime> 中。
其核心结构是 std::time_t(自1970年1月1日以来的秒数)与 std::tm(本地时间结构体)。
1. 获取当前时间
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
int main() {
std::time_t now = std::time(nullptr); // 获取当前时间(自1970-01-01起的秒数)
std::cout << "time_t: " << now << std::endl;
// 转换为本地时间
std::tm* localTime = std::localtime(&now);
std::cout << "Local time: "
<< 1900 + localTime->tm_year << "-"
<< 1 + localTime->tm_mon << "-"
<< localTime->tm_mday << " "
<< localTime->tm_hour << ":"
<< localTime->tm_min << ":"
<< localTime->tm_sec << std::endl;
return 0;
}
输出示例:

error C4996: ‘localtime’: This function or variable may be unsafe.
Consider using localtime_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
是 Visual Studio 的安全警告机制(Secure CRT) 发出的,
它认为 localtime() 是不安全的(因为它返回的 tm* 指向全局静态对象,可能线程不安全)。
2. 使用更安全的 localtime_s()
#include <ctime>
#include <iostream>
int main() {
std::time_t now = std::time(nullptr);
std::tm localTime{};
localtime_s(&localTime, &now); // ✅ 安全版本
std::cout << "Local time: "
<< 1900 + localTime.tm_year << "-"
<< 1 + localTime.tm_mon << "-"
<< localTime.tm_mday << " "
<< localTime.tm_hour << ":"
<< localTime.tm_min << ":"
<< localTime.tm_sec << std::endl;
return 0;
}
💡 localtime_s 的参数顺序是:
int localtime_s(struct tm* _Tm, const time_t* _Time);
注意与 POSIX 的 localtime_r() 参数顺序相反!
输出示例:

3. 结构体 std::tm 解析
| 字段 | 含义 | 示例 |
|---|---|---|
tm_year | 年份偏移量(从1900开始) | 125 → 2025 |
tm_mon | 月份,从0开始 | 0~11 |
tm_mday | 日(1~31) | 10 |
tm_hour | 时(0~23) | 23 |
tm_min | 分(0~59) | 28 |
tm_sec | 秒(0~59) | 14 |
因此,格式化时常常要加上 1900 和 1 修正。
4. 时间字符串与格式化
char buffer[64];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);
std::cout << "Formatted time: " << buffer << std::endl;
输出:
Formatted time: 2025-10-10 23:28:14
缺点:
- 容易出错(结构体字段不直观)
- 不支持毫秒、纳秒
- 不便于时间计算
二、现代C++的时间库:<chrono>
C++11 引入的 <chrono> 库带来了强类型时间系统。
它更安全、更精确,也更符合现代开发习惯。
1. 获取当前时间
#define _CRT_SECURE_NO_WARNINGS
#include <chrono>
#include <iostream>
int main() {
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::cout << "Current time: " << std::ctime(&t);
}
输出:

2. 高精度时间点与持续时间
#include <chrono>
#include <iostream>
#include <thread>
int main() {
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
auto end = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "Elapsed: " << duration.count() << " ms\n";
}
输出:

✅
steady_clock单调递增,不受系统时间调整影响,适合用于性能测试。
3. 时间单位与类型系统
using namespace std::chrono_literals;
auto delay = 2s + 500ms;
std::cout << delay.count() << " milliseconds total\n";
输出:

| 单位 | 类型名 |
|---|---|
| 秒 | std::chrono::seconds |
| 毫秒 | std::chrono::milliseconds |
| 微秒 | std::chrono::microseconds |
| 纳秒 | std::chrono::nanoseconds |
4. 日期与格式化输出(C++20)
C++20 新增了日期类型与格式化支持:

#include <chrono>
#include <iostream>
#include <format>
int main() {
using namespace std::chrono;
auto now = system_clock::now();
auto today = floor<days>(now);
year_month_day ymd{today};
std::cout << std::format("Today is: {:%Y-%m-%d}\n", ymd);
}
输出:

日期加减也更直观:
auto tomorrow = sys_days{ ymd } + days{ 1 };
std::cout << std::format("Tomorrow: {:%Y-%m-%d}\n", tomorrow);

三、实战:计算两个日期的差值
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
year_month_day start{year{2025}, month{1}, day{1}};
year_month_day end{year{2025}, month{10}, day{10}};
auto diff = sys_days{end} - sys_days{start};
std::cout << "Days between: " << diff.count() << " days\n";
}
输出:

四、混合使用:兼容旧接口
在实际工程中,常常需要兼容旧API(日志系统、数据库等)。
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm* tm = std::localtime(&t);
反向转换:
std::time_t t = std::time(nullptr);
auto tp = std::chrono::system_clock::from_time_t(t);
五、总结与最佳实践
| 需求 | 推荐方案 | 理由 |
|---|---|---|
| 获取系统时间 | std::chrono::system_clock::now() | 高精度、类型安全 |
| 计算时间间隔 | steady_clock | 不受系统调整影响 |
| 格式化输出 | std::format("{:%Y-%m-%d %H:%M:%S}", tp) | 简洁优雅 |
| 日期差值 | year_month_day + sys_days | 精准直观 |
| 与旧接口兼容 | <ctime> 转换 | 平滑迁移 |
六、结语
从 time_t 到 std::chrono,C++ 的时间处理终于从“痛苦拼结构体”升级为“类型安全 + 可读 + 精准”的现代方案。
如果你还在用 std::tm 做日期计算,
不妨试试 std::chrono ——
它不仅让代码更优雅,也能避免那些年年踩的时间坑。
七、推荐阅读
- 📘 cppreference:
<chrono> - ⏳ Howard Hinnant’s date library —
<chrono>的灵感来源 - 🧭 C++20
<format>时间格式化
更多推荐




所有评论(0)