Visual 2015 上的 std::get_time 不会在错误的日期失败

std::get_time on Visual 2015 does not fail on incorrect date

本文关键字:错误 失败 日期 time 上的 2015 std get Visual      更新时间:2023-10-16

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

我已经使用 g++ 5.4.0 在 Ubuntu 上尝试过这个,它设置了失败位并打印"解析失败!这是 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;
}

您可以在 Windows 上使用 Howard Hinnant 的免费、仅限标头的日期时间库来为您提供所需的行为。 语法只是略有不同,并且更容易使用,并且与<chrono>兼容。 它也比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" ,如果需要,它也可以以亚秒级精度工作。

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

AFAIK,该标准要求:

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

但在这里,可以解析输入字符串,并且某些实现可以假定 3 月 32 日只是 4 月 1 日。换句话说,标准没有指定实现对输入值的控制。非数字日期将给出错误,但这取决于实现。

相关文章: