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.

### 3272. `%I%p` should parse/format `duration` since midnight

Section: 29.12 [time.format], 29.13 [time.parse] Status: C++20 Submitter: Howard Hinnant Opened: 2019-09-02 Last modified: 2021-02-25

Priority: 0

View other active issues in [time.format].

View all other issues in [time.format].

View all issues with C++20 status.

Discussion:

It is clear how `"%I%p"` parses and formats time points. What is not clear is how these flags interact with durations. We should treat durations as "elapsed time since midnight". For example:

>     #include <chrono>
>     #include <iostream>
>     #include <string>
>     #include <sstream>

>     int main()
>     {
>       using namespace std;
>       using namespace std::chrono;
>       // Format
>       {
>         // format time_point with %I%p
>         cout << format("{:%F %I%p}", sys_days{2019_y/August/10}+14h) << '\n';
>       }
>       {
>         // format duration with %I%p
>         cout << format("{:%I%p}", 14h) << '\n';
>       }

>       // Parse
>       {
>         // Parse %I%p as day-of-year combined with an hour into a time_point
>         istringstream in{"2019-08-10 2pm"};
>         system_clock::time_point tp;
>         in >> parse("%F %I%p", tp);
>         cout << tp << '\n';
>       }
>       {
>         // Parse %I%p as number of hours into a duration
>         istringstream in{"2pm"};
>         hours d;
>         in >> parse("%I%p", d);
>         cout << d << '\n';
>       }
>     }

Output:

>     2019-08-10 02PM
>     02PM
>     2019-08-10 14:00:00.000000
>     14h

[2019-10 Status set to 'Tentatively Ready' after reflector discussion]

Proposed resolution:

This wording is relative to N4830.

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

   > -3- Unless explicitly requested, the result of formatting a chrono type does not contain time zone abbreviation and time zone offset information. If the information is available, the conversion specifiers `%Z` and `%z` will format this information (respectively). [Note: If the information is not available and a `%Z` or `%z` conversion specifier appears in the chrono-format-spec, an exception of type `format_error` is thrown, as described above. — end note]

   > -?- If the type being formatted does not contain the information that the format flag needs, an exception of type `format_error` is thrown. [Example: A `duration` does not contain enough information to format as a `weekday` — end example]. However if a flag refers to a "time of day" (e.g. `%H`, `%I`, `%p`, etc.), then a specialization of `duration` is interpreted as the time of day elapsed since midnight.

2. Modify 29.13 [time.parse] as indicated:

   > [Drafting note: The modification of 29.13 [time.parse] p1 is intended to be non-conflictingly mergeable with the change suggested by LWG 3269 and LWG 3271 at the same paragraph.]

   > -1- Each parse overload specified in this subclause calls `from_stream` unqualified, so as to enable argument dependent lookup (6.5.4 [basic.lookup.argdep]). In the following paragraphs, let `is` denote an object of type `basic_istream<charT, traits>`, where `charT` and `traits` are template parameters in that context.

   > […]

   > -10- All `from_stream` overloads behave as unformatted input functions, except that they have an unspecified effect on the value returned by subsequent calls to `basic_istream<>::gcount()`. Each overload takes a format string containing ordinary characters and flags which have special meaning. Each flag begins with a `%`. Some flags can be modified by `E` or `O`. During parsing each flag interprets characters as parts of date and time types according to Table [tab:time.parse.spec]. Some flags can be modified by a width parameter given as a positive decimal integer called out as `N` below which governs how many characters are parsed from the stream in interpreting the flag. All characters in the format string that are not represented in Table [tab:time.parse.spec], except for white space, are parsed unchanged from the stream. A white space character matches zero or more white space characters in the input stream.

   > -?- If the type being parsed can not represent the information that the format flag refers to, `is.setstate(ios_base::failbit)` is called. [Example: A `duration` cannot represent a `weekday` — end example]. However if a flag refers to a "time of day" (e.g. `%H`, `%I`, `%p`, etc.), then a specialization of `duration` is parsed as the time of day elapsed since midnight.