C ++标准库,支持时间算术

时间:2017-07-29 17:33:28

标签: c++ datetime time

我有很多以“HH:MM”形式的字符串,我经常不得不对它们进行算术运算(例如加5分钟,加24小时等)。

我想知道标准库中是否有任何内置类可以处理这样的算术而不必手动更改字符串并处理极端情况?

3 个答案:

答案 0 :(得分:3)

如果您没有strptime可用,如果您有<chrono>并且不想使用C API,则可以使用Howard Hinnant's free, open-source, portable datetime library编写帮助以转换为std::chrono::minutes。{/ p>

因此,从字符串转换为分钟,执行您需要的任何计算,然后转换回字符串:

#include "date.h"
#include <iostream>
#include <string>
#include <sstream>

std::chrono::minutes
to_minutes(const std::string& s)
{
    std::istringstream in{s};
    in.exceptions(std::ios::failbit);
    std::chrono::minutes m;
    in >> date::parse("%H:%M", m);
    return m;
}

std::string
to_string(std::chrono::minutes m)
{
    return date::format("%H:%M", m);
}

int
main()
{
    using namespace std::chrono_literals;
    std::cout << to_string(to_minutes("5:47") + 2h + 168min) << '\n';
}

输出:

10:35

此库已移植到最新版本的VS,gcc和clang。

您还可以使用此库非常无缝地处理不同的精度,例如几秒甚至几毫秒,甚至可以混合所需的所有精度:

std::chrono::milliseconds
to_milliseconds(const std::string& s)
{
    std::istringstream in{s};
    in.exceptions(std::ios::failbit);
    std::chrono::milliseconds ms;
    in >> date::parse("%T", ms);
    return ms;
}

std::string
to_string(std::chrono::milliseconds ms)
{
    return date::format("%T", ms);
}

// ...

    std::cout << to_string(to_minutes("5:47") + 2h + 168min +
                           122s + 465ms + to_milliseconds("1:23:02.123")) << '\n';

输出:

12:00:04.588

答案 1 :(得分:2)

使用<ctime>您可以将HH:MM字符串转换为struct tm,如下所示:

struct tm time_components;
memset(&time_components, 0, sizeof(struct tm));
time_components.tm_year = 2017;
strptime("01:45", "%H:%M", &time_components);

这假设您有strptime可用。如果没有,请使用sscanf或类似内容来提取您的小时和分钟组件 - 我们确定您已经这样做了。我在那里设置tm_year,因为否则它为零,这不是以后转换为time_t的有效年份。

我们可以使用tm轻松地将strftime结构转换回HH:MM字符串。

char buf[6];
strftime(buf, 6, "%H:%M", &time_components);

printf("time_components before manipulation: %s\n", buf);

但操纵它怎么样?我的第一个想法是“只需转换为time_t并加上/减去你想要的许多秒”。但time_t并不能保证在几秒钟内完成,所以不要这样做。相反,将您喜欢的任意分钟数添加到tm_min结构的tm组件中,然后使用它调用mktime,这将正确处理超出正常时间范围的任何值/分钟/秒。此时您有time_t,我们不想搞砸,所以只需使用tm返回转换为localtimelocaltime将镜像mktime中发生的转化,因此您不必担心时区等问题。现在,您已基本规范化tm结构,并且您的溢出分钟已转换为小时数,并且您的溢出时间已转换为天数。

time_components.tm_min += 65; // Add 65 minutes. Negative values work as expected too!
time_t temp_time = mktime(&time_components);
struct tm* adjusted_time = localtime(&temp_time);
strftime(buf, 6, "%H:%M", adjusted_time);
printf("adjusted_time: %s\n", buf);

adjusted_time指针似乎指向内部tm结构,该结构将在对mktimegmtime,FYI的任何后续调用中发生更改。

毫无疑问,这是一种相当地狱般的方法。如果您只需要处理分钟/小时溢出和简单的算术运算,我就会想要自己动手或者寻找其他地方。

答案 2 :(得分:1)

http://en.cppreference.com/w/cpp/chrono/duration支持你想要的算术和类型,但我认为你不能用字符串构造。

但是你可以使用Boost Chrono。在大多数情况下,我倾向于喜欢它,因为如果我处理的是小时和分钟的问题,我可能会在将来处理日期。