c++oding="utf-8" ?>
std::chrono::parse在c++20中引入,需编译器(gcc 12+、clang 14+、msvc 19.30+)支持并显式启用-std=c++20或/std:c++20,但部分标准库实现(如gcc 12.1)对毫秒等格式支持不全,可能静默失败或抛std::format_error。

std::chrono::parse 在 C++20 中才可用,且需编译器支持
不是所有编译器默认启用 std::chrono::parse,它依赖 C++20 的日历和时区扩展。GCC 12+、Clang 14+、MSVC 19.30+ 支持,但必须显式开启 -std=c++20(GCC/Clang)或 /std:c++20(MSVC)。即使开了标准,某些 libstdc++ 版本仍缺少完整实现——比如 GCC 12.1 的 parse 不支持带毫秒的格式,会静默失败或抛 std::format_error。
验证是否真能用:
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
try {
auto tp = parse("%Y-%m-%d", "2023-12-25");
std::cout
<p>如果编译失败或运行时报 <code>std::format_error: format-specifier not supported</code>,说明底层库没实现对应 specifier(如 <code>%f</code>、<code>%z</code>),得降级处理或换方案。</p>
<h3>parse 的格式字符串必须与输入严格对齐,空格和标点不能多也不能少</h3>
<p><code>std::chrono::parse</code> 是“贪婪匹配”,不跳过空白,不忽略多余字符。输入是 <code>"2023-12-25T14:30:45"</code>,格式写成 <code>"%Y-%m-%d %H:%M:%S"</code>(中间是空格)就会失败,因为实际是 <code>T</code> 字符。</p>
<ul>
<li>格式中每个字面量(如 <code>-</code>、<code>T</code>、<code>:</code>)都必须在输入中精确出现</li>
<li>输入末尾多出字符(如 <code>"2023-12-25T14:30:45Z"</code> 但格式没写 <code>%z</code>)会导致解析失败,不会截断</li>
<li>年份字段用 <code>%Y</code>(4位)还是 <code>%y</code>(2位)必须匹配,<code>"23"</code> 用 <code>%Y</code> 会失败</li>
</ul>
<p>正确示例:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">auto s = "2023-12-25T14:30:45.123Z";
auto tp = std::chrono::parse("%Y-%m-%dT%H:%M:%S.%f%z", s);
// 注意:%f 解析毫秒(3位),%z 解析时区偏移(Z 或 +0800)
解析结果类型必须是 time_point,且时钟类型要选对
std::chrono::parse 返回的是 time_point,但模板参数必须显式指定时钟。最常用的是 std::chrono::system_clock,它对应 Unix 时间戳;若用 std::chrono::steady_clock 会编译失败(它不支持从字符串构造)。
- 别写
auto tp = parse(...)—— 类型推导失败,必须写全:std::chrono::system_clock::time_point tp - 如果输入含时区(如
Z或+0800),parse会自动转为 UTC 时间,存入system_clock::time_point(即 epoch 起始的纳秒数) - 若输入无时区(如
"2023-12-25"),parse默认按本地时区解释 —— 这行为不可控,建议总带%z或手动补时区
安全写法:
std::chrono::system_clock::time_point tp;
std::istringstream ss{"2023-12-25T14:30:45Z"};
ss >> std::chrono::parse("%Y-%m-%dT%H:%M:%S%z", tp);
// 注意:这里用流操作符重载,更易捕获失败(ss.fail() 可查)
常见错误:%f 解析毫秒失败、%z 不识别 Z、中文环境 locale 干扰
%f 在多数实现中只接受 1–6 位数字并转为微秒(不是毫秒),且要求位数固定:输入 "123" 用 %f 会失败,除非写成 "123000"(补零到6位)或改用 %E3f(非标准,libstdc++ 不支持)。
-
%z要求输入是Z或+HHMM/-HHMM,+08:00(带冒号)不被识别 - 某些 locale(如中文 Windows)下
std::locale::global会影响parse对数字的识别,导致%Y读不到四位数 —— 建议解析前设回Clocale - 没有异常捕获时,失败表现为
tp保持默认值(epoch 起始),容易误判成功
规避建议:
std::locale::global(std::locale("C")); // 强制 C locale
std::chrono::system_clock::time_point tp;
if (!(std::istringstream{"2023-12-25T14:30:45.123Z"}
>> std::chrono::parse("%Y-%m-%dT%H:%M:%S.%f%z", tp))) {
// 解析失败,tp 未修改
}
真正麻烦的是跨平台兼容性:Linux 上 libstdc++ 和 macOS 上 libc++ 对 %f、%E* 的支持程度不同,生产环境建议对简单格式(如 ISO 8601)优先用 std::get_time + 手动拼装,复杂需求再上 parse。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










