使用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对 epoch 一无所知。Aduration只是两个time_points之间的时间度量。

time_point另一方面,A知道一个纪元。它包含一个duration和意味着:这已经duration超出了(或之前)我的时代。

std::format理解之间的区别time_pointduration。因此,如果格式字符串要求输入日期(例如%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


以上是使用std::format将time_point转换为字符串,格式包括日期、时间和亚秒的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>