Allow %j to parse and format durations

This commit is contained in:
Howard Hinnant
2018-09-26 13:55:37 -07:00
parent 69e9cd612f
commit 591f572b67

View File

@@ -5034,11 +5034,19 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
if (modified == CharT{}) if (modified == CharT{})
{ {
if (!fds.ymd.ok()) if (fds.ymd.ok() || fds.has_tod)
os.setstate(std::ios::failbit); {
days doy;
if (fds.ymd.ok())
{
auto ld = local_days(fds.ymd); auto ld = local_days(fds.ymd);
auto y = fds.ymd.year(); auto y = fds.ymd.year();
auto doy = ld - local_days(y/January/1) + days{1}; doy = ld - local_days(y/January/1) + days{1};
}
else
{
doy = duration_cast<days>(fds.tod.to_duration());
}
save_ostream<CharT, Traits> _(os); save_ostream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
@@ -5046,6 +5054,11 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
os << doy.count(); os << doy.count();
} }
else else
{
os.setstate(std::ios::failbit);
}
}
else
{ {
os << CharT{'%'} << modified << *fmt; os << CharT{'%'} << modified << *fmt;
modified = CharT{}; modified = CharT{};
@@ -6150,7 +6163,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
CONSTDATA int not_a_hour_12_value = 0; CONSTDATA int not_a_hour_12_value = 0;
CONSTDATA int not_a_minute = not_a_hour; CONSTDATA int not_a_minute = not_a_hour;
CONSTDATA Duration not_a_second = Duration::min(); CONSTDATA Duration not_a_second = Duration::min();
CONSTDATA int not_a_doy = 0; CONSTDATA int not_a_doy = -1;
CONSTDATA int not_a_weekday = 8; CONSTDATA int not_a_weekday = 8;
CONSTDATA int not_a_week_num = 100; CONSTDATA int not_a_week_num = 100;
CONSTDATA int not_a_ampm = -1; CONSTDATA int not_a_ampm = -1;
@@ -7317,7 +7330,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
goto broken; goto broken;
computed = true; computed = true;
} }
if (j != 0 && Y != not_a_year) if (j != not_a_doy && Y != not_a_year)
{ {
auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}}; auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}};
if (m == 0) if (m == 0)
@@ -7328,6 +7341,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
d = static_cast<int>(static_cast<unsigned>(ymd_trial.day())); d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
else if (day(static_cast<unsigned>(d)) != ymd_trial.day()) else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
goto broken; goto broken;
j = not_a_doy;
} }
auto ymd = year{Y}/m/d; auto ymd = year{Y}/m/d;
if (ymd.ok()) if (ymd.ok())
@@ -7426,6 +7440,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
fds.has_tod = true; fds.has_tod = true;
fds.tod.s_ = detail::decimal_format_seconds<Duration>{s}; fds.tod.s_ = detail::decimal_format_seconds<Duration>{s};
} }
if (j != not_a_doy)
{
fds.has_tod = true;
fds.tod.h_ += hours{days{j}};
}
if (wd != not_a_weekday) if (wd != not_a_weekday)
fds.wd = weekday{static_cast<unsigned>(wd)}; fds.wd = weekday{static_cast<unsigned>(wd)};
if (abbrev != nullptr) if (abbrev != nullptr)