c++20 最简方案是用 std::chrono::zoned_time{std::chrono::current_zone(), now} 配合 std::format,自动处理本地时区转换与偏移(如 +0800),无需手动计算,但需编译器支持(gcc 13+ 等)并注意夏令时测试。

用 std::chrono + std::format(C++20)最简方案
直接获取带本地时区偏移的当前时间,C++20 起最干净的方式是组合 std::chrono::system_clock::now() 和 std::format。它自动处理本地时区转换和偏移格式(如 +0800 或 -05:00),无需手动调用 C 风格函数。
注意:需开启 -std=c++20 且编译器支持(GCC 13+、Clang 15+、MSVC 19.30+)。示例:
auto now = std::chrono::system_clock::now();
auto local_time = std::chrono::zoned_time{std::chrono::current_zone(), now};
std::cout
-
%z输出紧凑时区偏移(+0800),%:z输出带冒号格式(+08:00) -
std::chrono::current_zone()是关键——它读取系统环境(如TZ环境变量或系统配置),不是硬编码 UTC - 若编译器不支持
std::format,会编译失败,不能静默退化
兼容 C++11/14/17:用 std::localtime + std::strftime
老标准下必须借助 C 的 localtime_r(POSIX)或 localtime_s(Windows),再用 strftime 格式化。但要注意:这些函数依赖全局时区状态,std::localtime 在多线程下不安全,且不显式返回偏移值。
要拿到偏移,得手动计算:std::difftime 对比 localtime 和 gmtime 的 tm_hour 差值,再考虑夏令时。容易出错:
auto now = std::time(nullptr);
std::tm lt{};
#ifdef _WIN32
localtime_s(<, &now);
#else
localtime_r(&now, <);
#endif
int offset_hours = lt.tm_hour - std::gmtime(&now)->tm_hour;
// 这种推算在跨日/夏令时切换点会错,不可靠
- 真正安全的做法是调用
std::mktime(<)得到本地时间戳,再与原始now相减,除以 3600 得小时偏移(含符号) -
strftime(..., "%z")在部分平台(如 macOS)可能输出空字符串,不能依赖 - 所有 C 风格时间函数受
setenv("TZ", ...)影响,但修改后需调用tzset()才生效
为什么不用 std::get_time 或 std::put_time 直接输出偏移
std::put_time 看似能用 %z,但它底层仍调用 C 的 strftime,行为完全一致——即依赖当前 C 运行时的时区设置,且不保证跨平台输出稳定。更关键的是:std::put_time 只接受 std::tm*,而 std::tm 本身不存储时区偏移信息,%z 是运行时查表拼出来的。
- 传入由
gmtime得到的std::tm*,%z仍可能输出本地偏移(因运行时已设为本地时区) -
std::put_time无法指定目标时区,只能反映“当前 C 时区上下文”,和std::chrono::zoned_time的显式语义完全不同 - 若程序中途调用
setenv("TZ", "UTC")但忘了tzset(),std::put_time行为会意外卡在旧时区
时区偏移动态变化的坑(夏令时、系统时区切换)
本地时区偏移不是常量。夏令时切换瞬间,同一秒内 std::chrono::current_zone() 返回的偏移可能不同;用户手动改系统时区后,下次调用 std::chrono::current_zone() 会自动更新——但旧的 zoned_time 对象不会重算。
- 不要缓存
std::chrono::zoned_time对象超过必要时间,尤其在长周期服务中 - 避免用
std::chrono::current_zone()->get_info(time_point).offset提前提取偏移再手算,这绕过了zoned_time的自动对齐逻辑 - 测试时务必覆盖夏令时边界(如 3 月第二个周日、11 月第一个周日),仅用当前时间验证会漏掉逻辑分支
偏移值本身只是个整数秒差,真正难的是让它和“本地日历时间”严格对应——这点 zoned_time 封装了全部复杂性,手动模拟极易翻车。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











