【问题标题】:std::get_time on Visual 2015 does not fail on incorrect dateVisual 2015 上的 std::get_time 在错误日期不会失败
【发布时间】:2017-08-31 08:22:48
【问题描述】:

我正在使用 Visual Studio 2015 在 Windows 上执行以下代码。基本上我使用 std::get_time 来解析日期,但是当日期无效时,例如大于 31 的一天,它似乎没有设置流上的失败位。

我已经在 Ubuntu 上使用 g++ 5.4.0 进行了尝试,它设置了失败位并打印“解析失败!”。这是 Windows 上的错误还是我做错了什么。

提前致谢!

std::string date = "2019-2-37 23:00:00"; // day (37) is wrong. 
std::string format = "%Y-%m-%d %H:%M:%S";
std::tm tm_object{};
std::istringstream input(date);        
input.imbue(std::locale(std::setlocale(LC_ALL, nullptr)));
input >> std::get_time(&tm_object, format.c_str());
if (input.fail()) 
{
    std::cout << "Parsing failed!";
}
else
{
    std::cout << "Parsing ok!\n";
    std::cout << "Day is : " << tm_object.tm_mday;
}

【问题讨论】:

    标签: c++ c++11 visual-c++ visual-studio-2015 std


    【解决方案1】:

    您可以在 Windows 上使用 Howard Hinnant's free, open-source header-only datetime library 来为您提供所需的行为。语法只是略有不同,而且更容易使用,并且与&lt;chrono&gt; 兼容。它也比 C++ 标准的时间解析部分有更好的文档和说明。

    #include "date.h"
    #include <iostream>
    #include <sstream>
    #include <string>
    
    int
    main()
    {
        std::string date = "2019-2-37 23:00:00"; // day (37) is wrong. 
        std::string format = "%Y-%m-%d %H:%M:%S";
        date::sys_seconds tm_object{};
        std::istringstream input(date);        
        input >> date::parse(format, tm_object);
        if (input.fail()) 
        {
            std::cout << "Parsing failed!";
        }
        else
        {
            std::cout << "Parsing ok!\n";
            date::year_month_day ymd = date::floor<date::days>(tm_object);
            std::cout << "Day is : " << ymd.day();
        }
    }
    

    输出:

    Parsing failed!
    

    这个库也适用于 g++ 5.4.0 和 clang。

    您还可以将format 简化为"%F %T",如果需要,它还可以达到亚秒级精度。

    【讨论】:

    • 感谢您的回答霍华德,您的图书馆为我工作!无论如何,我仍然不明白为什么 Windows 没有 strptime 函数,或者为什么 std::get_time 不能验证 Visual 2015 上的日期是否正确。
    • @rboc:很高兴它对你有用! strptime 不是标准 C++,而是由 POSIX 指定的。尽管std::get_time 是根据strptime 指定的。 POSIX 关于strptime 的说法是:“没有定义错误。” (pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html)
    • 是的,但至少 strptime 在未成功完成时(2 月 37 日)返回一个空指针。我希望 std::get_time 在 Visual Studio 2015 上做类似的事情。
    • @rboc:我正在努力使我的库标准化。我将尝试将更精确的规范纳入标准。
    【解决方案2】:

    欢迎来到标准灰色地带的世界! std::get_time(各种重载)在标准的第 22 章本地化库和第 27 章输入/输出库中指定。

    AFAIK,标准要求:

    • 如果输入字符串以有效格式正确描述了有效日期,则相应地填充 std::tm 对象
    • 如果输入字符串无法解析,则设置输入字符串的失败位

    但是在这里,输入字符串可以被解析,并且一些实现可以假设 March 32 只是 4 月 1 日。换句话说,标准未指定实现对输入值的控制。非数字日期会报错,但这取决于实现。

    【讨论】:

    • 我认为应该在 2 月 37 日设置失败位。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 2015-11-08
    • 2016-05-04
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多