%I%p should parse/format duration since midnight
Howard Hinnant

Created on 2019-09-02.00:00:00 last changed 31 months ago


Date: 2019-10-07.02:21:30

Proposed resolution:

This wording is relative to N4830.

  1. Modify [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 weekdayend 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 [time.parse] as indicated:

    [Drafting note: The modification of [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 ([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 weekdayend 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.

Date: 2019-10-07.02:21:30

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

Date: 2019-09-02.00:00:00

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';


2019-08-10 02PM
2019-08-10 14:00:00.000000
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2019-11-19 14:48:30adminsetstatus: voting -> wp
2019-10-07 02:48:00adminsetstatus: ready -> voting
2019-10-07 02:21:30adminsetmessages: + msg10679
2019-10-07 02:21:30adminsetstatus: new -> ready
2019-09-14 11:32:28adminsetmessages: + msg10605
2019-09-02 00:00:00admincreate