std::get_time不支持微秒解析,应改用C++20的std::chrono::parse或手动切分字符串:先用std::get_time解析主干时间,再用std::stoi提取微秒并补零,最后组合为time_point。

std::get_time 无法解析微秒,必须换方案
std::get_time 是 C++11 提供的轻量时间解析工具,但它只支持到秒级(%S),对 .123456 这类微秒部分完全忽略或导致解析失败。哪怕你写 %Y-%m-%dT%H:%M:%S.%f,std::get_time 也根本不认识 %f —— 它不是标准支持的格式符。实际测试中,输入 "2024-05-20T14:32:18.123456" 会导致 failbit 置位,tm 中秒字段仍是 0。
用 std::chrono::parse(C++20)直接转为 time_point
C++20 引入了 std::chrono::parse,原生支持微秒甚至纳秒精度,且语法贴近 ISO 8601。关键点是:必须用 std::chrono::sys_time(即系统时钟时间点)配合带小数秒的格式串,不能用 std::tm 中间过渡。
示例:
std::string s = "2024-05-20T14:32:18.123456";
std::chrono::sys_seconds sec;
std::chrono::microseconds us;
std::istringstream iss(s);
iss >> std::chrono::parse("%Y-%m-%dT%H:%M:%S", sec)
>> std::chrono::parse(".%f", us);
auto tp = sec + us;
注意:%f 在 std::chrono::parse 中表示“小数秒”,自动按位数推断精度(6 位即微秒);us 类型必须与实际精度匹配,否则截断或溢出。
立即学习“C++免费学习笔记(深入)”;
兼容 C++17 或更低版本:手动切分 + std::stoi
没有 C++20?别硬套 strptime(非标准)或第三方库。稳妥做法是字符串切分:先用 find('.'') 找小数点,分离主干和微秒部分,再分别解析。
- 主干部分(如
"2024-05-20T14:32:18")用std::get_time解析进std::tm - 微秒部分(如
"123456")用std::stoi转整数,注意补零到 6 位("123"→123000) - 用
std::mktime转为time_t,再转std::chrono::system_clock::time_point,最后加上微秒偏移
容易漏掉的坑:std::tm 的 tm_year 是从 1900 起算,tm_mon 是 0–11;std::mktime 会修改 tm_isdst,若不关心夏令时,建议显式设为 -1。
ISO 8601 变体多,先标准化再解析
真实数据里常出现 Z、+08:00、-0500 等时区标识,而 std::chrono::parse 默认不处理时区(只认 UTC 偏移数值)。如果字符串含 Z,必须在格式串中显式写 "%Z" 并配 std::chrono::zoned_time;如果含 +HH:MM,得用 %z,但要注意 std::chrono::parse 对 %z 的支持在 GCC 12+ 和 Clang 14+ 才稳定。
更省事的做法:用正则或简单查找预处理,把所有时区信息剥离,统一转成 UTC 时间字符串(例如将 "+08:00" 对应的本地时间减去 8 小时),再交给核心解析逻辑。否则,一个 %z 解析失败,整个 failbit 就置位,连微秒都读不到。
微秒精度本身不难,难的是 ISO 字符串的现实碎片化——先做归一化,比堆砌解析逻辑更可靠。


















