-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fail time parsing if input is insufficient to supply all fields #2523
Fail time parsing if input is insufficient to supply all fields #2523
Conversation
(and literals) of the format spec, even if it is sufficient to fully specify the parsable argument. For example "23:59" is not a valid input for "%H:%M:%S" (or for "%T"). https://eel.is/c++draft/time.parse#17.sentence-1 > If the from_stream overload fails to parse everything specified by > the format string, or if insufficient information is parsed to specify a > complete duration, time point, or calendrical data structure, > setstate(ios_base::failbit) is called on the basic_istream.
@HowardHinnant (or any interested party), if you have time, could you comment on an underlying issue here? MSVC STL follows libc++ and libstdc++ in setting #include <cassert>
#include <iomanip>
#include <sstream>
int main() {
std::tm t;
std::istringstream iss("2022");
iss >> std::get_time(&t, "%Y");
assert(iss.rdstate() == std::ios_base::eofbit);
return 0;
} Personally I find the Standard wording here a bit unclear ([locale.time.get.virtuals]/12: "When MSVC STL carries over this behavior for #include <cassert>
#include <date/date.h>
#include <sstream>
int main() {
date::year y;
std::istringstream iss("2022");
iss >> date::parse("%Y", y);
assert(iss.rdstate() == std::ios_base::goodbit);
return 0;
} Do you have any opinion about what the behavior here should be or if an LWG issue is needed? Thanks. FWIW, I like Date's behavior, even though it's inconsistent with |
I like date’s behavior as well, and for the same reason. %Y only looks for four digits and finds them. There’s no need for it to go poking around to see if there’s another character or not.
Contrast that with “%5Y” which does succeed, and does set eofbit because it does look for another digit and finds eof.
Howard
…On Feb 7, 2022, at 11:31 PM, Matt Stephanson ***@***.***> wrote:
@HowardHinnant (or any interested party), if you have time, could you comment on an underlying issue here?
MSVC STL follows libc++ and libstdc++ in setting eofbit in the following situation (godbolt):
#include <cassert>
#
include <iomanip>
#
include <sstream>
int main
() {
std::
tm
t;
std::istringstream
iss("2022"
);
iss >>
std::get_time(&t, "%Y"
);
assert(iss.rdstate
() == std::ios_base::eofbit);
return 0
;
}
Personally I find the Standard wording here a bit unclear ([locale.time.get.virtuals]/12: "When s == end evaluates to true after reading a character the function evaluates err |= ios_base::eofbit."), but these three implementations agree.
MSVC STL carries over this behavior for std::chrono::parse, because [time] doesn't mention eofbit anywhere. In contrast, your Date library does not set eofbit after an equivalent parse (godbolt):
#include <cassert>
#
include <date/date.h>
#
include <sstream>
int main
() {
date::year y;
std::istringstream
iss("2022"
);
iss >>
date::parse("%Y"
, y);
assert(iss.rdstate
() == std::ios_base::goodbit);
return 0
;
}
Do you have any opinion about what the behavior here should be or if an LWG issue is needed? Thanks.
FWIW, I like Date's behavior, even though it's inconsistent with get_time, because it's more consistent with the philosophy (as I understand it) that eofbit isn't set until we actually try to read after reaching the end. All the numeric chrono parse fields have a known width, either default or user-specified, so it makes sense to me that it should act more like string s; istringstream{"abcd"} >> setw(4) >> s;, which doesn't set eofbit.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you were mentioned.
|
@MattStephanson @HowardHinnant Thanks for the info - that does seem worthy of an LWG issue, especially if we want microsoft/STL, libstdc++, and libc++ to all change to follow Date's behavior. |
Co-authored-by: Matt Stephanson <68978048+MattStephanson@users.noreply.github.com>
Test for whitespace after other fields (explicit and shorthand) to ensure that we don't return early on EOF. Check exact rdstate flags to ensure that we set eofbit in addition to failbit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! I have just one small style nitpick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks great! Just a couple of minor style questions/issues.
Break out of loop after setting failbit | eofbit Test against goodbit instead of 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks correct to me.
I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Thanks for fixing this bug in one of C++20's biggest features, and congratulations on your first microsoft/STL commit! 😻 🎉 🚀 This is expected to ship in VS 2022 17.3 Preview 1. |
(and literals) of the format spec, even if it is sufficient to fully
specify the parsable argument.
For example "23:59" is not a valid input for "%H:%M:%S" (or for "%T").
https://eel.is/c++draft/time.parse#17.sentence-1