2017-04-05 81 views
2

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

我在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; 
} 

回答

2

您可以在Windows上使用Howard Hinnant's free, open-source header-only datetime library为您提供所需的行为。语法略有不同,使用起来也更容易,并且与<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和铛。

您还可以将您的format简化为"%F %T",并且如果需要也可以使用亚秒级精度。

+0

感谢您的回答霍华德,您的图书馆为我工作! 无论如何,我仍然不明白为什么没有Windows的strptime函数或为什么std :: get_time没有验证日期在Visual 2015上是正确的。 – rboc

+0

@rboc:很高兴为您效劳! 'strptime'不是标准的C++,而是由POSIX指定的。虽然'std :: get_time'是根据'strptime'指定的。 POSIX对'strptime'这样说:“没有错误被定义。” (http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html) –

+0

是的,但至少strptime会在未完成(2月37日)时返回空指针。我期望std :: get_time在Visual Studio 2015上做类似的事情。 – rboc

2

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

AFAIK,该标准要求:

  • 如果输入的字符串正确地描述了在有效格式的有效日期,std::tm对象相应地填充
  • 如果输入的字符串不能被解析,故障位上应该设置输入字符串

但是在这里,输入字符串可以被解析,并且一些实现可以假设行军32只是四月1.不同地说,标准没有规定什么控制工具应对输入值进行处理。一个非数字的日子应该给出一个错误,但这是依赖于实现的。

+1

我以为2月37日它应该设置失败位。 :-) – rboc