C++20 推荐用 std::chrono::system_clock::now() 配 std::format 生成 ISO 8601 字符串(如"2024-05-22T14:35:08.123Z"),需手动处理毫秒和Z后缀;旧标准退而使用 std::strftime,仅支持秒级且需注意线程安全与缓冲区大小。

用 std::chrono 和 std::format 生成 ISO 8601 时间字符串
现代 C++(C++20 起)最直接的方式是用 std::chrono::system_clock::now() 获取时间点,再通过 std::format 转成标准 ISO 8601 字符串(如 "2024-05-22T14:35:08.123Z"),这是 JSON 中推荐的时间表示法。
注意:std::format 在 GCC 13+ / Clang 17+ / MSVC 19.35+ 才完全支持;若编译器不支持,会触发编译错误而非静默降级。
- 必须启用 C++20:编译时加
-std=c++20 - ISO 8601 的毫秒部分需手动截断或补零 —
std::format默认只输出秒级,要毫秒得先转成std::chrono::milliseconds - Z 时区标识需手动添加(
std::format不自动处理时区);若需本地时间,得用std::chrono::current_zone()(C++20)或平台 API 补充
auto now = std::chrono::system_clock::now();
auto ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto s = std::format("{:%Y-%m-%dT%H:%M:%S}.{:03}Z",
std::chrono::time_point_cast<std::chrono::seconds>(ms),
ms.time_since_epoch().count() % 1000);
// s 示例:"2024-05-22T14:35:08.123Z"
用 std::strftime 兼容旧标准(C++11/14/17)
若项目受限于 C++17 或需跨平台稳定行为,退回到 std::time_t + std::strftime 是更稳妥的选择。它不依赖 std::format,但需注意时区和精度损失。
关键限制:只能到秒级(std::time_t 本身无毫秒),且 std::gmtime 返回的是 UTC,std::localtime 受 TZ 环境变量影响,不可靠。
立即学习“C++免费学习笔记(深入)”;
- 务必检查
std::strftime返回值是否为 0(失败),否则可能写入未初始化内存 - 缓冲区大小要足够:ISO 8601 带毫秒最多 24 字符,但
strftime不支持毫秒,所以用"%Y-%m-%dT%H:%M:%SZ"最多 20 字符,建议开 32 字节 - Windows 下
std::gmtime_s替代std::gmtime(后者不是线程安全的)
std::time_t t = std::time(nullptr);
char buf[32];
if (std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", std::gmtime(&t))) {
std::string json_time = std::string(buf);
}
嵌入 JSON 时避免手动拼接字符串
直接把时间字符串塞进 JSON 字段(如 "timestamp": "2024-05-22T14:35:08.123Z")看似简单,但容易出错:引号没转义、时区写错、字符串含非法字符(极小概率,但 strftime 若传错 tm 可能输出空字节)。
真正健壮的做法是交给 JSON 库处理序列化 — 它会自动加双引号、转义、验证格式。
- 用
nlohmann/json:直接赋值json["timestamp"] = time_str;,库内部会当字符串处理 - 用
boost::json:需显式构造boost::json::value字符串类型 - 手写 JSON 拼接?除非极简场景(如单字段日志),否则不建议 — 缺少校验,后续加字段易引入语法错误
时区与精度取舍:UTC 还是本地时间?
JSON 规范没强制时区,但工业实践强烈推荐 UTC(带 Z 后缀)。本地时间在跨系统传输时极易因时区配置不一致导致解析偏差,尤其是服务器集群分布在不同时区时。
毫秒精度也需权衡:很多日志系统或数据库(如 PostgreSQL 的 TIMESTAMP WITH TIME ZONE)默认存微秒,但 JSON 传输中保留毫秒已足够,再高反而增加体积、降低可读性。
- 别用
std::localtime生成 JSON 时间 — 它依赖运行环境,CI/CD 环境常设为 UTC,本地开发却是 CST,结果不一致 - 若业务强依赖本地时间(如前端展示),应在客户端转换,后端统一发 UTC
- C++20 的
std::chrono::zoned_time可做时区转换,但目前主流 JSON 库还不支持直接序列化它,仍需先转成字符串
std::format 的支持程度 — 看似一行代码,GCC 12 下直接编译失败,而错误信息非常不直观。宁可先用 strftime 跑通逻辑,再按需升级。


















