gcc 6.3和clang 4.0中的std :: get_time()不适用于完整的月份名称

时间:2017-07-28 07:37:53

标签: c++ date gcc clang

我想用std::get_time()解析日期字符串,但似乎代码适用于VC ++ 2015,但不适用于gcc 6.3和clang 4.0。这是MCVE:

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>

int main() {

    std::string line = "February 4 1993 15:21";

    std::tm date_1 = {};

    std::stringstream ss(line);

    ss >> std::get_time(&date_1, "%b %d %Y %H:%M");

    if(ss.fail())
    {
        std::cout << "parse failed\n";
    }

    std::cout << date_1.tm_year << "\n";
    std::cout << date_1.tm_mon << "\n";
    std::cout << date_1.tm_mday << "\n";
    std::cout << date_1.tm_hour << "\n";
    std::cout << date_1.tm_min << "\n";

    return 0;
}

这是VC ++ 2015的结果:

93
1
4
15
21

以下是gcc 6.3.2和clang 4.0的结果(我在ideone.comColiru上使用了编译器) - 有和没有c ++ 14标志:

parse failed
0
1
0
0
0

当我使用缩写的月份名称时,它会起作用,例如2月,8月等。

我尝试在stringstreamen_USen_GB + UTF-8版本)上设置不同的区域设置,但它们没有任何区别或导致运行时错误。我尝试过改变分隔符,但也没有区别。

我已在CPP Reference上读到std::get_time()中的%b:

  

解析月份名称,完整或缩写,例如辛

这是gcc和clang中的错误/缺失功能还是编译器,与上面的内容相反,根据实现可以自由处理缩写名称?标准对此有何看法?这两个编译器在这里表现出相同的行为是巧合吗?

1 个答案:

答案 0 :(得分:2)

如评论中所述,这是一个libstdc ++错误。然而,没有注意到如何解决它。

使用%B代替%b,libstdc ++将进行解析。对于解析,%B%b应具有相同的行为。但是对于格式化,%B输出语言环境的完整月份名称,而%b格式化缩写的月份名称。

最后,您可能对Howard Hinnant's free, open-source date-time library感兴趣,它允许您直接解析<chrono>个时间点和持续时间:

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

int
main()
{
    using namespace date;
    using namespace std::chrono;
    std::istringstream in{"February 4 1993 15:21"};
    sys_time<minutes> tp;
    in >> parse("%B %d %Y %H:%M", tp);
    if (in.fail())
        return 1;
    std::cout << tp << '\n';
}

输出:

1993-02-04 15:21

在上面的示例中,sys_time<minutes>std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>的类型别名。