This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
zoned_time with resolution coarser than secondsSection: 30.12 [time.format] Status: WP Submitter: Jonathan Wakely Opened: 2024-07-26 Last modified: 2024-11-28
Priority: Not Prioritized
View other active issues in [time.format].
View all other issues in [time.format].
View all issues with WP status.
Discussion:
The
std::formatter<std::chrono::zoned_time<Duration, TimeZonePtr>>
specialization calls tp.get_local_time() for the object it passes to its
base class' format function. But get_local_time() does not return a
local_time<Duration>, it returns
local_time<common_type_t<Duration, seconds>>.
The base class' format function is only defined for
local_time<Duration>.
That means this is ill-formed, even though the static assert passes:
using namespace std::chrono;
static_assert( std::formattable<zoned_time<minutes>, char> );
zoned_time<minutes> zt;
(void) std::format("{}", zt); // error: cannot convert local_time<seconds> to local_time<minutes>
Additionally, it's not specified what output you should get for:
std::format("{}", local_time_format(zt.get_local_time()));
30.12 [time.format] p7 says it's formatted as if by streaming to an
ostringstream,
but there is no operator<< for local-time-format-t.
Presumably it should give the same result as operator<< for
a zoned_time, i.e. "{:L%F %T %Z}" with padding adjustments etc.
The proposed resolution below has been implemented in libstdc++.
[2024-08-02; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
[Wrocław 2024-11-23; Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4986.
Modify 30.12 [time.format] as indicated:
template<classDuration, class charT> struct formatter<chrono::local-time-format-t<Duration>, charT>;-17- Let
fbe alocale-time-format-t<Duration>object passed toformatter::format.-18- Remarks: If the chrono-specs is omitted, the result is equivalent to using
%F %T %Zas the chrono-specs. If%Zis used, it is replaced with*f.abbreviff.abbrevis not a null pointer value. If%Zis used andf.abbrevis a null pointer value, an exception of typeformat_erroris thrown. If%z(or a modified variant of%z) is used, it is formatted with the value of*f.offset_seciff.offset_secis not a null pointer value. If%z(or a modified variant of%z) is used andf.offset_secis a null pointer value, then an exception of typeformat_erroris thrown.template<class Duration, class TimeZonePtr, class charT> struct formatter<chrono::zoned_time<Duration, TimeZonePtr>, charT> : formatter<chrono::local-time-format-t<common_type_t<Duration, seconds>>, charT> { template<class FormatContext> typename FormatContext::iterator format(const chrono::zoned_time<Duration, TimeZonePtr>& tp, FormatContext& ctx) const; };template<class FormatContext> typename FormatContext::iterator format(const chrono::zoned_time<Duration, TimeZonePtr>& tp, FormatContext& ctx) const;-19- Effects: Equivalent to:
sys_info info = tp.get_info(); return formatter<chrono::local-time-format-t<common_type_t<Duration, seconds>>, charT>:: format({tp.get_local_time(), &info.abbrev, &info.offset}, ctx);