最可靠方案是用 std::put_time 配合 std::gmtime 反推本地时区偏移并手动拼接带冒号的 +HH:MM,避免 strftime %z 不可移植及手写格式错误;C++20 起推荐 std::chrono::zoned_time 与 std::format。

直接用 std::put_time 配合 std::gmtime 或 std::localtime 最可靠,别手写格式化逻辑。
为什么不用 strftime 直接套 ISO 8601?
strftime 的 %z 在 Windows MSVC 下不输出带冒号的时区(如 +08:00),而是 +0800;%:z 是 GNU 扩展,不可移植。ISO 8601 要求时区分隔冒号(如 2024-05-20T13:45:30+08:00),标准 C++ 库原生不支持 %:z。
- Linux/GCC 可能工作,但跨平台项目会出问题
- Windows 上
strftime(..., "%Y-%m-%dT%H:%M:%S%z")输出2024-05-20T13:45:30+0800—— 不符合 ISO 8601:2004 附录 B 要求 - 自己拼接时区字符串容易漏掉夏令时偏移或符号处理错误
std::put_time + std::gmtime 的安全写法
用 std::put_time 格式化 std::tm,再手动补上带冒号的时区。关键点:必须用 std::gmtime 获取 UTC 时间后反推本地偏移,避免 std::localtime 在多线程下非重入(C++20 前)。
- 先调用
std::gmtime(&t)得到 UTC 的std::tm - 用
std::mktime把它转回time_t,再和原值比较算出本地偏移秒数 - 偏移转为
+HH:MM字符串(注意负偏移、-05:30这类半时区) - 最后用
std::ostringstream拼接:YYYY-MM-DDTHH:MM:SS+ 时区
示例片段:
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
time_t t = std::time(nullptr);
std::tm utc_tm = *std::gmtime(&t);
std::time_t utc_as_local = std::mktime(&utc_tm); // 强制解释为本地时间
int offset_sec = static_cast<int>(t - utc_as_local);
char sign = offset_sec >= 0 ? '+' : '-';
int abs_off = std::abs(offset_sec);
int hh = abs_off / 3600;
int mm = (abs_off % 3600) / 60;
std::ostringstream oss;
oss << std::put_time(&utc_tm, "%Y-%m-%dT%H:%M:%S") << sign << std::setfill('0') << std::setw(2) << hh << ":" << std::setw(2) << mm;C++20 <chrono> 的更简洁方案
如果你能用 C++20,std::chrono::zoned_time + std::format 是最干净的:
-
std::chrono::system_clock::from_time_t(t)转成sys_time - 用
std::chrono::current_zone()或指定时区构造zoned_time -
std::format(std::locale{}, "{:%Y-%m-%dT%H:%M:%S%z}", zt)自动输出带冒号时区 - 注意:GCC 13+、Clang 16+、MSVC 19.35+ 才完整支持
std::format和时区
不支持 C++20 时,硬要省代码就用第三方库如 date.h(Howard Hinnant’s date library),它把 std::format 的能力提前带到了 C++11。
容易被忽略的细节
UTC 时间本身没有时区标识,但 ISO 8601 允许用 Z 表示零偏移。很多人直接用 std::gmtime + std::put_time 输出 ...Z,却忘了:如果原始 time_t 来自网络协议(如 HTTP Date 头),它本就是 UTC,此时加 Z 正确;但如果想表达“本地时间按 ISO 格式转出”,就必须显式计算并插入本地偏移 —— 这个选择不能靠函数自动判断,得由业务逻辑决定。
另外,std::tm 的 tm_isdst 字段在 std::gmtime 中恒为 0,但在 std::localtime 中可能为 1,影响偏移计算。所以偏移必须通过时间戳差值算,不能依赖 tm_gmtoff(非标准字段,glibc 特有)。

















