[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 Jonathan Wakely changed: What|Removed |Added Target Milestone|--- |13.3 --- Comment #7 from Jonathan Wakely --- Fixed on trunk so far.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #6 from GCC Commits --- The master branch has been updated by Jonathan Wakely : https://gcc.gnu.org/g:5f9d7a5b6cf64639274e63051caf70fbc8418ea2 commit r14-9376-g5f9d7a5b6cf64639274e63051caf70fbc8418ea2 Author: Jonathan Wakely Date: Thu Mar 7 13:15:41 2024 + libstdc++: Fix parsing of fractional seconds [PR114244] When converting a chrono::duration to a result type with an integer representation we should use chrono::round<_Duration> so that we don't truncate towards zero. Rounding ensures that e.g. 0.001999s becomes 2ms not 1ms. We can also remove some redundant uses of chrono::duration_cast to convert from seconds to _Duration, because the _Parser class template requires _Duration type to be able to represent seconds without loss of precision. This also fixes a bug where no fractional part would be parsed for chrono::duration because its period is ratio<1>. We should also consider treat_as_floating_point when deciding whether to skip reading a fractional part. libstdc++-v3/ChangeLog: PR libstdc++/114244 * include/bits/chrono_io.h (_Parser::operator()): Remove redundant uses of duration_cast. Use chrono::round to convert long double value to durations with integer representations. Check represenation type when deciding whether to skip parsing fractional seconds. * testsuite/20_util/duration/114244.cc: New test. * testsuite/20_util/duration/io.cc: Check that a floating-point duration with ratio<1> precision can be parsed.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #5 from Jonathan Wakely --- Yup, that's what I have in my local tree now.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #4 from Howard Hinnant --- Not positive (because I don't know your code that well), but I think: __s = round<_Duration>(__fs); will do it.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #3 from Jonathan Wakely --- (In reply to Jonathan Wakely from comment #1) > Yup, the seconds part "00.002" is parsed using std::numpunct (in order to Oops, std::num_get obviously. > handle the locale's decimal point) and then converted to milliseconds using > duration_cast: > > auto& __ng = use_facet>(__loc); > long double __val; > ios_base::iostate __err2{}; > __ng.get(__buf, {}, __buf, __err2, __val); > if (__is_failed(__err2)) [[unlikely]] > __err |= __err2; > else > { > duration __fs(__val); > __s = duration_cast<_Duration>(__fs); > } As an unrelated optimization, when the locale is "C" we could use std::from_chars or std::stod instead of std::num_get.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #2 from Jonathan Wakely --- (In reply to Jonathan Wakely from comment #1) > and another duration_cast in chrono::from_stream for durations. That one > could be used with either integral or floating-point reps. Ah, but we're converting from common_type_t to Duration, so either it's float-to-float or integer-to-integer, and duration_cast is OK if we're fine with truncating.
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 --- Comment #1 from Jonathan Wakely --- Yup, the seconds part "00.002" is parsed using std::numpunct (in order to handle the locale's decimal point) and then converted to milliseconds using duration_cast: auto& __ng = use_facet>(__loc); long double __val; ios_base::iostate __err2{}; __ng.get(__buf, {}, __buf, __err2, __val); if (__is_failed(__err2)) [[unlikely]] __err |= __err2; else { duration __fs(__val); __s = duration_cast<_Duration>(__fs); } We also use duration_cast when parsing %c and %X using std::time_get, but that's an integer conversion there (but the duration_cast should have been qualified to prevent ADL): __h = hours(__tm.tm_hour); __min = minutes(__tm.tm_min); __s = duration_cast<_Duration>(seconds(__tm.tm_sec)); and another duration_cast in chrono::from_stream for durations. That one could be used with either integral or floating-point reps. Do we want to parse "00:00:31" as minutes(1)? I don't think we do, so only the first case where converting long double to milliseconds should be rounded?
[Bug libstdc++/114244] Need to use round when parsing fractional seconds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114244 Jonathan Wakely changed: What|Removed |Added Ever confirmed|0 |1 Status|UNCONFIRMED |ASSIGNED Assignee|unassigned at gcc dot gnu.org |redi at gcc dot gnu.org Last reconfirmed||2024-03-05