R3:
weekday(unsigned) constructor to not use the word "stores."
hh_mm_ss(Duration) constructor to not use the word "stores."
hh_mm_ss
constructor Effects clause..
noexcept from hh_mm_ss constructor.
hh_mm_ss, allow
subseconds to be based on a non-positive power of 10.
__cpp_lib_chrono.
weekday to
unsigned in specification.
floor to duration_cast in the
Ensures: clause of the hh_mm_ss constructor.
make12 and make24 to use
const hours& parameters instead of hours.
struct leap_second_info.
is_leap_second renamed to get_leap_second_info.
is_leap_second changed from
pair<bool, seconds> to leap_second_info.
weekday.
weekday::iso_encoding Returns: clause.
link comparison operators. They
are implicitly specified by the existing standard.
time_of_day to hh_mm_ss.
make12/make24 from hh_mm_ss to
namespace scope.
fractional_width to hh_mm_ss.
hh_mm_ss specification.
R0: Original paper.
This is a collection of minor fixes and upgrades to the <chrono>
library that have come to my attention since the acceptance of
P0355r7.
This paper is written with respect to
N4810.
__cpp_lib_chrono in table
"Standard library feature-test macros" of [support.limits.general] to reflect date
of approval of this proposal.
Feedback from the field asks for a way to identify if a
utc_timerepresents a leap second. This proposed API is the only API that has field experience in providing that information in a way that is efficient, and provides all information the client desires when making a query in this area. It is used in the implementation of the conversion betweenutc_timeandsys_time, and in the parsing and formatting ofutc_time, so is likely to be present in any event. If we choose to specify it, it can be spelled without underscores, and be available to clients of<chrono>.
Insert into the synopsis 27.2 Header <chrono> synopsis [time.syn]:
struct leap_second_info; template <class Duration> leap_second_info get_leap_second_info(utc_time<Duration> const& ut);
Insert new paragraphs in 27.7.2.3 Non-member functions [time.clock.utc.nonmembers]:
struct leap_second_info { bool is_leap_second; seconds elapsed; };The type
leap_second_infohas data members and special members specified above. It has no base classes or members other than those specified.template <class Duration> leap_second_info get_leap_second_info(utc_time<Duration> const& ut);Returns: A
leap_second_infowhereis_leap_secondis true ifutis during a leap second insertion, and otherwise false.elapsedis the number of leap seconds between 1970-01-01 andut. Ifis_leap_secondis true, the leap second referred to byutis included in the count.
Feedback from the field asks for a way to customize the spacing between a duration's value and its unit (e.g. supply a space, or a Unicode custom space between the value and the unit). This item proposes
%Qto represent the durations's value and%qto represent the duration's unit, for formatting only. Example:format("%Q %q", 45ms) == "45 ms".
Add two new rows to Table 87 — Meaning of format conversion
specifiers:
%QThe duration's numeric value (as if extracted via .count()).%qThe duration's unit suffix as specified in [time.duration.io].
About half of the clients are upset that the currently specified encoding for
weekdayimplies that Sunday is the first day of the week (consistent with the current C and C++ specifications fortm.tm_wday), and the other half of the clients will be upset if theweekdayencoding follows the ISO specification of [1, 7] maps to [Monday, Sunday].This change strikes a compromise in an attempt to please everyone (a nearly impossible task).
The
weekday{unsigned}constructor accepts both mappings, which means that [0, 6] maps to [Sunday, Saturday] and [1, 7] maps to [Monday, Sunday]. This is possible by simply accepting [0, 7] where [1, 6] maps to [Monday, Saturday] and both 0 and 7 map to Sunday.The explicit conversion to
unsignedis removed fromweekdayand named conversions are inserted in its place:c_encoding()andiso_encoding(). The client can choose which mapping fromweekdaytounsignedhe desires by choosing one of these member functions.
Modify 27.8.6.2 [time.cal.wd.members] as indicated:
constexpr explicit weekday(unsigned wd) noexcept;Effects: Constructs an object of type
weekdayby initializingwd_withwd == 7 ? 0 : wd. The value held is unspecified if wd is not in the range [0, 255].constexpr explicit operator unsigned() const noexcept;
Returns:wd_.constexpr unsigned c_encoding() const noexcept;Returns:
wd_.constexpr unsigned iso_encoding() const noexcept;Returns:
wd_ == 0u ? 7u : wd_.
Modify 27.8.6.3 [time.cal.wd.nonmembers] as indicated:
constexpr bool operator==(const weekday& x, const weekday& y) noexcept;Returns:
.unsigned{x} == unsigned{y}x.wd_ == y.wd_constexpr weekday operator+(const weekday& x, const days& y) noexcept;Returns:
weekday{modulo(static_cast<long long>(.unsigned{x.wd_}) + y.count(), 7)}template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd);Effects: If
wd.ok() == trueinsertsformat(os.getloc(), fmt, wd)wherefmtis"%a"widened tocharT. Otherwise insertsunsigned{wd.wd_} << " is not a valid weekday".
time_of_dayis poorly specified. It suffers from an overly complicated specification, and at the same time, insufficient functionality from that specification. Additionally, guidance from the LEWG mailing list indicates significant dissatisfaction with the name oftime_of_dayand its internal state that changes mode between 24h and 12h time. This note changes the name oftime_of_daytohh_mm_ssto bring the semantics away from holding just a time duration since midnight, and more towards holding any duration as an{hours, minutes, seconds, subseconds}data structure. Also the 24h/12h functionality is moved out of this structure and into namespace-scope functions. And finally this change both simplifies the specification while providing more pertinent functionality. However the basic functionality is maintained:hh_mm_ssis an{hours, minutes, seconds, subseconds}structure which easily converts to and from adurationand provides easy formatting.
Modify 27.1 General [time.general]
Table 85 — Time library summary Subclause Header(s) ... 27.8 Civil calendar 27.9 Class template time_of_dayhh_mm_ss27.10 12/24 hour functions 27.1027.11Time zones ... Modify 27.2 Header
<chrono>synopsis [time.syn]... // 27.9, class templatetime_of_dayhh_mm_ss template <class Duration> classtime_of_dayhh_mm_ss;template<> class time_of_day<hours>;template<> class time_of_day<minutes>;template<> class time_of_day<seconds>;template<class Rep, class Period> class time_of_day<duration<Rep, Period>>;template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<hours>& t); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<minutes>& t); template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<seconds>& t);template<class charT, class traits, classRep, class PeriodDuration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, consttime_of_dayhh_mm_ss<Dduration<Rep, Period>>& t); // 27.10, 12/24 hour functions constexpr bool is_am(const hours& h) noexcept; constexpr bool is_pm(const hours& h) noexcept; constexpr hours make12(const hours& h) noexcept; constexpr hours make24(const hours& h, bool is_pm) noexcept; ...Modify 27.7.1.3 Non-member functions [time.clock.system.nonmembers]
Effects:
...
os << year_month_day{dp} << ' ' <<time_of_dayhh_mm_ss{tp-dp};Replace [time.tod] with [time.hms]:
27.9 Class template
hh_mm_ss[time.hms]27.9.1 Overview [time.hms.overview]
template <class Duration> class hh_mm_ss { bool is_neg; // exposition only chrono::hours h; // exposition only chrono::minutes m; // exposition only chrono::seconds s; // exposition only precision ss; // exposition only public: static unsigned constexpr fractional_width = see below; using precision = see below; constexpr hh_mm_ss() noexcept : hh_mm_ss{Duration::zero()} {} constexpr explicit hh_mm_ss(Duration d); constexpr bool is_negative() const noexcept; constexpr chrono::hours hours() const noexcept; constexpr chrono::minutes minutes() const noexcept; constexpr chrono::seconds seconds() const noexcept; constexpr precision subseconds() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; }; template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, hh_mm_ss<Duration> const& hms);The
hh_mm_ssclass template splits a duration into a multi-field time structure hours:minutes:seconds and possibly subseconds, where subseconds will be adurationunit based on a non-positive power of 10. TheDurationtemplate parameter dictates the precision to which the time is split. Ahh_mm_ssmodels negative durations with a distinctis_negativegetter that returnstruewhen the input duration is negative. The individual duration fields always return non-negative durations even whenis_negative()indicates the structure is representing a negative duration.If
Durationis not an instance ofduration, the program is ill-formed.27.9.2 Members [time.hms.members]
static unsigned constexpr fractional_width = see below;
fractional_widthis the number of fractional decimal digits represented byprecision.fractional_widthhas the value of the smallest possible integer in the range [0, 18] such thatprecisionwill exactly represent all values ofDuration. If no such value offractional_widthexists, thenfractional_widthis 6.[Example:
Durationfractional_widthFormatted fractional second
output ofDuration{1}hours,minutes, andseconds0milliseconds3.001 microseconds6.000001 nanoseconds9.000000001 duration<int, ratio<1, 2>>1.5 duration<int, ratio<1, 3>>6.333333 duration<int, ratio<1, 4>>2.25 duration<int, ratio<1, 5>>1.2 duration<int, ratio<1, 6>>6.166666 duration<int, ratio<1, 7>>6.142857 duration<int, ratio<1, 8>>3.125 duration<int, ratio<1, 9>>6.111111 duration<int, ratio<1, 10>>1.1 duration<int, ratio<756, 625>> //microfortnights4.2096 — end example]
using precision = see below;
precisionisduration<common_type_t<Duration::rep, seconds::rep>, ratio<1, 10fractional_width>>.constexpr explicit hh_mm_ss(Duration d);Effects: constructs an object of type
hh_mm_sswhich represents theDuration dwith precisionprecision.Initializes
is_negwithd < Duration::zero().Initializes
hwithduration_cast<chrono::hours>(abs(d)).Initializes
mwithduration_cast<chrono::minutes>(abs(d) - hours()).Initializes
swithduration_cast<chrono::seconds>(abs(d) - hours() - minutes()).If
treat_as_floating_point_v<precision::rep>istrue, initializessswithabs(d) - hours() - minutes() - seconds(). Else initializessswithduration_cast<precision>(abs(d) - hours() - minutes() - seconds()). [Note: Whenprecisionissecondswith integral representation,subseconds()always returns0s— end note]Ensures: If
treat_as_floating_point_v<precision::rep>istrue,to_duration()returnsd, elseto_duration()returnsduration_cast<precision>(d).constexpr bool is_negative() const noexcept;Returns:
is_neg.constexpr chrono::hours hours() const noexcept;Returns:
h.constexpr chrono::minutes minutes() const noexcept;Returns:
m.constexpr chrono::seconds seconds() const noexcept;Returns:
s.constexpr precision subseconds() const noexcept;Returns:
ss.constexpr precision to_duration() const noexcept;Returns: If
is_neg, returns-(h + m + s + ss), else returnsh + m + s + ss.constexpr explicit operator precision() const noexcept;Returns:
to_duration().27.9.3 Non-members [time.hms.nonmembers]
template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, hh_mm_ss<Duration> const& hms);Effects: Outputs to
osaccording to the format"%T"([time.format]). Ifhms.is_negative(), the output is preceded with'-'.Returns:
os.[Example:
for (auto ms : {-4083007ms, 4083007ms, 65745123ms}) { hh_mm_ss hms{ms}; cout << hms << '\n'; } cout << hh_mm_ss{65745s} << '\n';Produces the output (assuming the "C" locale):
-01:08:03.007 01:08:03.007 18:15:45.123 18:15:45— end example]
Insert a new section, 27.10 12/24 hour functions [time.12]:
27.10 12/24 hour functions [time.12]
These functions aid in translating between a 12h format time of day, and a 24h format time of day.
constexpr bool is_am(const hours& h) noexcept;Returns:
0h <= h && h <= 11h.constexpr bool is_pm(const hours& h) noexcept;Returns:
12h <= h && h <= 23h.constexpr hours make12(const hours& h) noexcept;Returns: The 12-hour equivalent of
hin the range[1h, 12h]. Ifhis not in the range[0h, 23h], the value returned is unspecified.constexpr hours make24(const hours& h, bool is_pm) noexcept;Returns: If
is_pmisfalse, returns the 24-hour equivalent ofhin the range[0h, 11h], assuminghrepresents an ante meridiem hour. Else returns the 24-hour equivalent ofhin the range[12h, 23h], assuminghrepresents a post meridiem hour. Ifhis not in the range[1h, 12h], the value returned is unspecified.