fmt::format与iostream输出chrono时间不一致问题及UTC配置方法
解决fmt库与iostream时间输出不一致及设置fmt默认UTC格式化的问题
问题背景
在使用{fmt}库格式化std::chrono::system_clock::time_point时,出现输出不一致的情况:fmt默认将时间转换为本地时区时间,而<iostream>直接输出UTC时间。示例代码及对应输出如下:
示例代码:
#include <chrono> #include <fmt/chrono.h> #include <iostream> int main(){ using TimePoint = std::chrono::system_clock::time_point; TimePoint localTime = std::chrono::system_clock::now(); auto localTimeStr = fmt::format("{:%F %T}", localTime); std::cout << localTimeStr << std::endl << localTime; return 0; }
输出结果:
2023-03-15 21:47:46 2023-03-15 20:47:46.0631142
开发环境:MSVC 19.34、fmt 9.1.0。需要解决两个核心问题:
- 如何配置fmt使其输出与
<iostream>一致? - 如何设置fmt始终以UTC格式打印时间?
问题1:让fmt输出与iostream一致(即UTC时间)
<iostream>输出std::chrono::system_clock::time_point时,直接基于UTC基准的时间戳转换为字符串;而fmt默认会将system_clock的时间点转换为本地时区时间。要让fmt输出UTC时间,只需用fmt::gmtime()包装时间点,它会将时间点转换为UTC时区的时间结构:
修改后的代码片段:
auto utcTimeStr = fmt::format("{:%F %T}", fmt::gmtime(localTime)); std::cout << utcTimeStr << std::endl << localTime;
此时utcTimeStr的输出会和cout直接打印的时间完全一致。
问题2:设置fmt始终以UTC格式打印时间
如果希望所有fmt对system_clock::time_point的格式化都默认使用UTC,推荐两种实用方式:
方式1:封装工具函数
定义一个轻量工具函数,自动帮你完成fmt::gmtime的包装,避免重复代码:
#include <fmt/chrono.h> template <typename TimePoint> auto utc_format(const TimePoint& tp, fmt::format_string<TimePoint> fmt_str) { return fmt::format(fmt_str, fmt::gmtime(tp)); } // 使用示例 auto utcStr = utc_format(localTime, "{:%F %T}");
方式2:自定义fmt格式化器
通过特化fmt的格式化器,让system_clock::time_point默认使用UTC规则格式化,无需每次手动包装:
#include <fmt/chrono.h> #include <chrono> template <> struct fmt::formatter<std::chrono::system_clock::time_point> : fmt::formatter<fmt::gmtime_format> { template <typename FormatContext> auto format(std::chrono::system_clock::time_point tp, FormatContext& ctx) { return formatter<fmt::gmtime_format>::format(fmt::gmtime(tp), ctx); } }; // 使用示例,直接格式化即可输出UTC时间 auto utcStr = fmt::format("{:%F %T}", localTime);
内容的提问来源于stack exchange,提问作者Kaaml
相关产品推荐
相关产品推荐

