将std::string转换为std::chrono::duration

4
我的目标是将形式为“%H:%M:%S”的一个字符串转换为C ++ 11中的chrono :: duration。
例如,为了将“00:15:00”转换,我想出了以下间接解决方案,其中我计算了两个时间点(1)“00:15:00”和(2)“00:00:00”,它们与system_clock或steady_clock有关:然后我从彼此中减去它们以获得持续时间。
std::tm tm0 = {}, tm1{};
std::stringstream ss0("00:00:00"), ss1("00:15:00");
ss0 >> std::get_time(&tm0, "%H:%M:%S");
ss1 >> std::get_time(&tm1, "%H:%M:%S");
auto t0 = std::chrono::system_clock::from_time_t(std::mktime(&tm0));
auto t1 = std::chrono::system_clock::from_time_t(std::mktime(&tm1));
auto d = t1-t0;
std::cout << std::chrono::duration_cast<std::chrono::seconds>(d).count();

它可以完成转换,但我想知道是否有更优雅或直接的方法来实现这一点。

1个回答

3

您目前的解决方案有可能偶尔会给出错误答案。如果您的两个本地时间恰好横跨本地时区的UTC偏移更改(例如夏令时转换),则该偏移量将被包含在减法中,进而导致您得到错误的答案。

我建议自己进行解析,将小时、分钟和秒钟的值转换为int类型:

int h0, h1;
int m0, m1;
int s0, s1;

然后,您可以非常简单地将它们转换为适当的单位并进行加减操作:

auto d = (hours{h1} + minutes{m1} + seconds{s1})
       - (hours{h0} + minutes{m0} + seconds{s0});

d的类型是

在C++11中,您有几个选项用于解析,这是其中一种最简单的方法之一:

ss0 >> h0 >> c >> m0 >> c >> s0;
ss1 >> h1 >> c >> m1 >> c >> s1;

(其中c是要解析的char)

C++20中将会有一个std::chrono::parse函数,可以像这样使用:

seconds d;
ss0 >> parse("%H:%M:%S", d);

或者可以使用"%T"作为"%H:%M:%S"的快捷方式。我提到这一点是因为我知道你正在使用C++11,而不是C++20。但是有一个免费、开源的C++20 chrono预览版可用于C++11/14/17。对于此部分,您只需要头文件date.h,它是一个仅包含头文件的库。

#include "date/date.h"

// ...

seconds d;
ss0 >> date::parse("%T", d);

1
当然,流需要将其基数设置为10(幸运的是这是默认值),而不是0 /未设置,因为这些输入字符串通常包含前导零。 - Ben Voigt
1
同意。在我的回答中,假设ssoss1的类型和值与问题中相同。 - Howard Hinnant
谢谢你的回答。我正在尝试将一个格式为%H:%M:%S的字符串转换为chrono::duration。是否有直接的方法可以进行此转换? - afp_2008
1
我已更新我的回答,加入了一个免费、开源的只有头文件的库,可以帮你完成解析和加法运算。 - Howard Hinnant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接