R2:
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_time
represents 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_time
andsys_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_info
has 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_info
whereis_leap_second
is true ifut
is during a leap second insertion, and otherwise false.elapsed
is the number of leap seconds between 1970-01-01 andut
. Ifis_leap_second
is true, the leap second referred to byut
is 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
%Q
to represent the durations's value and%q
to 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:
%Q
The duration's numeric value (as if extracted via .count()
).%q
The duration's unit suffix as specified in [time.duration.io].
About half of the clients are upset that the currently specified encoding for
weekday
implies 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 theweekday
encoding 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
unsigned
is removed fromweekday
and named conversions are inserted in its place:c_encoding()
andiso_encoding()
. The client can choose which mapping fromweekday
tounsigned
he 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
weekday
by initializingwd_
withwd
, except ifwd_ == 7
, stores0
. 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() == true
insertsformat(os.getloc(), fmt, wd)
wherefmt
is"%a"
widened tocharT
. Otherwise insertsunsigned{wd.wd_} << " is not a valid weekday"
.
time_of_day
is 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_day
and its internal state that changes mode between 24h and 12h time. This note changes the name oftime_of_day
tohh_mm_ss
to 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_ss
is an{hours, minutes, seconds, subseconds}
structure which easily converts to and from aduration
and 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_day
hh_mm_ss
27.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_ss
class template splits a duration into a multi-field time structure hours:minutes:seconds and possibly subseconds, where subseconds will be aduration
unit based on a non-positive power of 10. TheDuration
template parameter dictates the precision to which the time is split. Ahh_mm_ss
models negative durations with a distinctis_negative
getter that returnstrue
when 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
Duration
is not an instance ofduration
, the program is ill-formed.27.9.2 Members [time.hms.members]
static unsigned constexpr fractional_width = see below;
fractional_width
is the number of fractional decimal digits represented byprecision
.fractional_width
has the value of the smallest possible integer in the range [0, 18] such thatprecision
will exactly represent all values ofDuration
. If no such value offractional_width
exists, thenfractional_width
is 6.[Example:
Duration
fractional_width
Formatted fractional second
output ofDuration{1}
hours
,minutes
, andseconds
0
milliseconds
3
.001 microseconds
6
.000001 nanoseconds
9
.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;
precision
isduration<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_ss
which represents theDuration d
with precisionprecision
.Stores
d < Duration::zero()
inis_neg
.Stores
duration_cast<chrono::hours>(abs(d))
inh
.Stores
duration_cast<chrono::minutes>(abs(d) - hours())
inm
.Stores
duration_cast<chrono::seconds>(abs(d) - hours() - minutes())
ins
.If
treat_as_floating_point_v<precision::rep>
istrue
, storesabs(d) - hours() - minutes() - seconds()
inss
. Else storesduration_cast<precision>(abs(d) - hours() - minutes() - seconds())
inss
. [Note: Whenprecision
isseconds
with 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
os
according 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
h
in the range[1h, 12h]
. Ifh
is not in the range[0h, 23h]
, the value returned is unspecified.constexpr hours make24(const hours& h, bool is_pm) noexcept;Returns: If
is_pm
isfalse
, returns the 24-hour equivalent ofh
in the range[0h, 11h]
, assumingh
represents an ante meridiem hour. Else returns the 24-hour equivalent ofh
in the range[12h, 23h]
, assumingh
represents a post meridiem hour. Ifh
is not in the range[1h, 12h]
, the value returned is unspecified.