c++ - 使用 std::format 将 time_point 转换为字符串,格式包括日期、时间和亚秒
问题描述
假设我们有一个简单的函数,它接受一个 std::chrono::time_point 并使用给定的格式化字符串返回一个字符串。像这样:
std::string DateTimeToString(std::chrono::sys_time, const char * szFormat /*= "%Y/%m/%d %H:%M:%S"*/)
根据std::formatter的 cppreference 文档,我们应该能够使用各个标签来创建类似2021/03/24 15:36:32.123123
. 但是,当 time_point 的持续时间使用微秒(这是我们必须使用的)时,则会引发 format_error。
如果我们将其拆分为单独的调用,以便我们分别使用日期和时间的格式,那么它就可以工作。像这样:
auto tSysTime = std::chrono::system_clock::now();
std::string sTime = std::format("{:%H:%M:%S}", tSysTime.time_since_epoch());
std::string sDate = std::format("{:%Y/%m/%d}", std::chrono::sys_days(std::chrono::duration_cast<std::chrono::days>(tSysTime.time_since_epoch())));
我是否误解了某些东西,或者没有办法为我的目的使用一个格式字符串?请记住,格式字符串是可选参数,因此我无法硬编码单个参数的拆分。
我的期望是写
std::format("{:%Y/%m/%d %H:%M:%S}",tSysTime.time_since_epoch());
然而,这崩溃了...
预先感谢您的任何帮助!
编辑:我在 Visual Studio 2019 中使用 /std::c++latest 标志
解决方案
你需要:
std::format("{:%Y/%m/%d %H:%M:%S}",tSysTime);
或者您可以将其简化为:
std::format("{:%Y/%m/%d %T}",tSysTime);
如果你system_clock::time_point::duration
不是microseconds
,你可以强制它达到微秒精度:
std::format("{:%Y/%m/%d %T}",floor<microseconds>(tSysTime));
std::format("{:%Y/%m/%d %H:%M:%S}",tSysTime.time_since_epoch());
失败的原因是.time_since_epoch()
变成time_point
了duration
. 并且duration
对日期一无所知。例如,如果你问我现在的日期和时间是什么,我告诉你 1,616,600,192,123,123µs,你会觉得我很有趣。Aduration
对一个时代一无所知。Aduration
只是两个time_point
s 之间的时间度量。
time_point
另一方面,A知道一个纪元。它拥有一个duration
和意味着:这个时代duration
超出(或之前)我的时代。
std::format
time_point
了解和之间的区别duration
。因此,如果格式字符串要求输入日期(例如%Y/%m/%d
)并且您正在格式化 a duration
,它会抛出一个异常,表明信息不足,无法完成所请求的工作。但是如果你给它一个time_point
,那么就std::format
知道如何从中获取日期信息。
这都是基于类型安全设计的一部分<chrono>
,因此可以尽早捕获尽可能多的逻辑错误。
int64_t i = 1'616'600'192'123'123;
microseconds d{i};
sys_time<microseconds> t{d};
cout << "i = " << i << '\n';
cout << "d = " << d << '\n';
cout << "t = " << t << '\n';
i
,d
并且t
都在内存中保存相同的值:1,616,600,192,123,123,但含义不同。当您打印出来时,您可以看到这些不同的含义:
i = 1616600192123123
d = 1616600192123123µs
t = 2021-03-24 15:36:32.123123
这与:
char x = 'A';
int y{x};
cout << "x = " << x << '\n'; // x = A
cout << "y = " << y << '\n'; // y = 65
推荐阅读
- flutter - 如何在三元运算符中使用不仅仅是 if/else?
- c - 打印一个额外的下划线,我不知道为什么,在清除屏幕之前只发生一次
- azure-logic-apps - “发送电子邮件”参数“附件内容”不能为空
- reactjs - 如何通过 API 数据设置 useState 来处理延迟
- scheme - 使用 readline 时如何抑制回显输入
- javascript - Javascript 在鼠标悬停时播放视频(多个视频)
- html - CSS 导入字体问题,无法直接访问 HTML
- postgresql - 查询年初至今,但跨越几年
- node.js - typescript 4.4.4:tsconfig 路径未按预期解析
- asp.net - Blazor 服务器 - HTTP 错误 500.30 - ASP.NET Core 应用程序无法启动