]> git.ipfire.org Git - thirdparty/gcc.git/commit
libstdc++: Fix std::format output for std::chrono::zoned_time
authorJonathan Wakely <jwakely@redhat.com>
Fri, 26 Jul 2024 17:11:26 +0000 (18:11 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 30 Jul 2024 20:14:28 +0000 (21:14 +0100)
commit8f05ada7dfb9a40d4333a2aa9ccb5ddcdf8e2b06
tree7c26413c30662d43baadcd2380a9bc1bb8256c0b
parenta9e472c6b748abde55b5ecde2e2d98dcb2f96ded
libstdc++: Fix std::format output for std::chrono::zoned_time

When formatting a chrono::zoned_time with an empty chrono-specs, we were
only formatting its _M_time member, but the ostream insertion operator
uses the format "{:L%F %T %Z}" which includes the time zone
abbreviation. The %Z should also be used when formatting with an empty
chrono-specs.

This commit makes _M_format_to_ostream handle __local_time_fmt
specializations directly, rather than calling itself recursively to
format the _M_time member. We need to be able to customize the output of
_M_format_to_ostream for __local_time_fmt, because we use that type for
gps_time and tai_time as well as for zoned_time and __local_time_fmt.
When formatting gps_time and tai_time we don't want to include the time
zone abbreviation in the "{}" output, but for zoned_time we do want to.
We can reuse the __is_neg flag passed to _M_format_to_ostream (via
_M_format) to say that we want the time zone abbreviation.  Currently
the __is_neg flag is only used for duration specializations, so it's
available for __local_time_fmt to use.

In addition to fixing the zoned_time output to use %Z, this commit also
changes the __local_time_fmt output to use %Z. Previously it didn't use
it, just like zoned_time.  The standard doesn't actually say how to
format local-time-format-t for an empty chrono-specs, but this behaviour
seems sensible and is what I'm proposing as part of LWG 4124.

While testing this I noticed that some chrono types were not being
tested with empty chrono-specs, so this adds more tests. I also noticed
that std/time/clock/local/io.cc was testing tai_time instead of
local_time, which was completely wrong. That's fixed now too.

libstdc++-v3/ChangeLog:

* include/bits/chrono_io.h (__local_fmt_t): Remove unused
declaration.
(__formatter_chrono::_M_format_to_ostream): Add explicit
handling for specializations of __local_time_fmt, including the
time zone abbreviation in the output if __is_neg is true.
(formatter<chrono::tai_time<D>>::format): Add comment.
(formatter<chrono::gps_time<D>>::format): Likewise.
(formatter<chrono::__detail::__local_time_fmt::format): Call
_M_format with true for the __is_neg flag.
* testsuite/std/time/clock/gps/io.cc: Remove unused variable.
* testsuite/std/time/clock/local/io.cc: Fix test error that
checked tai_time instead of local_time. Add tests for
local-time-format-t formatting.
* testsuite/std/time/clock/system/io.cc: Check empty
chrono-specs.
* testsuite/std/time/clock/tai/io.cc: Likewise.
* testsuite/std/time/zoned_time/io.cc: Likewise.
libstdc++-v3/include/bits/chrono_io.h
libstdc++-v3/testsuite/std/time/clock/gps/io.cc
libstdc++-v3/testsuite/std/time/clock/local/io.cc
libstdc++-v3/testsuite/std/time/clock/system/io.cc
libstdc++-v3/testsuite/std/time/clock/tai/io.cc
libstdc++-v3/testsuite/std/time/zoned_time/io.cc