C++20中获取今天日期最轻量可靠的方式是用std::chrono::system_clock::now()获取时间点,floor截断到当日零点,再用year_month_day拆解年月日。

用 std::chrono::system_clock 获取今天日期(年月日)
直接取当前时间点再转换成本地日历日期,是 C++20 最轻量、最可靠的方式。别用 time() + localtime(),那套老接口不保证线程安全,且无法直接对接 std::chrono 类型。
关键步骤:先用 std::chrono::system_clock::now() 拿时间点,再通过 std::chrono::floor<:chrono::days></:chrono::days> 截断到当日零点,最后用 std::chrono::year_month_day 拆解:
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
auto now = system_clock::now();
auto today = year_month_day{floor<days>(now)};
std::cout << today.year() << '-'
<< static_cast<unsigned>(today.month()) << '-'
<< static_cast<unsigned>(today.day()) << '\n';
}
-
floor<days>(now)</days>是必须的——它把毫秒级时间点“归零”到当天 00:00:00,否则year_month_day构造可能跨天(比如系统时钟刚好在 23:59:59.999 时取值) -
month()和day()返回的是month/day类型,不能直接流输出,得转成unsigned - 这个结果是 UTC 时间对应的日历日期;若需本地时区,得先用
std::chrono::current_zone()转换(见下节)
获取本地时区下的“今天”要额外转换
system_clock 的时间点本质是 UTC,year_month_day 默认按 UTC 解析。想得到你所在时区的“今天”,不能只靠 std::chrono::current_zone() —— 它返回的是运行时默认时区对象,但必须手动把时间点从 UTC 映射过去:
auto now = system_clock::now();
auto zoned = current_zone()->to_local(now);
auto today_local = year_month_day{floor<days>(zoned)};
- 漏掉
to_local()直接对now取floor<days></days>,结果仍是 UTC 日期,不是你电脑设置的本地日期 -
current_zone()可能返回nullptr(如时区数据库未加载),生产环境应判空 - Windows 上需链接
tzdb库(CMake 中加target_link_libraries(... PRIVATE tzdb)),否则current_zone()恒为nullptr
格式化成字符串推荐用 std::format(C++20)
手拼 year()/month()/day() 容易出错,尤其补零问题。C++20 原生支持 std::format,简洁又安全:
立即学习“C++免费学习笔记(深入)”;
auto today = year_month_day{floor<days>(system_clock::now())};
std::string s = std::format("{:%Y-%m-%d}", today); // 输出如 "2024-06-12"
-
{:%Y-%m-%d}是标准 strftime 格式,%Y四位年,%m补零月,%d补零日 - 注意:MSVC 2022 17.5+、GCC 13+、Clang 15+ 才完整支持
std::format;旧编译器会编译失败 - 如果不用
std::format,就老实用std::ostringstream+std::setfill('0'),别自己写 sprintf 风格拼接
别踩 std::chrono::utc_clock 的坑
看到 “UTC” 就以为能直接拿今天日期?错。UTC 时间点和日历日期是两回事:utc_clock 的时间点仍需 floor 到 days 单位才能转 year_month_day,而且它的 epoch 和 system_clock 不同,直接混用会出错。
- 除非你在做高精度天文或金融时间计算,否则一律用
system_clock—— 它是 C++ 标准规定的“系统实时时钟”,语义清晰 -
utc_clock主要用于协调世界时与闰秒同步,日常业务完全不需要 - 所有示例里出现的
floor<days>(...)</days>都不可省略,这是从时间点到日历日期的必要转换,不是可选项
真正麻烦的从来不是怎么写,而是搞清“今天”到底指哪个时区、要不要考虑夏令时、以及 floor 操作是否被遗漏——这几个点卡住,代码跑出来永远差一天。


















