This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3262. Formatting of negative durations is not specified

Section: 27.12 [time.format] Status: C++20 Submitter: Tomasz Kamiński Opened: 2019-08-18 Last modified: 2021-02-25

Priority: 2

View all other issues in [time.format].

View all issues with C++20 status.

Discussion:

The current specification of the formatting for `std::chrono::duration` and `std::hh_mm_ss` types is unclear in regards the the handling of negative values. To illustrate:

>     std::cout << std::format("%H:%M:%S", -10'000s); // prints either -02:46:40 or -02:-46:-40

The indented behavior (and currently implemented, see here) is to apply the sign once, before the leftmost converted field.

[2019-09-14 Priority set to 2 based on reflector discussion]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4830.

> > [Drafting note: With the above clarification, the specification of the `operator<<` for `hh_mm_ss` may be simplified to `format("{:%T}", hms)`.]

> 1. Modify 27.12 [time.format] as indicated:

>    > -2- Each conversion specifier conversion-spec is replaced by appropriate characters as described in Table [tab:time.format.spec]. Some of the conversion specifiers depend on the locale that is passed to the formatting function if the latter takes one, or the global locale otherwise. If the formatted object does not contain the information the conversion specifier refers to, an exception of type `format_error` is thrown.

>    > -?- The result of formatting a `std::chrono::duration` instance holding a negative value, or of an `hh_mm_ss` object `h` for which `h.is_negative()` is `true`, is equivalent to the output of the corresponding positive value, with a `-` character placed before the replacement of the leftmost conversion specifier.

>    > [Example:

>    > >     cout << format("%T", -10'000s); // prints: -02:46:40
>    > >     cout << format("%H:%M:%S", -10'000s); // prints: -02:46:40
>    > >     cout << format("minutes %M, hours %H, seconds %S", -10'000s); // prints: minutes -46, hours 02, seconds 40

>    > — end example]

>    > -3- Unless explicitly requested, […]

> 2. Modify 27.9.3 [time.hms.nonmembers] as indicated:

>    >     template<class charT, class traits, class Duration>
>    >     basic_ostream<charT, traits>&
>    >     operator<<(basic_ostream<charT, traits>& os, const hh_mm_ss<Duration>& hms);

>    > > -1- Effects: Equivalent to:

>    > > >     return os << format(os.getloc(),
>    > > >                  hms.is_negative() ? STATICALLY-WIDEN<charT>("-{:%T}")
>    > > >                                    : STATICALLY-WIDEN<charT>("{:%T}"),
>    > > >                  abs(hms.to_duration()));

[2019-09-14; Howard improves wording]

[2020-02; Status set to Immediate after LWG discussion Thursday in Prague. (Minor example wording cleanup)]

Proposed resolution:

This wording is relative to N4830.

> [Drafting note: With the above clarification, the specification of the `operator<<` for `hh_mm_ss` may be simplified to `format("{:%T}", hms)`.]

1. Modify 27.12 [time.format] as indicated:

   > -2- Each conversion specifier conversion-spec is replaced by appropriate characters as described in Table [tab:time.format.spec]. Some of the conversion specifiers depend on the locale that is passed to the formatting function if the latter takes one, or the global locale otherwise. If the formatted object does not contain the information the conversion specifier refers to, an exception of type `format_error` is thrown.

   > -?- The result of formatting a `std::chrono::duration` instance holding a negative value, or of an `hh_mm_ss` object `h` for which `h.is_negative()` is `true`, is equivalent to the output of the corresponding positive value, with a `STATICALLY-WIDEN<charT>("-")` character sequence placed before the replacement of the leftmost conversion specifier.

   > [Example:

   > >     cout << format("{%:T}", -10'000s); // prints: -02:46:40
   > >     cout << format("{:%H:%M:%S}", -10'000s); // prints: -02:46:40
   > >     cout << format("{:minutes %M, hours %H, seconds %S}", -10'000s); // prints: minutes -46, hours 02, seconds 40

   > — end example]

   > -3- Unless explicitly requested, […]

2. Modify 27.9.3 [time.hms.nonmembers] as indicated:

   >     template<class charT, class traits, class Duration>
   >     basic_ostream<charT, traits>&
   >     operator<<(basic_ostream<charT, traits>& os, const hh_mm_ss<Duration>& hms);

   > > -1- Effects: Equivalent to:

   > > >     return os << format(os.getloc(),
   > > >                  hms.is_negative() ? STATICALLY-WIDEN<charT>("-{:%T}")
   > > >                                    : STATICALLY-WIDEN<charT>("{:%T}"),
   > > >                  abs(hms.to_duration()));