问题
I'm executing the following code on Windows with Visual Studio 2015. Basically I use std::get_time
to parse a date, but when the date is invalid, for example, a day greater than 31, it does not seem to set the fail bit on the stream.
I have tried this on Ubuntu with g++ 5.4.0 and it sets the fail bit and prints "Parsing failed!". Is this a bug on Windows or am I doing something wrong.
Thanks in advance!
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;
}
回答1:
You can use Howard Hinnant's free, open-source header-only datetime library on Windows to give you the desired behavior. The syntax is only slightly different, and it is much easier to use, and compatible with <chrono>
. It is also better documented and specified than the time-parsing parts of the C++ standard.
#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();
}
}
Output:
Parsing failed!
This library also works with g++ 5.4.0 and clang.
You can also simplify your format
down to "%F %T"
, and it can also work with subsecond precision if desired.
回答2:
Welcome to the world of the grey zone of the standard! std::get_time
(various overloads) is specified in chapters 22 Localization library, and 27 Input/output library of the standard.
AFAIK, the standard requires:
- if the input string correctly describes a valid date in valid format, the
std::tm
object is populated accordingly - if the input string cannot be parsed, the fail bit on the input string shall be set
But here, the input string can be parsed, and some implementations can assume that the march 32 is just the april 1. Said differently it is unspecified by standard what controls an implementation shall do on the input value. A non numeric day shall give an error, but this is implementation dependant.
来源:https://stackoverflow.com/questions/43235953/stdget-time-on-visual-2015-does-not-fail-on-incorrect-date