标准C++20之前需用std::time_t与std::localtime配合std::tm提取本地日期:tm_year+1900得年份,tm_mon+1得月份,tm_mday得日;C++20推荐用floor<days>(system_clock::now())转year_month_day,再取year()、month()、day()。

用 std::chrono 和 std::time_t 获取本地当前日期
标准 C++20 之前没有直接的「年月日」类型,得靠 std::time_t + std::localtime 配合 std::tm 结构体。这是最通用、跨平台且无需第三方库的方式。
注意:std::localtime 返回的是本地时区时间,线程不安全(可改用 std::localtime_r 在 POSIX 系统上);Windows 上对应的是 localtime_s。
常见错误是直接对 std::time(nullptr) 做指针解引用而没检查是否为 nullptr——系统时钟未初始化或权限受限时可能返回空指针。
-
std::tm中tm_year是从 1900 年起算的,所以要加 1900 才得真实年份 -
tm_mon是 0 起始(0 表示一月),输出前必须 +1 -
tm_mday是 1 起始,可直接用
auto now = std::time(nullptr);
auto* tm_ptr = std::localtime(&now);
if (tm_ptr) {
int year = tm_ptr->tm_year + 1900;
int month = tm_ptr->tm_mon + 1;
int day = tm_ptr->tm_mday;
// year, month, day 已就绪
}用 C++20 std::chrono::year_month_day 更安全简洁
C++20 引入了真正语义清晰的日期类型,但需确认编译器支持(GCC 11+、Clang 14+、MSVC 19.30+),且默认不启用时区支持——year_month_day 本身只表示日历日期,不带时区信息。
立即学习“C++免费学习笔记(深入)”;
关键点:它不能直接从「现在」构造,必须先转成 sys_days(即系统时钟的「天」精度时间点),再转换。
- 用
std::chrono::system_clock::now()获取当前时间点 - 截断到天精度:调用
floor<days>(...) - 转成
year_month_day:隐式或显式构造均可
using namespace std::chrono;
auto today = floor<days>(system_clock::now());
year_month_day ymd{today};
int year = static_cast<int>(ymd.year());
unsigned month = ymd.month();
unsigned day = ymd.day();注意:ymd.year() 返回 std::chrono::year 类型,必须显式转 int;month() 和 day() 返回的是无符号整型,值域合法(month 是 1–12,day 是 1–31)。
为什么别用 std::get_time 或字符串解析来“反推”日期
有人试图用 std::put_time 格式化成字符串再用 std::get_time 解析,纯属绕路且脆弱——格式依赖 locale、易因空格/分隔符失败,还多一次 I/O 和字符串分配。
更隐蔽的问题是:某些 locale 下 %Y 可能输出负数年份(如公元前),而 std::get_time 对负年份支持不一致,GCC libstdc++ 和 MSVC STL 行为不同。
- 不要把时间当字符串中转,除非你明确需要格式化输出
-
std::put_time适合输出,std::get_time适合解析外部输入,不是内部日期提取工具 - 所有「获取当前日期」的需求,都该走
time_t或chrono时间点路径
跨平台编译时容易漏掉的细节
Windows 默认不定义 _CRT_SECURE_NO_WARNINGS,调用 localtime 会触发安全警告;而 Linux 下若忘了链接 -lrt(某些旧 glibc 版本需要),clock_gettime 等函数可能链接失败——但这里用不到它。
真正容易被忽略的是:C++20 的 <chrono> 日期类型在不同标准库实现中,部分成员函数(比如 year::operator int())在早期 GCC 版本里是 explicit 的,必须写 static_cast<int>(y),不能直接 y + 0。
如果项目要兼容 C++17,就老实用 std::tm 方案;选 C++20 就确保构建环境和标准库版本匹配,别只看编译器版本号。


















