C++开发基础之日期处理的全面指南:从C库到Chrono
📚 目录
- 一、C语言时代的日期处理:
<ctime>
- 1. 获取当前时间
- 2. 使用更安全的 localtime_s()
- 3. 结构体
std::tm
解析 - 4. 时间字符串与格式化
- 二、现代C++的时间库:
<chrono>
- 1. 获取当前时间
- 2. 高精度时间点与持续时间
- 3. 时间单位与类型系统
- 4. 日期与格式化输出(C++20)
- 三、实战:计算两个日期的差值
- 四、混合使用:兼容旧接口
- 五、总结与最佳实践
- 六、结语
- 七、推荐阅读
一、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>
时间格式化