Fail if you need a valid year and don't parse one.

This commit is contained in:
Howard Hinnant 2017-05-20 23:04:49 -04:00
parent 83c8b4d522
commit 0fb3921e5b
3 changed files with 17 additions and 8 deletions

15
date.h
View File

@ -1403,14 +1403,21 @@ year::is_leap() const NOEXCEPT
} }
CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
CONSTCD11 inline bool year::ok() const NOEXCEPT {return true;}
CONSTCD11
inline
bool
year::ok() const NOEXCEPT
{
return y_ != std::numeric_limits<short>::min();
}
CONSTCD11 CONSTCD11
inline inline
year year
year::min() NOEXCEPT year::min() NOEXCEPT
{ {
return year{std::numeric_limits<short>::min()}; return year{std::numeric_limits<short>::min()+1};
} }
CONSTCD11 CONSTCD11
@ -5458,7 +5465,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
const CharT* command = nullptr; const CharT* command = nullptr;
auto modified = CharT{}; auto modified = CharT{};
auto width = -1; auto width = -1;
CONSTDATA int not_a_year = 33000; CONSTDATA int not_a_year = numeric_limits<short>::min();
int Y = not_a_year; int Y = not_a_year;
CONSTDATA int not_a_century = not_a_year / 100; CONSTDATA int not_a_century = not_a_year / 100;
int C = not_a_century; int C = not_a_century;
@ -6377,6 +6384,8 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year& y,
using CT = seconds; using CT = seconds;
fields<CT> fds{}; fields<CT> fds{};
from_stream(is, fmt, fds, abbrev, offset); from_stream(is, fmt, fds, abbrev, offset);
if (!fds.ymd.year().ok())
is.setstate(ios::failbit);
if (!is.fail()) if (!is.fail())
y = fds.ymd.year(); y = fds.ymd.year();
} }

View File

@ -41,7 +41,7 @@ main()
using namespace std::chrono; using namespace std::chrono;
std::ostringstream os; std::ostringstream os;
os << format("%F %T", sys_days{jan/1/year::min()}); os << format("%F %T", sys_days{jan/1/year::min()});
assert(os.str() == "-32768-01-01 00:00:00"); assert(os.str() == "-32767-01-01 00:00:00");
os.str(""); os.str("");
os << format("%F %T", sys_days{dec/last/year::max()}); os << format("%F %T", sys_days{dec/last/year::max()});
assert(os.str() == "32767-12-31 00:00:00"); assert(os.str() == "32767-12-31 00:00:00");
@ -52,7 +52,7 @@ main()
os.str(""); os.str("");
os << format("%Y-%m-%d %H:%M:%S", sys_days{jan/1/year::min()}); os << format("%Y-%m-%d %H:%M:%S", sys_days{jan/1/year::min()});
assert(os.str() == "-32768-01-01 00:00:00"); assert(os.str() == "-32767-01-01 00:00:00");
os.str(""); os.str("");
os << format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()}); os << format("%Y-%m-%d %H:%M:%S", sys_days{dec/last/year::max()});
assert(os.str() == "32767-12-31 00:00:00"); assert(os.str() == "32767-12-31 00:00:00");
@ -63,14 +63,14 @@ main()
os.str(""); os.str("");
os << format("%F %T", sys_days{jan/1/year::min()} + microfortnights{1}); os << format("%F %T", sys_days{jan/1/year::min()} + microfortnights{1});
assert(os.str() == "-32768-01-01 00:00:01.2096"); assert(os.str() == "-32767-01-01 00:00:01.2096");
os.str(""); os.str("");
os << format("%F %T", sys_days{dec/last/year::max()} + microfortnights{1}); os << format("%F %T", sys_days{dec/last/year::max()} + microfortnights{1});
assert(os.str() == "32767-12-31 00:00:01.2096"); assert(os.str() == "32767-12-31 00:00:01.2096");
os.str(""); os.str("");
os << format("%F %T", jan/1/year::min()); os << format("%F %T", jan/1/year::min());
assert(os.str() == "-32768-01-01 00:00:00"); assert(os.str() == "-32767-01-01 00:00:00");
os.str(""); os.str("");
os << format("%F %T", dec/last/year::max()); os << format("%F %T", dec/last/year::max());
assert(os.str() == "32767-12-31 00:00:00"); assert(os.str() == "32767-12-31 00:00:00");

View File

@ -117,5 +117,5 @@ main()
os.str(""); os.str("");
os << format("%y", sys_days{jun/1/year::min()}); os << format("%y", sys_days{jun/1/year::min()});
assert(os.str() == "68"); assert(os.str() == "67");
} }