<chrono>
to Calendars and Time Zonesto_sys_time
,
to_utc_time
, to_tai_time
, to_gps_time
,
to_file_time
, with clock_cast
.zoned_time
conversion among different TimeZonePtr
types.nonexistent_local_time
and
ambiguous_local_time
.remote_download
and
remote_install
. This functionality is now subsumed by the implementation.to_stream
sets failbit
if it is required to create a name
for an invalid month or weekday.fmt
(P0645)format
throw an exception if anything happens so that it
could not return an accurate string.zoned_time
on TimeZonePtr
.weekday_indexed
a defaulted default constructor.from_stream
and to_stream
customization points.tzdb
with
an atomic head pointer, instead of a single tzdb
.string_view
.zoned_time
default constructor.zoned_time
deduction guides.to_stream
and from_stream
to
utc_time<Duration>
, tai_time<Duration>
, and
gps_time<Duration>
.from_stream
, and rewrite format
and
parse
in terms of to_stream
and
from_stream
.to_stream
and from_stream
for year
,
month
, day
, weekday
, year_month
, and
month_day
.to_stream
will set failbit
instead of throw
.file_clock
and hook it into filesytem
.zoned_time
to be coarser than seconds.make_time
and make_zoned
in favor of the
implicit deduction guides.zoned_time(const char* name, ...)
overloads to enable
implicit deduction guides.time_of_day
default constructor.Alloc
to basic_string
everywhere possible.system_clock::to_time_t
and
system_clock::from_time_t
.is_clock
type trait.time_point
to be a Clock or
a local_t
.is_clock{}
is false.time_point
incremental and decrementableyear
enum {am, pm}
, time_of_day
constructors which use it, and make_time
factory functions
which use it.to_stream
.format
and parse
for duration
.utc_clock::utc_to_sys
and utc_clock::sys_to_utc
.utc_clock::utc_to_sys
and utc_clock::sys_to_utc
in favor of free functions such as to_sys_time
and to_utc_time
.utc_time
a streaming operator.format
to take time_point
s by const&
instead of by value.noexcept
from make_time
.
The purpose of a calendar is to give a name to each day.1
There are many different ways this can be accomplished. This paper proposes only the
Gregorian calendar. However the design of this proposal is such that clients can code
other calendars and have them interoperate with <chrono>
, the civil
calendar, and with time zones, all with a minimal coupling. For example:
#include "coptic.h" // not proposed, just an example #include <chrono> #include <iostream> int main() { using namespace std::chrono_literals; auto date = 2016y/may/29; cout << date << " is " << coptic::year_month_day{date} << " in the Coptic calendar\n"; // 2016-05-29 is 1732-09-21 in the Coptic calendar }
The above example creates a date in the Gregorian calendar (proposed) with the
literal 2016y/may/29
. The meaning of this literal is without
question. It is conventional and clearly readable. This proposal has no
knowledge whatsoever of the Coptic calendar. However it is relatively easy to
create a Coptic calendar (which knows nothing about the Gregorian calendar),
which will convert to and from the Gregorian calendar. This is done by
establishing a clear and simple communication channel between calendar systems
and the <chrono>
library (specifically a
system_clock::time_point
with a precision of days).
The paper proposes:
<chrono>
to support calendar and
time zone libraries.strftime
-like formatting and parsing facilities with fully operational
support for fractional seconds, time zone abbreviations, and UTC offsets.<chrono>
clocks for computing with leap seconds which is
also supported by the IANA Time Zone
Database.Everything proposed herein has been fully implemented here:
https://github.com/HowardHinnant/date
The implementation includes full documentation, and an active community of users with positive field experience. The implementation has been ported to Windows, Linux, Android, macOS and iOS.
The API stresses:
<chrono>
library.<chrono>
does.Listing "Performance" in the API design deserves a little explanation as one usually thinks of that as an implementation issue. Think of it this way:
vector<T>::push_front(const T&)
existed, that would
encourage inefficient code, even though it would be trivial to implement.
list<T>::operator[](size_type index)
existed, that would
encourage inefficient code, even though it would be trivial to implement (by
incrementing from begin()
or decrementing from end()
).
This API makes it convenient to write efficient code, and inconvenient to write
inefficient code. It turns out that conversion between a field type such as
{year, month, day}
and a serial type such as
{count-of-days}
is one of the more expensive operations when
dealing with calendrical computations. Both data structures are very useful
(just as both vector
and list
are very useful). So
this library puts you in control of when and how often that conversion
takes place, and makes it easy to avoid such conversions when not necessary.
One can create a year
like this:
auto y = year{2016};
Just like <chrono>
, type safety is taken very seriously. The
type year
is distinct from type int
, just as 3
can never mean "3 seconds", unless it is explicitly typed to do so:
seconds{3}
.
And just like seconds
, there is a year literal suffix which can help make
your code more readable:
auto y = 2016y;
year
is a partial-calendar-type. It can be combined with
other partial-calendar-types to create a full-calendar-type such as
year_month_day
. Full-calendar-types can be converted to and from
the family of system_clock::time_point
s. Full-calendar-types such
as year_month_day
are time points with a precision of a day, but
they are also field types. They are composed of 3 fields under the hood:
year
, month
and day
. Thus when you
construct a year_month_day
from a year
,
month
and day
, absolutely no computation takes place.
The only thing that happens is a year
, month
and
day
are stored inside the year_month_day
.
year_month_day ymd1{2016y, month{5}, day{29}};
This is a very simple operation and can even be made
constexpr
when all of the inputs are compile-time constants. And
conventional syntax is available which means the exact same thing, with
the same run-time or compile-time performance. It can make date literals much
more readable without sacrificing type safety:
constexpr year_month_day ymd1{2016y, month{5}, day{29}}; constexpr auto ymd2 = 2016y/may/29d; static_assert(ymd1 == ymd2); static_assert(ymd1.year() == 2016y); static_assert(ymd1.month() == may); static_assert(ymd1.day() == 29d);
year_month_day
is a very simple, very understandable
calendrical data structure:
class year_month_day { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::day d_; // exposition only public: constexpr year_month_day(const chrono::year& y, const chrono::month& m, const chrono::day& d) noexcept; // ...
By now you should be yawning and muttering "so what?"
Now we introduce a little <chrono>
infrastructure that serves
as the communication channel with simplistic calendrical data structures such as
year_month_day
.
using days = duration<int32_t, ratio_multiply<ratio<24>, hours::period>>; template <class Duration> using sys_time = time_point<system_clock, Duration>; using sys_days = sys_time<days>;
sys_days
is a std::chrono::time_point
. This
time_point
is based on system_clock
and has a very coarse
precision: 24 hours. Just as system_clock::time_point
is nothing more
than a count of microseconds (or nanoseconds, or whatever), sys_days
is
simply a count of days since the system_clock
epoch. And
sys_days
is fully interoperable with
system_clock::time_point
in all of the ways normal to the
<chrono>
library:
sys_days
implicitly converts to system_clock::time_point
with no truncation error.system_clock::time_point
does not implicitly convert to
sys_days
because it would involve truncation error.system_clock::time_point
by
using the existing <chrono>
facilities time_point_cast
or floor
.constexpr system_clock::time_point tp = sys_days{2016y/may/29d}; // Convert date to time_point static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us); constexpr auto ymd = year_month_day{floor<days>(tp)}; // Convert time_point to date static_assert(ymd == 2016y/may/29d);
The calendrical type year_month_day
provides conversions to and
from sys_days
. This conversion is easy to do for std::lib
implementors using algorithms
such as these.
If the committee standardizes existing practice and specifies that
system_clock
measures
Unix Time,
then it will be equally easy for
anyone to write their own calendar system which converts to and from
sys_days
(e.g. the coptic example in the introduction).
This proposal actually contains a second calendar. It is so closely related to the
civil calendar that we normally don't think of it as another calendar. We often
refer to dates like "the 5th Sunday of May in 2016" as opposed to "the 29th of May
in 2016." This proposal makes it so easy to build fully functional calendars that
interoperate with system_clock::time_point
, that it is nearly trivial
to include such functionality:
constexpr system_clock::time_point tp = sys_days{sun[5]/may/2016}; // Convert date to time_point static_assert(tp.time_since_epoch() == 1'464'480'000'000'000us); constexpr auto ymd = year_month_weekday{floor<days>(tp)}; // Convert time_point to date static_assert(ymd == sun[5]/may/2016);
The literal sun[5]/may/2016
means "the 5th Sunday of May in 2016."
The conventional syntax is remarkably readable. Constructor syntax is
also available to do the same thing. The type constructed is
year_month_weekday
which does nothing but store a
year
, month
, weekday
, and the number 5.
This "auxiliary calendar" converts to and from sys_days
just like
year_month_day
as demonstrated above. As such,
year_month_weekday
will interoperate with year_month_day
(by bouncing off of sys_days
) just as it will with any other calendar
that interoperates with sys_days
:
static_assert(2016y/may/29d == year_month_day{sun[5]/may/2016});
Since year_month_day
is so easy to convert to (or from) a
time_point
it makes sense to convert to a time_point
when
you need to talk about a date and time-of-day:
constexpr auto tp = sys_days{2016y/may/29d} + 7h + 30min; // 2016-05-29 07:30 UTC
The time zone is implicitly UTC because system_clock
tracks Unix Time which is (a very
close approximation to) UTC. If you need another time zone, no worries, we'll
get there. And remember, tp
above is a
system_clock::time_point
, except with minutes precision. You can
compare it with system_clock::now()
to find out if the date is in
the past or the future. Also note that the syntax above (like
<chrono>
) is precision neutral. That's because the
syntax above is <chrono>
, except for the part
converting a calendar type into the <chrono>
system. If you
suddenly need to convert your minutes-precision time point into seconds or
milliseconds (or whatever) precision, the change is seamlessly handled by the
existing <chrono>
system:
constexpr auto tp = sys_days{2016y/may/29d} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 UTC
Simple streaming is provided:
cout << tp << '\n'; // 2016-05-29 07:30:06.153
But I need the time in Tokyo!
auto tp = sys_days{2016y/may/29d} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 UTC zoned_time zt = {"Asia/Tokyo", tp}; cout << zt << '\n'; // 2016-05-29 16:30:06.153 JST
zoned_time
is templated on the duration type of tp
, which is
automatically deduced from the initialization expression (milliseconds in this example).
This effectively pairs a time zone with a time point. In this example we pair the time
zone "Asia/Tokyo" with a sys_time
(which is implicitly UTC). When printed
out, you see the local time, and by default the current time zone abbreviation. Also by
default, you see the full precision of the zoned_time
.
Sometimes, instead of specifying the time in UTC as above, it is convenient to specify the time in terms of the local time of the time zone. It is very easy to change the above example to mean 7:30 JST instead of 7:30 UTC:
auto tp = local_days{2016y/may/29d} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 auto zt = zoned_time{"Asia/Tokyo", tp}; cout << zt << '\n'; // 2016-05-29 07:30:06.153 JST
The only change to the code is the use of local_days
in
place of sys_days
. local_days
is also a
std::chrono::time_point
but its "clock type" local_t
has no now()
function. This time_point
is called
local_time
. A local_time
can refer to any time
zone. In the above example when we pair "Asia/Tokyo" with the
local_time
, the result becomes a zoned_time
with the
local time specified by the local_time
.
To interoperate with time zones, calendrical types must convert to and from
local_days
as well as sys_days
. The math is identical
for both conversions, so it is very easy for the calendar author to provide.
But as seen in this example, the meaning can be quite different.
The client of the calendar library can easily use the calendar types with the
time zone library, specifying times either in the local time, or in UTC, simply
by switching between local_days
and sys_days
. Here
is an example that sets up a meeting at 9am on the third Tuesday of June, 2016
in New York:
auto zt = zoned_time{"America/New_York", local_days{tue[3]/jun/2016} + 9h}; cout << zt << '\n'; // 2016-06-21 09:00:00 EDT
Need to set up a video conference with your partners in Helsinki?
cout << zoned_time{"Europe/Helsinki", zt} << '\n';
This converts one zoned_time
into another zoned_time
where
the only difference is changing from "America/New_York" to "Europe/Helsinki". The
conversion preserves the UTC equivalent in both zoned_time
s, and
therefore outputs:
2016-06-21 16:00:00 EEST
And if this is not the formatting you prefer, that is easily fixed too:
cout << format("%F %H:%M %z", zoned_time{"Europe/Helsinki", zt}) << '\n'; // 2016-06-21 16:00 +0300
Or perhaps properly localized:
cout << format(locale{"fi_FI"}, "%c", zoned_time{"Europe/Helsinki", zt}) << '\n'; // Ti 21 Kes 16:00:00 2016
Wait, slow down, this is too much information! Let's start at the beginning. How do I get the current time?
cout << system_clock::now() << " UTC\n"; // 2016-05-30 17:57:30.694574 UTC
My current local time?
cout << zoned_time{current_zone(), system_clock::now()} << '\n'; // 2016-05-30 13:57:30.694574 EDT
Current time in Budapest?
cout << zoned_time{"Europe/Budapest", system_clock::now()} << '\n'; // 2016-05-30 19:57:30.694574 CEST
For more documentation about the calendar portion of this proposal, including more details, more examples, and performance analyses, please see:
http://howardhinnant.github.io/date/date.html
For a video introduction to the calendar portion, please see:
https://www.youtube.com/watch?v=tzyGjOm8AKo
For a video introduction to the time zone portion, please see:
https://www.youtube.com/watch?v=Vwd3pduVGKY
For more documentation about the time zone portion of this proposal, including more details, and more examples, please see:
http://howardhinnant.github.io/date/tz.html
For more examples, some of which are written by users of this library, please see:
https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
For another example calendar which models the ISO week-based calendar, please see:
http://howardhinnant.github.io/date/iso_week.html
[time] 23.17 [time.general] 23.17.1 [time.syn] 23.17.2 [time.clock.req] 23.17.3 [time.traits] 23.17.4 [time.traits.is_fp] 23.17.4.1 [time.traits.duration_values] 23.17.4.2 [time.traits.specializations] 23.17.4.3 [time.traits.is_clock] [time.duration] 23.17.5 [time.duration.cons] 23.17.5.1 [time.duration.observer] 23.17.5.2 [time.duration.arithmetic] 23.17.5.3 [time.duration.special] 23.17.5.4 [time.duration.nonmember] 23.17.5.5 [time.duration.comparisons] 23.17.5.6 [time.duration.cast] 23.17.5.7 [time.duration.literals] 23.17.5.8 [time.duration.alg] 23.17.5.9 [time.duration.io] [time.point] 23.17.6 [time.point.cons] 23.17.6.1 [time.point.observer] 23.17.6.2 [time.point.arithmetic] 23.17.6.3 [time.point.special] 23.17.6.4 [time.point.nonmember] 23.17.6.5 [time.point.comparisons] 23.17.6.6 [time.point.cast] 23.17.6.7 [time.clock] 23.17.7 [time.clock.system] 23.17.7.1 [time.clock.utc] [time.clock.tai] [time.clock.gps] [time.clock.file] [time.clock.steady] 23.17.7.2 [time.clock.hires] 23.17.7.3 [time.clock.local_time] [time.clock.clock_cast] [time.format] [time.parse] [time.calendar] [time.calendar.last] [time.calendar.day] [time.calendar.month] [time.calendar.year] [time.calendar.weekday] [time.calendar.weekday_indexed] [time.calendar.weekday_last] [time.calendar.month_day] [time.calendar.month_day_last] [time.calendar.month_weekday] [time.calendar.month_weekday_last] [time.calendar.year_month] [time.calendar.year_month_day] [time.calendar.year_month_day_last] [time.calendar.year_month_weekday] [time.calendar.year_month_weekday_last] [time.calendar.operators] [time.time_of_day] [time.timezone] [time.timezone.database] [time.timezone.database.remote] [time.timezone.exception] [time.timezone.info] [time.timezone.time_zone] [time.timezone.zoned_traits] [time.timezone.zoned_time] [time.timezone.leap] [time.timezone.link] [ctime.syn] 23.17.8 [fs.filesystem.syn] 30.10.6 [thread.req.paramname] 33.2.1
Text in grey boxes is not proposed wording.
Insert into synopsis in 23.17.2 Header <chrono>
synopsis [time.syn]:
namespace std { namespace chrono { // ... // customization traits // ... template <class T> struct is_clock; template <class T> inline constexpr bool is_clock_v = is_clock<T>::value; // duration I/O template <class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d); template <class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const duration<Rep, Period>& d); template <class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // ... // convenience typedefs // ... using days = duration<signed integer type of at least 25 bits, ratio_multiply<ratio<24>, hours::period>>; using weeks = duration<signed integer type of at least 22 bits, ratio_multiply<ratio<7>, days::period>>; using years = duration<signed integer type of at least 17 bits, ratio_multiply<ratio<146097, 400>, days::period>>; using months = duration<signed integer type of at least 20 bits, ratio_divide<years::period, ratio<12>>>; // ... // clocks // ... class utc_clock; class tai_clock; class gps_clock; class file_clock; // time_point families template <class Duration> using sys_time = time_point<system_clock, Duration>; using sys_seconds = sys_time<seconds>; using sys_days = sys_time<days>; struct local_t {}; template <class Duration> using local_time = time_point<local_t, Duration>; using local_seconds = local_time<seconds>; using local_days = local_time<days>; template <class Duration> using utc_time = time_point<utc_clock, Duration>; using utc_seconds = utc_time<seconds>; template <class Duration> using tai_time = time_point<tai_clock, Duration>; using tai_seconds = tai_time<seconds>; template <class Duration> using gps_time = time_point<gps_clock, Duration>; using gps_seconds = gps_time<seconds>; template <class Duration> using file_time = time_point<file_clock, Duration>; // time_point conversions template <class DestClock, class SourceClock> struct clock_time_conversion; template <class DestClock, class SourceClock, class Duration> time_point<DestClock, some duration> clock_cast(const time_point<SourceClock, Duration>& t); // time_point I/O // operator<< template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& tp); template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_days& dp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const utc_time<Duration>& t); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& tp); // to_stream template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const sys_time<Duration>& tp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const local_time<Duration>& tp, const string* abbrev = nullptr, const seconds* offset_sec = nullptr); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const utc_time<Duration>& tp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const tai_time<Duration>& tp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const gps_time<Duration>& tp); template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const file_time<Duration>& tp); // from_stream template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); // Calendrical types struct last_spec; class day; constexpr bool operator==(const day& x, const day& y) noexcept; constexpr bool operator!=(const day& x, const day& y) noexcept; constexpr bool operator< (const day& x, const day& y) noexcept; constexpr bool operator> (const day& x, const day& y) noexcept; constexpr bool operator<=(const day& x, const day& y) noexcept; constexpr bool operator>=(const day& x, const day& y) noexcept; constexpr day operator+(const day& x, const days& y) noexcept; constexpr day operator+(const days& x, const day& y) noexcept; constexpr day operator-(const day& x, const days& y) noexcept; constexpr days operator-(const day& x, const day& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const day& d); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class month; constexpr bool operator==(const month& x, const month& y) noexcept; constexpr bool operator!=(const month& x, const month& y) noexcept; constexpr bool operator< (const month& x, const month& y) noexcept; constexpr bool operator> (const month& x, const month& y) noexcept; constexpr bool operator<=(const month& x, const month& y) noexcept; constexpr bool operator>=(const month& x, const month& y) noexcept; constexpr month operator+(const month& x, const months& y) noexcept; constexpr month operator+(const months& x, const month& y) noexcept; constexpr month operator-(const month& x, const months& y) noexcept; constexpr months operator-(const month& x, const month& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month& m); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month& m); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class year; constexpr bool operator==(const year& x, const year& y) noexcept; constexpr bool operator!=(const year& x, const year& y) noexcept; constexpr bool operator< (const year& x, const year& y) noexcept; constexpr bool operator> (const year& x, const year& y) noexcept; constexpr bool operator<=(const year& x, const year& y) noexcept; constexpr bool operator>=(const year& x, const year& y) noexcept; constexpr year operator+(const year& x, const years& y) noexcept; constexpr year operator+(const years& x, const year& y) noexcept; constexpr year operator-(const year& x, const years& y) noexcept; constexpr years operator-(const year& x, const year& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year& y); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year& y); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class weekday; constexpr bool operator==(const weekday& x, const weekday& y) noexcept; constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; constexpr weekday operator+(const weekday& x, const days& y) noexcept; constexpr weekday operator+(const days& x, const weekday& y) noexcept; constexpr weekday operator-(const weekday& x, const days& y) noexcept; constexpr days operator-(const weekday& x, const weekday& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const weekday& wd); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class weekday_indexed; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi); class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl); class month_day; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; constexpr bool operator!=(const month_day& x, const month_day& y) noexcept; constexpr bool operator< (const month_day& x, const month_day& y) noexcept; constexpr bool operator> (const month_day& x, const month_day& y) noexcept; constexpr bool operator<=(const month_day& x, const month_day& y) noexcept; constexpr bool operator>=(const month_day& x, const month_day& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day& md); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month_day& md); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class month_day_last; constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl); class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd); class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl); class year_month; constexpr bool operator==(const year_month& x, const year_month& y) noexcept; constexpr bool operator!=(const year_month& x, const year_month& y) noexcept; constexpr bool operator< (const year_month& x, const year_month& y) noexcept; constexpr bool operator> (const year_month& x, const year_month& y) noexcept; constexpr bool operator<=(const year_month& x, const year_month& y) noexcept; constexpr bool operator>=(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; constexpr months operator-(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month& ym); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month& ym); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class year_month_day; constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month_day& ymd); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr); class year_month_day_last; constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator> (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept; constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl); class year_month_weekday; constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept; constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwdi); class year_month_weekday_last; constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl); // civil calendar conventional syntax operators constexpr year_month operator/(const year& y, const month& m) noexcept; constexpr year_month operator/(const year& y, int m) noexcept; constexpr month_day operator/(const month& m, const day& d) noexcept; constexpr month_day operator/(const month& m, int d) noexcept; constexpr month_day operator/(int m, const day& d) noexcept; constexpr month_day operator/(const day& d, const month& m) noexcept; constexpr month_day operator/(const day& d, int m) noexcept; constexpr month_day_last operator/(const month& m, last_spec) noexcept; constexpr month_day_last operator/(int m, last_spec) noexcept; constexpr month_day_last operator/(last_spec, const month& m) noexcept; constexpr month_day_last operator/(last_spec, int m) noexcept; constexpr month_weekday operator/(const month& m, const weekday_indexed& wdi) noexcept; constexpr month_weekday operator/(int m, const weekday_indexed& wdi) noexcept; constexpr month_weekday operator/(const weekday_indexed& wdi, const month& m) noexcept; constexpr month_weekday operator/(const weekday_indexed& wdi, int m) noexcept; constexpr month_weekday_last operator/(const month& m, const weekday_last& wdl) noexcept; constexpr month_weekday_last operator/(int m, const weekday_last& wdl) noexcept; constexpr month_weekday_last operator/(const weekday_last& wdl, const month& m) noexcept; constexpr month_weekday_last operator/(const weekday_last& wdl, int m) noexcept; constexpr year_month_day operator/(const year_month& ym, const day& d) noexcept; constexpr year_month_day operator/(const year_month& ym, int d) noexcept; constexpr year_month_day operator/(const year& y, const month_day& md) noexcept; constexpr year_month_day operator/(int y, const month_day& md) noexcept; constexpr year_month_day operator/(const month_day& md, const year& y) noexcept; constexpr year_month_day operator/(const month_day& md, int y) noexcept; constexpr year_month_day_last operator/(const year_month& ym, last_spec) noexcept; constexpr year_month_day_last operator/(const year& y, const month_day_last& mdl) noexcept; constexpr year_month_day_last operator/(int y, const month_day_last& mdl) noexcept; constexpr year_month_day_last operator/(const month_day_last& mdl, const year& y) noexcept; constexpr year_month_day_last operator/(const month_day_last& mdl, int y) noexcept; constexpr year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; constexpr year_month_weekday operator/(const year& y, const month_weekday& mwd) noexcept; constexpr year_month_weekday operator/(int y, const month_weekday& mwd) noexcept; constexpr year_month_weekday operator/(const month_weekday& mwd, const year& y) noexcept; constexpr year_month_weekday operator/(const month_weekday& mwd, int y) noexcept; constexpr year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) noexcept; constexpr year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) noexcept; constexpr year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) noexcept; constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) noexcept; constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) noexcept; // time_of_day template <class Duration> class time_of_day; 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, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<duration<Rep, Period>>& t); // time zone database struct tzdb; class tzdb_list; const tzdb& get_tzdb(); tzdb_list& get_tzdb_list(); const time_zone* locate_zone(string_view tz_name); const time_zone* current_zone(); // Remote time zone database -- Needs discussion const tzdb& reload_tzdb(); string remote_version(); // exception classes class nonexistent_local_time; class ambiguous_local_time; // information classes struct sys_info; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_info& si); struct local_info; template<class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_info& li); // time_zone enum class choose {earliest, latest}; class time_zone; bool operator==(const time_zone& x, const time_zone& y) noexcept; bool operator!=(const time_zone& x, const time_zone& y) noexcept; bool operator<(const time_zone& x, const time_zone& y) noexcept; bool operator>(const time_zone& x, const time_zone& y) noexcept; bool operator<=(const time_zone& x, const time_zone& y) noexcept; bool operator>=(const time_zone& x, const time_zone& y) noexcept; // zoned_time template <class Duration, class TimeZonePtr = const time_zone*> class zoned_time; using zoned_seconds = zoned_time<seconds>; template <class Duration1, class Duration2, class TimeZonePtr> bool operator==(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y); template <class Duration1, class Duration, class TimeZonePtr2> bool operator!=(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y); template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const zoned_time<Duration, TimeZonePtr>& t); template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const zoned_time<Duration, TimeZonePtr>& tp); // format template <class charT, class Streamable> basic_string<charT> format(const charT* fmt, const Streamable& s); template <class charT, class Streamable> basic_string<charT> format(const locale& loc, const charT* fmt, const Streamable& s); template <class charT, class traits, class Alloc, class Streamable> basic_string<charT, traits, Alloc> format(const basic_string<charT, traits, Alloc>& fmt, const Streamable& s); template <class charT, class traits, class Alloc, class Streamable> basic_string<charT, traits, Alloc> format(const locale& loc, const basic_string<charT, traits, Alloc>& fmt, const Streamable& s); // parse template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp); template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev); template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, minutes& offset); template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& format, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset); // leap second support class leap; bool operator==(const leap& x, const leap& y); bool operator!=(const leap& x, const leap& y); bool operator< (const leap& x, const leap& y); bool operator> (const leap& x, const leap& y); bool operator<=(const leap& x, const leap& y); bool operator>=(const leap& x, const leap& y); template <class Duration> bool operator==(const const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator==(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator!=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator!=(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator< (const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator< (const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator> (const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator> (const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator<=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator<=(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator>=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator>=(const sys_time<Duration>& x, const leap& y); class link; bool operator==(const link& x, const link& y); bool operator!=(const link& x, const link& y); bool operator< (const link& x, const link& y); bool operator> (const link& x, const link& y); bool operator<=(const link& x, const link& y); bool operator>=(const link& x, const link& y); } // namespace chrono inline namespace literals { inline namespace chrono_literals { // ... inline constexpr chrono::last_spec last{}; inline constexpr chrono::weekday sun{0}; inline constexpr chrono::weekday mon{1}; inline constexpr chrono::weekday tue{2}; inline constexpr chrono::weekday wed{3}; inline constexpr chrono::weekday thu{4}; inline constexpr chrono::weekday fri{5}; inline constexpr chrono::weekday sat{6}; inline constexpr chrono::month jan{1}; inline constexpr chrono::month feb{2}; inline constexpr chrono::month mar{3}; inline constexpr chrono::month apr{4}; inline constexpr chrono::month may{5}; inline constexpr chrono::month jun{6}; inline constexpr chrono::month jul{7}; inline constexpr chrono::month aug{8}; inline constexpr chrono::month sep{9}; inline constexpr chrono::month oct{10}; inline constexpr chrono::month nov{11}; inline constexpr chrono::month dec{12}; constexpr chrono::day operator "" d(unsigned long long d) noexcept; constexpr chrono::year operator "" y(unsigned long long y) noexcept; } }
Add new section [time.is_clock] after 23.17.4.3 Specializations of common_type
[time.traits.specializations]:
23.17.4.4
is_clock
[time.traits.is_clock]template <class T> struct is_clock;
is_clock
is aUnaryTypeTrait
([meta.rqmts]) with a base characteristic oftrue_type
ifT
meets theClock
requirements ([time.clock.req]), otherwisefalse_type
. For the purposes of the specification of this trait, the extent to which an implementation determines that a type cannot meet the clock requirements is unspecified, except that as a minimum a typeT
shall not qualify as a clock unless it satisfies all of the following conditions:
- the qualified-ids
T::rep
,T::period
,T::duration
, andT::time_point
are valid and each denotes a type ([temp.deduct]),- the expression
T::is_steady
is well-formed when treated as an unevaluated operand,- the expression
T::now()
is well-formed when treated as an unevaluated operand.The behavior of a program that adds specializations for
is_clock
is undefined.
Add new section [time.duration.io] after 23.17.5.9 duration algorithms [time.duration.alg]:
23.17.5.10 duration stream insertion [time.duration.io]
template <class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const duration<Rep, Period>& d);Effects: Forms a
basic_string<charT, traits>
fromd.count()
appended withget_units<charT, traits>(typename Period::type{})
(described below) and inserts thatbasic_string
intoos
. [Note: this specification assures that the result of this streaming operation will obey the width and alignment properties of the stream. — end note]
get_units<charT, traits>(typename Period::type{})
is an exposition-only function which returns a null-terminated string ofcharT
which depends onPeriod::type
as follows (letperiod
be the typePeriod::type
):
- If
period
is typeatto
,as
, else- if
period
is typefemto
,fs
, else- if
period
is typepico
,ps
, else- if
period
is typenano
,ns
, else- if
period
is typemicro
,µs
(U+00B5), else- if
period
is typemilli
,ms
, else- if
period
is typecenti
,cs
, else- if
period
is typedeci
,ds
, else- if
period
is typeratio<1>
,s
, else- if
period
is typedeca
,das
, else- if
period
is typehecto
,hs
, else- if
period
is typekilo
,ks
, else- if
period
is typemega
,Ms
, else- if
period
is typegiga
,Gs
, else- if
period
is typetera
,Ts
, else- if
period
is typepeta
,Ps
, else- if
period
is typeexa
,Es
, else- if
period
is typeratio<60>
,min
, else- if
period
is typeratio<3600>
,h
, else- if
period::den == 1
,[num]s
, else[num/den]s
.In the list above the use of
num
andden
refer to the static data members ofperiod
which are converted to arrays ofcharT
using a decimal conversion with no leading zeroes.For streams with
charT
which has a representation of 8 bitsµs
should be encoded as UTF-8. Otherwise UTF-16 or UTF-32 is encouraged. The implementation may substitute other encodings, includingus
.Returns:
os
.template <class charT, class traits, class Rep, class Period> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const duration<Rep, Period>& d);Effects: Streams
d
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, duration<Rep, Period>& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into the durationd
using the format flags as specified in [time.parse].If the parse parses everything specified by the parsing format flags without error, and yet none of the flags impacts a duration,
d
will be assigned a zero value.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.
Add to synopsis in section [time.point] 23.17.6 Class template time_point
:
template <class Clock, class Duration = typename Clock::duration> class time_point { public: ... // 23.17.6.3, arithmetic constexpr time_point& operator++(); constexpr time_point operator++(int); constexpr time_point& operator--(); constexpr time_point operator--(int); constexpr time_point& operator+=(const duration& d); constexpr time_point& operator-=(const duration& d); ... };
Modify section 23.17.6 Class template time_point
[time.point]/p1:
1
Clock
shall meet the Clock requirements ([time.clock.req]) orClock
shall belocal_t
.
Add to section [time.point.arithmetic] 23.17.6.3 time_point
arithmetic:
constexpr time_point& operator++();Effects:
++d_
.Returns:
*this
.constexpr time_point operator++(int);Returns:
time_point{d_++}
.constexpr time_point& operator--();Effects:
--d_
.Returns:
*this
.constexpr time_point operator--(int);Returns:
time_point{d_--}
.
Modify 23.17.7 [time.clock]:
1 The types defined in this subclause shall satisfy the TrivialClock requirements (23.17.3) unless otherwise specified.
Modify 23.17.7.1 [time.clock.system]:
1 Objects of class
system_clock
represent wall clock time from the system-wide realtime clock.sys_time<Duration>
measures time since (and before) 1970-01-01 00:00:00 UTC excluding leap seconds. This measure is commonly referred to as Unix Time. This measure facilitates an efficient mapping betweensys_time
and calendar types ([time.calendar])[Example:
sys_seconds{sys_days{1970y/jan/1}}.time_since_epoch() is 0s sys_seconds{sys_days{2000y/jan/1}}.time_since_epoch() is 946'684'800s which is 10'957 * 86'400s—end example]
Deprecate the to_time_t
and from_time_t
static member functions of
system_clock
in 23.17.7.1 [time.clock.system] by moving their declaration
and specification to Annex D.
Rationale: This proposal removes all need for using the C
<time.h>
API except to translatesystem_clock::time_point
to legacy code. That translation can now be portably done by converting asystem_clock::time_point
to ayear_month_day
andtime_of_day<seconds>
and translating that information into atm
. The C API is error prone with its lack of type safe distinctions between local time and UTC, and suffers from a lack of handling precisions finer than seconds. Furthermore the newertimespec
API makes no distinction between time points and time durations, further eroding type safety.
Append new paragraphs after 23.17.7.1 [time.clock.system]/p4:
template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_time<Duration>& tp);Remarks: This operator shall not participate in overload resolution if
treat_as_floating_point<typename Duration::rep>::value
is true, or ifDuration{1} >= days{1}
.Effects:
auto const dp = floor<days>(tp); os << year_month_day{dp} << ' ' << time_of_day{tp-dp};Returns:
os
.[Example:
cout << sys_seconds{0s} << '\n'; // 1970-01-01 00:00:00 cout << sys_seconds{946'684'800s} << '\n'; // 2000-01-01 00:00:00— end example:]
template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_days& dp);Effects:
os << year_month_day{dp};Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const sys_time<Duration>& tp);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with"UTC"
. If%z
is used (or a modified form of%z
), an offset of0min
will be formatted.Returns:
os
.template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, sys_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into thesys_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null. Additionally, the parsed offset will be subtracted from the successfully parsed time stamp prior to assigning that difference totp
.Returns:
is
.
Add new section [time.clock.utc] after 23.17.7.1 Class system_clock [time.clock.system]:
23.17.7.2 Class utc_clock [time.clock.utc]
class utc_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<utc_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template <class Duration> static sys_time<common_type_t<Duration, seconds>> to_sys(const utc_time<Duration>& t); template <class Duration> static utc_time<common_type_t<Duration, seconds>> from_sys(const sys_time<Duration>& t); };In contrast to
sys_time
which does not take leap seconds into account,utc_clock
and its associatedtime_point
,utc_time
, counts time, including leap seconds, since 1970-01-01 00:00:00 UTC.[Example:
clock_cast<utc_clock>(sys_seconds{sys_days{1970y/jan/1}}).time_since_epoch() is 0s clock_cast<utc_clock>(sys_seconds{sys_days{2000y/jan/1}}).time_since_epoch() is 946'684'822s which is 10'957 * 86'400s + 22s—end example]
utc_clock
is not aTrivialClock
unless the implementation can guarantee thatutc_clock::now()
does not propagate an exception. [Note:noexcept(from_sys(system_clock::now()))
isfalse
. — end note]static utc_clock::time_point utc_clock::now();Returns:
from_sys(system_clock::now())
, or a more accurate value ofutc_time
.template <typename Duration> static sys_time<common_type_t<Duration, seconds>> utc_clock::to_sys(const utc_time<Duration>& u);Returns: A
sys_time
t
, such thatfrom_sys(t) == u
if such a mapping exists. Otherwiseu
represents atime_point
during a leap second insertion and the last representable value ofsys_time
prior to the insertion of the leap second is returned.template <typename Duration> static utc_time<common_type_t<Duration, seconds>> utc_clock::from_sys(const sys_time<Duration>& t);Returns: A
utc_time
u
, such thatu.time_since_epoch() - t.time_since_epoch()
is equal to the number of leap seconds that were inserted betweent
and 1970-01-01. Ift
is exactly the date of leap second insertion, then the conversion counts that leap second as inserted.[Example:
auto t = sys_days{jul/1/2015} - 2ns; auto u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 25s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 25s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 26s); t += 1ns; u = utc_clock::from_sys(t); assert(u.time_since_epoch() - t.time_since_epoch() == 26s);— end example]
template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const utc_time<Duration>& t);Effects: Calls
to_stream(os, fmt, t)
, wherefmt
is a null-terminated array ofchar_t
containing"%F %T"
widened forcharT
.Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const utc_time<Duration>& tp);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with"UTC"
. If%z
is used (or a modified form of%z
), an offset of0min
will be formatted. Iftp
represents a time during a leap second insertion, and if a seconds field is formatted, the integral portion of that format shall be"60"
.Returns:
os
.[Example:
auto t = sys_days{jul/1/2015} - 500ms; auto u = clock_cast<utc_clock>(t); for (auto i = 0; i < 8; ++i, u += 250ms) cout << u << " UTC\n";Output:
2015-06-30 23:59:59.500 UTC 2015-06-30 23:59:59.750 UTC 2015-06-30 23:59:60.000 UTC 2015-06-30 23:59:60.250 UTC 2015-06-30 23:59:60.500 UTC 2015-06-30 23:59:60.750 UTC 2015-07-01 00:00:00.000 UTC 2015-07-01 00:00:00.250 UTC— end example]
template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, utc_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theutc_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null. Additionally, the parsed offset will be subtracted from the successfully parsed time stamp prior to assigning that difference totp
.Returns:
is
.
Add new section [time.clock.tai] after 23.17.7.2 Class utc_clock [time.clock.utc]:
23.17.7.3 Class tai_clock [time.clock.tai]
class tai_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<tai_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template <class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const tai_time<Duration>&) noexcept; template <class Duration> static tai_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>&) noexcept; };The clock
tai_clock
measures seconds since 1958-01-01 00:00:00 and is offset 10s ahead of UTC at this date. That is, 1958-01-01 00:00:00 TAI is equivalent to 1957-12-31 23:59:50 UTC. Leap seconds are not inserted into TAI. Therefore every time a leap second is inserted into UTC, UTC falls another second behind TAI. For example by 2000-01-01 there had been 22 leap seconds inserted so 2000-01-01 00:00:00 UTC is equivalent to 2000-01-01 00:00:32 TAI (22s plus the initial 10s offset).
tai_clock
is not aTrivialClock
unless the implementation can guarantee thattai_clock::now()
does not propagate an exception. [Note:noexcept(from_utc(utc_clock::now()))
isfalse
. — end note]static tai_clock::time_point tai_clock::now();Returns:
from_utc(utc_clock::now())
, or a more accurate value oftai_time
.template <class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const tai_time<Duration>& t) noexcept;Returns:
utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 378691210s
Note:
378691210s == sys_days{1970y/jan/1} - sys_days{1958y/jan/1} + 10s
template <class Duration> static tai_time<common_type_t<Duration, seconds>> tai_clock::from_utc(const utc_time<Duration>& t) noexcept;Returns:
tai_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 378691210s
Note:
378691210s == sys_days{1970y/jan/1} - sys_days{1958y/jan/1} + 10s
template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const tai_time<Duration>& t);Effects: Calls
to_stream(os, fmt, t)
, wherefmt
is a null-terminated array ofchar_t
containing"%F %T"
widened forcharT
.Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const tai_time<Duration>& tp);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with"TAI"
. If%z
is used (or a modified form of%z
), an offset of0min
will be formatted. The date and time formatted shall be equivalent to that formatted by asys_time
initialized with:sys_time<Duration>{tp.time_since_epoch()} - (sys_days{1970y/jan/1} - sys_days{1958y/jan/1})Returns:
os
.[Example:
auto st = sys_days{2000_y/jan/1}; auto tt = clock_cast<tai_clock>(st); cout << format("%F %T %Z == ", st) << format("%F %T %Z\n", tt);Output:
2000-01-01 00:00:00 UTC == 2000-01-01 00:00:32 TAI— end example]
template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, tai_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into thetai_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null. Additionally, the parsed offset will be subtracted from the successfully parsed time stamp prior to assigning that difference totp
.Returns:
is
.
Add new section [time.clock.gps] after 23.17.7.3 Class tai_clock [time.clock.tai]:
23.17.7.4 Class gps_clock [time.clock.gps]
class gps_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<gps_clock>; static constexpr bool is_steady = unspecified; static time_point now(); template <class Duration> static utc_time<common_type_t<Duration, seconds>> to_utc(const gps_time<Duration>&) noexcept; template <class Duration> static gps_time<common_type_t<Duration, seconds>> from_utc(const utc_time<Duration>&) noexcept; };The clock
gps_clock
measures seconds since The first Sunday of January, 1980 00:00:00 UTC. Leap seconds are not inserted into GPS. Therefore every time a leap second is inserted into UTC, UTC falls another second behind GPS. Aside from the offset from 1958y/jan/1 to 1980y/jan/sun[1] GPS is behind TAI by 19s due to the 10s offset between 1958 and 1970 and the additional 9 leap seconds inserted between 1970 and 1980.
gps_clock
is not aTrivialClock
unless the implementation can guarantee thatgps_clock::now()
does not propagate an exception. [Note:noexcept(from_utc(utc_clock::now()))
isfalse
. — end note]static gps_clock::time_point gps_clock::now();Returns:
from_utc(utc_clock::now())
, or a more accurate value ofgps_time
.template <class Duration> static utc_time<common_type_t<Duration, seconds>> gps_clock::to_utc(const gps_time<Duration>& t) noexcept;Returns:
gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 315964809s
Note:
315964809s == sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1} + 9s
template <class Duration> static gps_time<common_type_t<Duration, seconds>> gps_clock::from_utc(const utc_time<Duration>& t) noexcept;Returns:
gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 315964809s
Note:
315964809s == sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1} + 9s
template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const gps_time<Duration>& t);Effects: Calls
to_stream(os, fmt, t)
, wherefmt
is a null-terminated array ofchar_t
containing"%F %T"
widened forcharT
.Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const gps_time<Duration>& tp);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with"GPS"
. If%z
is used (or a modified form of%z
), an offset of0min
will be formatted. The date and time formatted shall be equivalent to that formatted by asys_time
initialized with:sys_time<Duration>{tp.time_since_epoch()} + (sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1})Returns:
os
.[Example:
auto st = sys_days{2000_y/jan/1}; auto gt = clock_cast<gps_clock>(st); cout << format("%F %T %Z == ", st) << format("%F %T %Z\n", gt);Output:
2000-01-01 00:00:00 UTC == 2000-01-01 00:00:13 GPS— end example]
template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, gps_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into thegps_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null. Additionally, the parsed offset will be subtracted from the successfully parsed time stamp prior to assigning that difference totp
.Returns:
is
.
Add new section [time.clock.file] after 23.17.7.4 Class gps_clock [time.clock.gps]:
23.17.7.5 Class file_clock [time.clock.file]
class file_clock { public: using rep = a signed arithmetic type; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<file_clock>; static constexpr bool is_steady = unspecified; static time_point now() noexcept; // Conversion functions, see below };The clock
file_clock
is used to create thetime_point
system used forfile_time_type
([filesystems]). It's epoch is unspecified.static file_clock::time_point file_clock::now();Returns: A
file_clock::time_point
indicating the current time.The class
file_clock
shall provide precisely one of the following two sets of static member functions:template <class Duration> static sys_time<some duration> to_sys(const file_time<Duration>&); template <class Duration> static file_time<some duration> from_sys(const sys_time<Duration>&);or:
template <class Duration> static utc_time<some duration> to_utc(const file_time<Duration>&); template <class Duration> static file_time<some duration> from_utc(const utc_time<Duration>&);These member functions shall provide
time_point
conversions consistent with those specified byutc_clock
,tai_clock
, andgps_clock
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const file_time<Duration>& t);Effects: Calls
to_stream(os, fmt, t)
, wherefmt
is a null-terminated array ofchar_t
containing"%F %T"
widened forcharT
.Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const file_time<Duration>& tp);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with"UTC"
. If%z
is used (or a modified form of%z
), an offset of0min
will be formatted. The date and time formatted shall be equivalent to that formatted by asys_time
initialized withclock_cast<system_clock>(tp)
, or by autc_time
initialized withclock_cast<utc_clock>(tp)
.Returns:
os
.template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, file_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into thefile_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null. Additionally, the parsed offset will be subtracted from the successfully parsed time stamp prior to assigning that difference totp
.Returns:
is
.
Add new section [time.clock.local_time] after 23.17.7.3 Class high_resolution_clock [time.clock.hres]:
23.17.7.8 local_time [time.clock.local_time]
The family of time points denoted by
local_time<Duration>
are based on the pseudo clocklocal_t
.local_t
has no membernow()
and thus does not meet the clock requirements. Neverthelesslocal_time<Duration>
serves the vital role of representing local time with respect to a not-yet-specified time zone. Aside from being able to get the current time, the completetime_point
algebra is available forlocal_time<Duration>
(just as forsys_time<Duration>
).template <class charT, class traits, class Duration> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_time<Duration>& lt);Effects:
os << sys_time<Duration>{lt.time_since_epoch()};Returns:
os
.template <class charT, class traits, class Duration> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const local_time<Duration>& tp, const string* abbrev = nullptr, const seconds* offset_sec = nullptr);Effects: Streams
tp
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format]. If%Z
is used, it will be replaced with*abbrev
ifabbrev
is not equal tonullptr
. Ifabbrev
is equal tonullptr
(and%Z
is used),ios_base::failbit
will be set. If%z
is used (or a modified form of%z
), it will be formatted with the value of*offset_sec
ifoffset_sec
is not equal tonullptr
. If%z
(or a modified form of%z
) is used, andoffset_sec
is equal tonullptr
, thenios_base::failbit
is set.Returns:
os
.template <class charT, class traits, class Duration, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, local_time<Duration>& tp, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into thelocal_time
tp
using the format flags as specified in [time.parse].If the parse fails to decode a valid date,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.
Add new section [time.clock.clock_cast] after 23.17.7.9 local_time [time.clock.local_time]:
23.17.7.9 clock_cast [time.clock.clock_cast]
template <class DestClock, class SourceClock> struct clock_time_conversion {};
clock_time_conversion
serves as trait which can be used to specify how to converttime_point<SourceClock, Duration>
totime_point<DestClock, Duration>
via a specialization:clock_time_conversion<DestClock, SourceClock>
. A specialization ofclock_time_conversion<DestClock, SourceClock>
shall provide aconst
-qualifiedoperator()
that takes a parameter of typetime_point<SourceClock, Duration>
and returns atime_point<DestClock, some duration>
representing an equivalent point in time. A program may specializeclock_time_conversion
if at least one of the template parameters is user-defined clock type.Several specializations are provided by the implementation:
// Identity template <typename Clock> struct clock_time_conversion<Clock, Clock> { template <class Duration> time_point<Clock, Duration> operator()(const time_point<Clock, Duration>& t) const; }; template <class Duration> time_point<Clock, Duration> operator()(const time_point<Clock, Duration>& t) const;Returns:
t
.template <> struct clock_time_conversion<system_clock, system_clock> { template <class Duration> sys_time<Duration> operator()(const sys_time<Duration>& t) const; }; template <class Duration> sys_time<Duration> operator()(const sys_time<Duration>& t) const;Returns:
t
.template <> struct clock_time_conversion<utc_clock, utc_clock> { template <class Duration> utc_time<Duration> operator()(const utc_time<Duration>& t) const; }; template <class Duration> utc_time<Duration> operator()(const utc_time<Duration>& t) const;Returns:
t
.// system_clock <-> utc_clocktemplate <> struct clock_time_conversion<utc_clock, system_clock> { template <class Duration> utc_time<common_type_t<Duration, seconds>> operator()(const sys_time<Duration>& t) const; }; template <class Duration> utc_time<common_type_t<Duration, seconds>> operator()(const sys_time<Duration>& t) const;Returns:
utc_clock::from_sys(t)
.template <> struct clock_time_conversion<system_clock, utc_clock> { template <class Duration> sys_time<common_type_t<Duration, seconds>> operator()(const utc_time<Duration>& t) const; }; template <class Duration> sys_time<common_type_t<Duration, seconds>> operator()(const utc_time<Duration>& t) const;Returns:
utc_clock::to_sys(t)
.// Clock <-> system_clocktemplate <class SourceClock> struct clock_time_conversion<system_clock, SourceClock> { template <class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_sys(t)); }; template <class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_sys(t));Remarks: This function does not participate in overload resolution unless
SourceClock::to_sys(t)
is well formed. IfSourceClock::to_sys(t)
does not returnsys_time<some duration>
the program is ill-formed.Returns:
SourceClock::to_sys(t)
.template <class DestClock> struct clock_time_conversion<DestClock, system_clock> { template <class Duration> auto operator()(const sys_time<Duration>& t) const -> decltype(DestClock::from_sys(t)); }; template <class Duration> auto operator()(const sys_time<Duration>& t) const -> decltype(DestClock::from_sys(t));Remarks: This function does not participate in overload resolution unless
DestClock::from_sys(t)
is well formed. IfDestClock::from_sys(t)
does not returntime_point<DestClock, some duration>
the program is ill-formed.Returns:
DestClock::from_sys(t)
.// Clock <-> utc_clocktemplate <class SourceClock> struct clock_time_conversion<utc_clock, SourceClock> { template <class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_utc(t)); }; template <class Duration> auto operator()(const time_point<SourceClock, Duration>& t) const -> decltype(SourceClock::to_utc(t));Remarks: This function does not participate in overload resolution unless
SourceClock::to_utc(t)
is well formed. IfSourceClock::to_utc(t)
does not returnutc_time<some duration>
the program is ill-formed.Returns:
SourceClock::to_utc(t)
.template <class DestClock> struct clock_time_conversion<DestClock, utc_clock> { template <class Duration> auto operator()(const utc_time<Duration>& t) const -> decltype(DestClock::from_utc(t)); }; template <class Duration> auto operator()(const utc_time<Duration>& t) const -> decltype(DestClock::from_utc(t));Remarks: This function does not participate in overload resolution unless
DestClock::from_utc(t)
is well formed. IfDestClock::from_utc(t)
does not returntime_point<DestClock, some duration>
the program is ill-formed..
Returns:
DestClock::from_utc(t)
.// clock_casttemplate <class DestClock, class SourceClock, class Duration> time_point<DestClock, some duration> clock_cast(const time_point<SourceClock, Duration>& t);Remarks: This function does not participate in overload resolution unless at least one of the following expressions are well formed:
clock_time_conversion<DestClock, SourceClock>{}(t)
- Exactly one of:
clock_time_conversion<DestClock, system_clock>{}( clock_time_conversion<system_clock, SourceClock>{}(t))
clock_time_conversion<DestClock, utc_clock>{}( clock_time_conversion<utc_clock, SourceClock>{}(t))
- Exactly one of:
clock_time_conversion<DestClock, utc_clock>{}( clock_time_conversion<utc_clock, system_clock>{}( clock_time_conversion<system_clock, SourceClock>{}(t)))
clock_time_conversion<DestClock, system_clock>{}( clock_time_conversion<system_clock, utc_clock>{}( clock_time_conversion<utc_clock, SourceClock>{}(t)))
Returns: The first expression in the above list that is well-formed. If item 1 is not well-formed and both expressions in item 2 are well-formed, the
clock_cast
is ambiguous (ill-formed). If items 1 and 2 are not well-formed and both expressions in item 3 are well-formed, theclock_cast
is ambiguous (ill-formed).
Add a new section 23.17.8 Formatting [time.format]:
If fmt
(P0645) moves forward
within the LEWG, this section can easily be reworked to plug into that facility
without loss of functionality. This will avoid two unrelated
format
facilities in the standard.
23.17.8 Formatting [time.format]
Each
format
overload specified in this section callsto_stream
unqualified, so as to enable argument dependent lookup ([basic.lookup.argdep]).template <class charT, class Streamable> basic_string<charT> format(const charT* fmt, const Streamable& s);Remarks: This function shall not participate in overload resolution unless
to_stream(declval<basic_ostream<charT>&>(), fmt, s)
is a valid expression.Effects: Constructs a local variable of type
basic_ostringstream<charT>
(for exposition purposes, namedos
). Executesos.exceptions(ios::failbit | ios::badbit)
. Then callsto_stream(os, fmt, s)
.Returns:
os.str()
.template <class charT, class Streamable> basic_string<charT> format(const locale& loc, const charT* fmt, const Streamable& s);Remarks: This function shall not participate in overload resolution unless
to_stream(declval<basic_ostream<charT>&>(), fmt, s)
is a valid expression.Effects: Constructs a local variable of type
basic_ostringstream<charT>
(for exposition purposes, namedos
). Executesos.exceptions(ios::failbit | ios::badbit)
. Then callsos.imbue(loc)
. Then callsto_stream(os, fmt, s)
.Returns:
os.str()
.template <class charT, class traits, class Alloc, class Streamable> basic_string<charT, traits, Alloc> format(const basic_string<charT, traits, Alloc>& fmt, const Streamable& s);Remarks: This function shall not participate in overload resolution unless
to_stream(declval<basic_ostringstream<charT, traits, Alloc>&>(), fmt.c_str(), s)
is a valid expression.Effects: Constructs a local variable of type
basic_ostringstream<charT, traits, Alloc>
(for exposition purposes, namedos
). Executesos.exceptions(ios::failbit | ios::badbit)
. Then callsto_stream(os, fmt.c_str(), s)
.Returns:
os.str()
.template <class charT, class traits, class Alloc, class Streamable> basic_string<charT, traits, Alloc> format(const locale& loc, const basic_string<charT, traits, Alloc>& fmt, const Streamable& s);Remarks: This function shall not participate in overload resolution unless
to_stream(declval<basic_ostringstream<charT, traits, Alloc>&>(), fmt.c_str(), s)
is a valid expression.Effects: Constructs a local variable of type
basic_ostringstream<charT, traits, Alloc>
(for exposition purposes, namedos
). Then callsos.imbue(loc)
. Executesos.exceptions(ios::failbit | ios::badbit)
. Then callsto_stream(os, fmt.c_str(), s)
.Returns:
os.str()
.The
format
functions call ato_stream
function with abasic_ostream
, a formatting string specifier, and aStreamable
argument. Eachto_stream
overload is customized for eachStreamable
type. However allto_stream
overloads treat the formatting string specifier according to the following specification:The
fmt
string consists of zero or more conversion specifiers and ordinary multibyte characters. A conversion specifier consists of a%
character, possibly followed by anE
orO
modifier character (described below), followed by a character that determines the behavior of the conversion specifier. All ordinary multibyte characters (excluding the terminating null character) are streamed unchanged into thebasic_ostream
.Each conversion specifier is replaced by appropriate characters as described in the following list. Some of the conversion specifiers depend on the locale which is imbued to the
basic_ostream
. If theStreamable
object does not contain the information the conversion specifier refers to, the value streamed to thebasic_ostream
is unspecified.Unless explicitly specified,
Streamable
types will not contain time zone abbreviation and time zone offset information. If available, the conversion specifiers%Z
and%z
will format this information (respectively). If the information is not available, and%Z
or%z
are contained infmt
,ios_base::failbit
will be set onos
.
%a
The locale's abbreviated weekday name. If the value does not contain a valid weekday
,ios::failbit
is set.%A
The locale's full weekday name. If the value does not contain a valid weekday
,ios::failbit
is set.%b
The locale's abbreviated month name. If the value does not contain a valid month
,ios::failbit
is set.%B
The locale's full month name. If the value does not contain a valid month
,ios::failbit
is set.%c
The locale's date and time representation. The modified command %Ec
produces the locale's alternate date and time representation.%C
The year divided by 100 using floored division. If the result is a single decimal digit, it is prefixed with 0
. The modified command%EC
produces the locale's alternative representation of the century.%d
The day of month as a decimal number. If the result is a single decimal digit, it is prefixed with 0
. The modified command%Od
produces the locale's alternative representation.%D
Equivalent to %m/%d/%y
.%e
The day of month as a decimal number. If the result is a single decimal digit, it is prefixed with a space. The modified command %Oe
produces the locale's alternative representation.%F
Equivalent to %Y-%m-%d
.%g
The last two decimal digits of the ISO week-based year. If the result is a single digit it is prefixed by 0
.%G
The ISO week-based year as a decimal number. If the result is less than four digits it is left-padded with 0
to four digits.%h
Equivalent to %b
.%H
The hour (24-hour clock) as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OH
produces the locale's alternative representation.%I
The hour (12-hour clock) as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OI
produces the locale's alternative representation.%j
The day of the year as a decimal number. Jan 1 is 001
. If the result is less than three digits, it is left-padded with0
to three digits.%m
The month as a decimal number. Jan is 01
. If the result is a single digit, it is prefixed with0
. The modified command%Om
produces the locale's alternative representation.%M
The minute as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OM
produces the locale's alternative representation.%n
A newline character. %p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock. %r
The locale's 12-hour clock time. %R
Equivalent to %H:%M
.%S
Seconds as a decimal number. If the number of seconds is less than 10, the result is prefixed with 0
. If the precision of the input can not be exactly represented with seconds, then the format is a decimal floating point number with a fixed format and a precision matching that of the precision of the input (or to a microseconds precision if the conversion to floating point decimal seconds can not be made within 18 fractional digits). The character for the decimal point is localized according to the locale. The modified command%OS
produces the locale's alternative representation.%t
A horizontal-tab character. %T
Equivalent to %H:%M:%S
.%u
The ISO weekday as a decimal number (1-7), where Monday is 1. The modified command %Ou
produces the locale's alternative representation.%U
The week number of the year as a decimal number. The first Sunday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. If the result is a single digit, it is prefixed with0
. The modified command%OU
produces the locale's alternative representation.%V
The ISO week-based week number as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OV
produces the locale's alternative representation.%w
The weekday as a decimal number (0-6), where Sunday is 0. The modified command %Ow
produces the locale's alternative representation.%W
The week number of the year as a decimal number. The first Monday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. If the result is a single digit, it is prefixed with0
. The modified command%OW
produces the locale's alternative representation.%x
The locale's date representation. The modified command %Ex
produces the locale's alternate date representation.%X
The locale's time representation. The modified command %Ex
produces the locale's alternate time representation.%y
The last two decimal digits of the year. If the result is a single digit it is prefixed by 0
.%Y
The year as a decimal number. If the result is less than four digits it is left-padded with 0
to four digits.%z
The offset from UTC in the ISO 8601 format. For example -0430
refers to 4 hours 30 minutes behind UTC. If the offset is zero,+0000
is used. The modified commands%Ez
and%Oz
insert a:
between the hours and minutes:-04:30
. If the offset information is not available,ios_base::failbit
will be set.%Z
The time zone abbreviation. If the time zone abbreviation is not available, ios_base::failbit
will be set.%%
A %
character.
Add a new section 23.17.9 Parsing [time.parse]:
23.17.9 Parsing [time.parse]
Each
parse
overload specified in this section callsfrom_stream
unqualified, so as to enable argument dependent lookup ([basic.lookup.argdep]).template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp);Remarks: This function shall not participate in overload resolution unless
from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp)
is a valid expression.Returns: A manipulator that when extracted from a
basic_istream<charT, traits> is
callsfrom_stream(is, fmt.c_str(), tp)
.template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev);Remarks: This function shall not participate in overload resolution unless
from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, &abbrev)
is a valid expression.Returns: A manipulator that when extracted from a
basic_istream<charT, traits> is
callsfrom_stream(is, fmt.c_str(), tp, &abbrev)
.template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, minutes& offset);Remarks: This function shall not participate in overload resolution unless
from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, nullptr, &offset)
is a valid expression.Returns: A manipulator that when extracted from a
basic_istream<charT, traits> is
callsfrom_stream(is, fmt.c_str(), tp, nullptr, &offset)
.template <class charT, class traits, class Alloc, class Parsable> unspecified parse(const basic_string<charT, traits, Alloc>& fmt, Parsable& tp, basic_string<charT, traits, Alloc>& abbrev, minutes& offset);Remarks: This function shall not participate in overload resolution unless
from_stream(declval<basic_istream<charT, traits>&>(), fmt.c_str(), tp, &abbrev, &offset)
is a valid expression.Returns: A manipulator that when extracted from a
basic_istream<charT, traits> is
callsfrom_stream(is, fmt.c_str(), tp, &abbrev, &offset)
.All
from_stream
overloads behave as an unformatted input function. 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 byE
orO
. During parsing each flag interprets characters as parts of date and time type according to the table below. Some flags can be modified by a width parameter which governs how many characters are parsed from the stream in interpreting the flag. All characters in the format string which are not represented in the table below, 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
from_stream
overload fails to parse everything specified by the format string, or if insufficient information is parsed to specify a complete duration, time point, or calendrical data structure,ios_base::failbit
is set in thebasic_istream
.
%a
The locale's full or abbreviated case-insensitive weekday name. %A
Equivalent to %a
.%b
The locale's full or abbreviated case-insensitive month name. %B
Equivalent to %b
.%c
The locale's date and time representation. The modified command %Ec
interprets the locale's alternate date and time representation.%C
The century as a decimal number. The modified command %NC
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands%EC
and%OC
interpret the locale's alternative representation of the century.%d
The day of the month as a decimal number. The modified command %Nd
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%EC
interprets the locale's alternative representation of the day of the month.%D
Equivalent to %m/%d/%y
.%e
Equivalent to %d
and can be modified like%d
.%F
Equivalent to %Y-%m-%d
. If modified with a width, the width is applied to only%Y
.%g
The last two decimal digits of the ISO week-based year. The modified command %Ng
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%G
The ISO week-based year as a decimal number. The modified command %NG
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 4. Leading zeroes are permitted but not required.%h
Equivalent to %b
.%H
The hour (24-hour clock) as a decimal number. The modified command %NH
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%OH
interprets the locale's alternative representation.%I
The hour (12-hour clock) as a decimal number. The modified command %NI
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%j
The day of the year as a decimal number. Jan 1 is 1
. The modified command%Nj
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 3. Leading zeroes are permitted but not required.%m
The month as a decimal number. Jan is 1
. The modified command%Nm
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%Om
interprets the locale's alternative representation.%M
The minutes as a decimal number. The modified command %NM
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%OM
interprets the locale's alternative representation.%n
Matches one white space character. [Note: %n
,%t
and a space, can be combined to match a wide range of white-space patterns. For example"%n "
matches one or more white space characters, and"%n%t%t"
matches one to three white space characters. — end note]%p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock. The command %I
must precede%p
in the format string.%r
The locale's 12-hour clock time. %R
Equivalent to %H:%M
.%S
The seconds as a decimal number. The modified command %NS
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2 if the input time has a precision convertible to seconds. Otherwise the default width is determined by the decimal precision of the input and the field is interpreted as a long double in a fixed format. If encountered, the locale determines the decimal point character. Leading zeroes are permitted but not required. The modified command%OS
interprets the locale's alternative representation.%t
Matches zero or one white space characters. %T
Equivalent to %H:%M:%S
.%u
The ISO weekday as a decimal number (1-7), where Monday is 1. The modified command %Nu
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 1. Leading zeroes are permitted but not required. The modified command%Ou
interprets the locale's alternative representation.%U
The week number of the year as a decimal number. The first Sunday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. The modified command%NU
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%V
The ISO week-based week number as a decimal number. The modified command %NV
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%w
The weekday as a decimal number (0-6), where Sunday is 0. The modified command %Nw
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 1. Leading zeroes are permitted but not required. The modified command%Ow
interprets the locale's alternative representation.%W
The week number of the year as a decimal number. The first Monday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. The modified command%NW
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%x
The locale's date representation. The modified command %Ex
produces the locale's alternate date representation.%X
The locale's time representation. The modified command %Ex
produces the locale's alternate time representation.%y
The last two decimal digits of the year. If the century is not otherwise specified (e.g. with %C
), values in the range [69 - 99] are presumed to refer to the years [1969 - 1999], and values in the range [00 - 68] are presumed to refer to the years [2000 - 2068]. The modified command%Ny
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands%Ey
and%Oy
interpret the locale's alternative representation.%Y
The year as a decimal number. The modified command %NY
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 4. Leading zeroes are permitted but not required. The modified command%EY
interprets the locale's alternative representation.%z
The offset from UTC in the ISO 8601 format. For example -0430
refers to 4 hours 30 minutes behind UTC. The modified commands%Ez
and%Oz
parse a:
between the hours and minutes and leading zeroes on the hour field are optional:-4:30
.%Z
The time zone abbreviation or name. A single word is parsed. This word can only contain characters from the basic source character set ([lex.charset] in the C++ standard) that are alphanumeric, or one of '_'
,'/'
,'-'
or'+'
.%%
A %
character is extracted.
Add new section [time.calendar] after 23.17.9 Clocks [time.parse]:
23.17.10 The civil calendar [time.calendar]
The types in this subclause describe the civil (Gregorian) calendar and its relationship to
sys_days
andlocal_days
.23.17.10.1 Class
last_spec
[time.calendar.last]The struct
last_spec
is used in conjunction with other calendar types to specify the last in a sequence. For example, depending on context, it can represent the last day of a month, or the last day of the week of a month.There is an
constexpr
object of this type namedlast
in thechrono_literals
namespace.struct last_spec { explicit last_spec() = default; };23.17.10.2 Class
day
[time.calendar.day]
day
represents a day of a month. It normally holds values in the range 1 to 31. However it may hold non-negative values outside this range. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intoday
's unspecified internal storage.day
is equality and less-than comparable, and participates in basic arithmetic withdays
representing the quantity between any twoday
's. One can form aday
literal withd
. And one can stream out aday
.day
has explicit conversions to and fromunsigned
.class day { unsigned char d_; // exposition only public: day() = default; explicit constexpr day(unsigned d) noexcept; constexpr day& operator++() noexcept; constexpr day operator++(int) noexcept; constexpr day& operator--() noexcept; constexpr day operator--(int) noexcept; constexpr day& operator+=(const days& d) noexcept; constexpr day& operator-=(const days& d) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const day& x, const day& y) noexcept; constexpr bool operator!=(const day& x, const day& y) noexcept; constexpr bool operator< (const day& x, const day& y) noexcept; constexpr bool operator> (const day& x, const day& y) noexcept; constexpr bool operator<=(const day& x, const day& y) noexcept; constexpr bool operator>=(const day& x, const day& y) noexcept; constexpr day operator+(const day& x, const days& y) noexcept; constexpr day operator+(const days& x, const day& y) noexcept; constexpr day operator-(const day& x, const days& y) noexcept; constexpr days operator-(const day& x, const day& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const day& d); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
day
is a trivially copyable class type.
day
is a standard-layout class type.
explicit constexpr day::day(unsigned d) noexcept;Effects: Constructs an object of type
day
by constructingd_
withd
. The value held is unspecified ifd
is not in the range[0, 255]
.constexpr day& day::operator++() noexcept;Effects:
++d_
.Returns:
*this
.constexpr day day::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr day& day::operator--() noexcept;Effects:
--d_
.Returns:
*this
.constexpr day day::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr day& day::operator+=(const days& d) noexcept;Effects:
*this = *this + d
.Returns:
*this
.constexpr day& day::operator-=(const days& d) noexcept;Effects:
*this = *this - d
.Returns:
*this
.constexpr explicit day::operator unsigned() const noexcept;Returns:
d_
.constexpr bool day::ok() const noexcept;Returns:
1 <= d_ && d_ <= 31
.constexpr bool operator==(const day& x, const day& y) noexcept;Returns:
unsigned{x} == unsigned{y}
.constexpr bool operator!=(const day& x, const day& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const day& x, const day& y) noexcept;Returns:
unsigned{x} < unsigned{y}
.constexpr bool operator> (const day& x, const day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const day& x, const day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const day& x, const day& y) noexcept;Returns:
!(x < y)
.constexpr day operator+(const day& x, const days& y) noexcept;Returns:
day{unsigned{x} + y.count()}
.constexpr day operator+(const days& x, const day& y) noexcept;Returns:
y + x
.constexpr day operator-(const day& x, const days& y) noexcept;Returns:
x + -y
.constexpr days operator-(const day& x, const day& y) noexcept;Returns:
days{static_cast<days::rep>(unsigned{x} - unsigned{y})}
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const day& d);Effects: Inserts a decimal integral text representation of
d
intoos
. Single digit values are prefixed with'0'
.Returns:
os
.template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const day& d);Effects: Streams
d
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, day& d, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theday d
using the format flags as specified in [time.parse].If the parse fails to decode a valid day,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.constexpr day operator "" d(unsigned long long d) noexcept;Returns:
day{static_cast<unsigned>(d)}
.23.17.10.3 Class
month
[time.calendar.month]
month
represents a month of a year. It normally holds values in the range 1 to 12. However it may hold non-negative values outside this range. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intomonth
's unspecified internal storage.month
is equality and less-than comparable, and participates in basic arithmetic withmonths
representing the quantity between any twomonth
's. One can stream out amonth
.month
has explicit conversions to and fromunsigned
. There are 12month
constants, one for each month of the year in thechrono_literals
namespace.class month { unsigned char m_; // exposition only public: month() = default; explicit constexpr month(unsigned m) noexcept; constexpr month& operator++() noexcept; constexpr month operator++(int) noexcept; constexpr month& operator--() noexcept; constexpr month operator--(int) noexcept; constexpr month& operator+=(const months& m) noexcept; constexpr month& operator-=(const months& m) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month& x, const month& y) noexcept; constexpr bool operator!=(const month& x, const month& y) noexcept; constexpr bool operator< (const month& x, const month& y) noexcept; constexpr bool operator> (const month& x, const month& y) noexcept; constexpr bool operator<=(const month& x, const month& y) noexcept; constexpr bool operator>=(const month& x, const month& y) noexcept; constexpr month operator+(const month& x, const months& y) noexcept; constexpr month operator+(const months& x, const month& y) noexcept; constexpr month operator-(const month& x, const months& y) noexcept; constexpr months operator-(const month& x, const month& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month& m); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month& m); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
month
is a trivially copyable class type.
month
is a standard-layout class type.
explicit constexpr month::month(unsigned m) noexcept;Effects: Constructs an object of type
month
by constructingm_
withm
. The value held is unspecified ifm
is not in the range[0, 255]
.constexpr month& month::operator++() noexcept;Effects: If
m_ < 12
,++m_
. Otherwise setsm_
to 1.Returns:
*this
.constexpr month month::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr month& month::operator--() noexcept;Effects: If
m_ > 1
,--m_
. Otherwise setsm_
to 12.Returns:
*this
.constexpr month month::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr month& month::operator+=(const months& m) noexcept;Effects:
*this = *this + m
.Returns:
*this
.constexpr month& month::operator-=(const months& m) noexcept;Effects:
*this = *this - m
.Returns:
*this
.constexpr explicit month::operator unsigned() const noexcept;Returns:
m_
.constexpr bool month::ok() const noexcept;Returns:
1 <= m_ && m_ <= 12
.constexpr bool operator==(const month& x, const month& y) noexcept;Returns:
unsigned{x} == unsigned{y}
.constexpr bool operator!=(const month& x, const month& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const month& x, const month& y) noexcept;Returns:
unsigned{x} < unsigned{y}
.constexpr bool operator> (const month& x, const month& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month& x, const month& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month& x, const month& y) noexcept;Returns:
!(x < y)
.constexpr month operator+(const month& x, const months& y) noexcept;Returns: A
month
for whichok() == true
and is found as if by incrementing (or decrementing ify < months{0}
)x
,y
times. Ifmonth.ok() == false
prior to this operation, behaves as if*this
is first brought into the range [1, 12] by modular arithmetic. [Note: For examplemonth{0}
becomesmonth{12}
, andmonth{13}
becomesmonth{1}
. — end note]Complexity: O(1) with respect to the value of
y
. [Note: Repeated increments or decrements is not a valid implementation. — end note]Example:
feb + months{11} == jan
.constexpr month operator+(const months& x, const month& y) noexcept;Returns:
y + x
.constexpr month operator-(const month& x, const months& y) noexcept;Returns:
x + -y
.constexpr months operator-(const month& x, const month& y) noexcept;Returns: If
x.ok() == true
andy.ok() == true
, returns a value ofmonths
in the range ofmonths{0}
tomonths{11}
inclusive. Otherwise the value returned is unspecified.Remarks: If
x.ok() == true
andy.ok() == true
, the returned valuem
shall satisfy the equality:y + m == x
.Example:
jan - feb == months{11}
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month& m);Effects: If
ok() == true
outputs the same string that would be output for the month field byasctime
. Otherwise outputsunsigned{m} << " is not a valid month"
.Returns:
os
.template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month& m);Effects: Streams
m
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month& m, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into themonth m
using the format flags as specified in [time.parse].If the parse fails to decode a valid month,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.23.17.10.4 Class
year
[time.calendar.year]
year
represents a year in the civil calendar. It shall represent values in the range[min(), max()]
. It can be constructed with anyint
value, which will be subsequently truncated to fit intoyear
's internal unspecified storage.year
is equality and less-than comparable, and participates in basic arithmetic withyears
representing the quantity between any twoyear
's. One can form ayear
literal withy
. And one can stream out ayear
.year
has explicit conversions to and fromint
.class year { short y_; // exposition only public: year() = default; explicit constexpr year(int y) noexcept; constexpr year& operator++() noexcept; constexpr year operator++(int) noexcept; constexpr year& operator--() noexcept; constexpr year operator--(int) noexcept; constexpr year& operator+=(const years& y) noexcept; constexpr year& operator-=(const years& y) noexcept; constexpr year operator+() const noexcept; constexpr year operator-() const noexcept; constexpr bool is_leap() const noexcept; constexpr explicit operator int() const noexcept; constexpr bool ok() const noexcept; static constexpr year min() noexcept; static constexpr year max() noexcept; }; constexpr bool operator==(const year& x, const year& y) noexcept; constexpr bool operator!=(const year& x, const year& y) noexcept; constexpr bool operator< (const year& x, const year& y) noexcept; constexpr bool operator> (const year& x, const year& y) noexcept; constexpr bool operator<=(const year& x, const year& y) noexcept; constexpr bool operator>=(const year& x, const year& y) noexcept; constexpr year operator+(const year& x, const years& y) noexcept; constexpr year operator+(const years& x, const year& y) noexcept; constexpr year operator-(const year& x, const years& y) noexcept; constexpr years operator-(const year& x, const year& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year& y); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year& y); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
year
is a trivially copyable class type.
year
is a standard-layout class type.
explicit constexpr year::year(int y) noexcept;Effects: Constructs an object of type
year
by constructingy_
withy
. The value held is unspecified ify
is not in the range[-32767, 32767]
.constexpr year& year::operator++() noexcept;Effects:
++y_
.Returns:
*this
.constexpr year year::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr year& year::operator--() noexcept;Effects:
--y_
.Returns:
*this
.constexpr year year::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr year& year::operator+=(const years& y) noexcept;Effects:
*this = *this + y
.Returns:
*this
.constexpr year& year::operator-=(const years& y) noexcept;Effects:
*this = *this - y
.Returns:
*this
.constexpr year& year::operator+() const noexcept;Returns:
*this
.constexpr year& year::operator-() const noexcept;Returns:
year{-y_}
.constexpr bool year::is_leap() const noexcept;Effects: Equivalent to:
return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0);
constexpr explicit year::operator int() const noexcept;Returns:
y_
.constexpr bool year::ok() const noexcept;Returns:
min() <= y_ && y_ <= max()
.static constexpr year year::min() noexcept;Returns:
-32767
.static constexpr year year::max() noexcept;Returns:
32767
.constexpr bool operator==(const year& x, const year& y) noexcept;Returns:
int{x} == int{y}
.constexpr bool operator!=(const year& x, const year& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year& x, const year& y) noexcept;Returns:
int{x} < int{y}
.constexpr bool operator> (const year& x, const year& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year& x, const year& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year& x, const year& y) noexcept;Returns:
!(x < y)
.constexpr year operator+(const year& x, const years& y) noexcept;Returns:
year{int{x} + y.count()}
.constexpr year operator+(const years& x, const year& y) noexcept;Returns:
y + x
.constexpr year operator-(const year& x, const years& y) noexcept;Returns:
x + -y
.constexpr years operator-(const year& x, const year& y) noexcept;Returns:
years{int{x} - int{y}}
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year& y);Effects: Inserts a signed decimal integral text representation of
y
intoos
. If the year is in the range [-999, 999], prefixes the year with'0'
to four digits. If the year is negative, prefixes with'-'
.Returns:
os
.template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year& y);Effects: Streams
y
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year& y, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theyear y
using the format flags as specified in [time.parse].If the parse fails to decode a valid year,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.constexpr year operator "" y(unsigned long long y) noexcept;Returns:
year{static_cast<int>(y)}
.23.17.10.5 Class
weekday
[time.calendar.weekday]
weekday
represents a day of the week in the civil calendar. It normally holds values in the range 0 to 6, corresponding to Sunday through Saturday. However it may hold non-negative values outside this range. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intoweekday
's unspecified internal storage.weekday
is equality comparable.weekday
is not less-than comparable because there is no universal consensus on which day is the first day of the week. This design chooses the encoding of 0 to 6 to represent Sunday through Saturday only because this is consistent with existing C and C++ practice. Howeverweekday
's comparison and arithmetic operations treat the days of the week as a circular range, with no beginning and no end. One can stream out aweekday
.weekday
has explicit conversions to and fromunsigned
. There are 7weekday
constants, one for each day of the week in thechrono_literals
namespace.A
weekday
can be implicitly constructed from asys_days
. This is the computation that discovers the day of the week of an arbitrary date.A
weekday
can be indexed with eitherunsigned
orlast
. This produces new types which represent the first, second, third, fourth, fifth or last weekdays of a month.class weekday { unsigned char wd_; // exposition only public: weekday() = default; explicit constexpr weekday(unsigned wd) noexcept; constexpr weekday(const sys_days& dp) noexcept; constexpr explicit weekday(const local_days& dp) noexcept; constexpr weekday& operator++() noexcept; constexpr weekday operator++(int) noexcept; constexpr weekday& operator--() noexcept; constexpr weekday operator--(int) noexcept; constexpr weekday& operator+=(const days& d) noexcept; constexpr weekday& operator-=(const days& d) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; constexpr weekday_indexed operator[](unsigned index) const noexcept; constexpr weekday_last operator[](last_spec) const noexcept; }; constexpr bool operator==(const weekday& x, const weekday& y) noexcept; constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; constexpr weekday operator+(const weekday& x, const days& y) noexcept; constexpr weekday operator+(const days& x, const weekday& y) noexcept; constexpr weekday operator-(const weekday& x, const days& y) noexcept; constexpr days operator-(const weekday& x, const weekday& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const weekday& wd); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
weekday
is a trivially copyable class type.
weekday
is a standard-layout class type.
explicit constexpr weekday::weekday(unsigned wd) noexcept;Effects: Constructs an object of type
weekday
by constructingwd_
withwd
. The value held is unspecified ifwd
is not in the range[0, 255]
.constexpr weekday(const sys_days& dp) noexcept;Effects: Constructs an object of type
weekday
by computing what day of the week corresponds to thesys_days dp
, and representing that day of the week inwd_
.Example: If
dp
represents 1970-01-01, the constructedweekday
represents Thursday by storing 4 inwd_
.constexpr explicit weekday(const local_days& dp) noexcept;Effects: Constructs an object of type
weekday
by computing what day of the week corresponds to thelocal_days dp
, and representing that day of the week inwd_
.The value after construction shall be identical to that constructed from
sys_days{dp.time_since_epoch()}
.constexpr weekday& weekday::operator++() noexcept;Effects: If
wd_ != 6
,++wd_
. Otherwise setswd_
to 0.Returns:
*this
.constexpr weekday weekday::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr weekday& weekday::operator--() noexcept;Effects: If
wd_ != 0
,--wd_
. Otherwise setswd_
to 6.Returns:
*this
.constexpr weekday weekday::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr weekday& weekday::operator+=(const days& d) noexcept;Effects:
*this = *this + d
.Returns:
*this
.constexpr weekday& weekday::operator-=(const days& d) noexcept;Effects:
*this = *this - d
.Returns:
*this
.constexpr explicit weekday::operator unsigned() const noexcept;Returns:
wd_
.constexpr bool weekday::ok() const noexcept;Returns:
wd_ <= 6
.constexpr weekday_indexed weekday::operator[](unsigned index) const noexcept;Returns:
{*this, index}
.constexpr weekday_last weekday::operator[](last_spec) const noexcept;Returns:
weekday_last{*this}
.constexpr bool operator==(const weekday& x, const weekday& y) noexcept;Returns:
unsigned{x} == unsigned{y}
.constexpr bool operator!=(const weekday& x, const weekday& y) noexcept;Returns:
!(x == y)
.constexpr weekday operator+(const weekday& x, const days& y) noexcept;Returns: A
weekday
for whichok() == true
and is found as if by incrementing (or decrementing ify < days{0}
)x
,y
times. Ifweekday.ok() == false
prior to this operation, behaves as if*this
is first brought into the range [0, 6] by modular arithmetic. [Note: For exampleweekday{7}
becomesweekday{0}
. — end note]Complexity: O(1) with respect to the value of
y
. [Note: Repeated increments or decrements is not a valid implementation. — end note]Example:
mon + days{6} == sun
.constexpr weekday operator+(const days& x, const weekday& y) noexcept;Returns:
y + x
.constexpr weekday operator-(const weekday& x, const days& y) noexcept;Returns:
x + -y
.constexpr days operator-(const weekday& x, const weekday& y) noexcept;Returns: If
x.ok() == true
andy.ok() == true
, returns a value ofdays
in the range ofdays{0}
todays{6}
inclusive. Otherwise the value returned is unspecified.Remarks: If
x.ok() == true
andy.ok() == true
, the returned valued
shall satisfy the equality:y + d == x
.Example:
sun - mon == days{6}
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday& wd);Effects: If
ok() == true
outputs the same string that would be output for the weekday field byasctime
. Otherwise outputsunsigned{wd} << " is not a valid weekday"
.Returns:
os
.template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const weekday& wd);Effects: Streams
wd
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, weekday& wd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theweekday wd
using the format flags as specified in [time.parse].If the parse fails to decode a valid weekday,
ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.23.17.10.6 Class
weekday_indexed
[time.calendar.weekday_indexed]
weekday_indexed
represents aweekday
and a small index in the range 1 to 5. This class is used to represent the first, second, third, fourth or fifth weekday of a month. It is most easily constructed by indexing aweekday
.[Example:
constexpr auto wdi = sun[2]; // wdi is the second Sunday of an as yet unspecified month static_assert(wdi.weekday() == sun); static_assert(wdi.index() == 2);— end example:]
class weekday_indexed { chrono::weekday wd_; // exposition only unsigned char index_; // exposition only public: weekday_indexed() = default; constexpr weekday_indexed(const chrono::weekday& wd, unsigned index) noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi);
weekday_indexed
is a trivially copyable class type.
weekday_indexed
is a standard-layout class type.
constexpr weekday_indexed::weekday_indexed(const chrono::weekday& wd, unsigned index) noexcept;Effects: Constructs an object of type
weekday_indexed
by constructingwd_
withwd
andindex_
withindex
. The values held are unspecified if!wd.ok()
orindex
is not in the range[1, 5]
.constexpr weekday weekday_indexed::weekday() const noexcept;Returns:
wd_
.constexpr unsigned weekday_indexed::index() const noexcept;Returns:
index_
.constexpr bool weekday_indexed::ok() const noexcept;Returns:
wd_.ok() && 1 <= index_ && index_ <= 5
.constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept;Returns:
x.weekday() == y.weekday() && x.index() == y.index()
.constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept;Returns:
!(x == y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_indexed& wdi);Effects: Equivalent to:
return os << wdi.weekday() << '[' << wdi.index() << ']';23.17.10.7 Class
weekday_last
[time.calendar.weekday_last]
weekday_last
represents the lastweekday
of a month. It is most easily constructed by indexing aweekday
withlast
.[Example:
constexpr auto wdl = sun[last]; // wdl is the last Sunday of an as yet unspecified month static_assert(wdl.weekday() == sun);— end example:]
class weekday_last { chrono::weekday wd_; // exposition only public: explicit constexpr weekday_last(const chrono::weekday& wd) noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl);
weekday_last
is a trivially copyable class type.
weekday_last
is a standard-layout class type.
explicit constexpr weekday_last::weekday_last(const chrono::weekday& wd) noexcept;Effects: Constructs an object of type
weekday_last
by constructingwd_
withwd
.constexpr weekday weekday_last::weekday() const noexcept;Returns:
wd_
.constexpr bool weekday_last::ok() const noexcept;Returns:
wd_.ok()
.constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept;Returns:
x.weekday() == y.weekday()
.constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept;Returns:
!(x == y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const weekday_last& wdl);Effects: Equivalent to:
return os << wdi.weekday() << "[last]";23.17.10.8 Class
month_day
[time.calendar.month_day]
month_day
represents a specificday
of a specificmonth
, but with an unspecifiedyear
. One can observe the different components. One can assign a new value.month_day
is equality comparable and less-than comparable. One can stream out amonth_day
.class month_day { chrono::month m_; // exposition only chrono::day d_; // exposition only public: month_day() = default; constexpr month_day(const chrono::month& m, const chrono::day& d) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::day day() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; constexpr bool operator!=(const month_day& x, const month_day& y) noexcept; constexpr bool operator< (const month_day& x, const month_day& y) noexcept; constexpr bool operator> (const month_day& x, const month_day& y) noexcept; constexpr bool operator<=(const month_day& x, const month_day& y) noexcept; constexpr bool operator>=(const month_day& x, const month_day& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day& md); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month_day& md); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
month_day
is a trivially copyable class type.
month_day
is a standard-layout class type.
constexpr month_day::month_day(const chrono::month& m, const chrono::day& d) noexcept;Effects: Constructs an object of type
month_day
by constructingm_
withm
, andd_
withd
.constexpr month month_day::month() const noexcept;Returns:
m_
.constexpr day month_day::day() const noexcept;Returns:
d_
.constexpr bool month_day::ok() const noexcept;Returns:
true
ifm_.ok()
is true, and if1d <= d_
, and ifd_ <=
the number of days in monthm_
. Form_ == feb
the number of days is considered to be 29. Otherwise returnsfalse
.constexpr bool operator==(const month_day& x, const month_day& y) noexcept;Returns:
x.month() == y.month() && x.day() == y.day()
constexpr bool operator!=(const month_day& x, const month_day& y) noexcept;Returns:
!(x == y)
constexpr bool operator< (const month_day& x, const month_day& y) noexcept;Returns: If
x.month() < y.month()
returnstrue
. Else ifx.month() > y.month()
returnsfalse
. Else returnsx.day() < y.day()
.constexpr bool operator> (const month_day& x, const month_day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month_day& x, const month_day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month_day& x, const month_day& y) noexcept;Returns:
!(x < y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day& md);Effects: Equivalent to:
return os << md.month() << '/' << md.day();template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const month_day& md);Effects: Streams
md
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, month_day& md, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into themonth_day md
using the format flags as specified in [time.parse].If the parse fails to decode a valid
month_day
,ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.23.17.10.9 Class
month_day_last
[time.calendar.month_day_last]
month_day_last
represents the lastday
of amonth
. It is most easily constructed using the expressionm/last
orlast/m
, wherem
is an expression with typemonth
.[Example:
constexpr auto mdl = feb/last; // mdl is the last day of February of an as yet unspecified year static_assert(mdl.month() == feb);— end example:]
class month_day_last { chrono::month m_; // exposition only public: constexpr explicit month_day_last(const chrono::month& m) noexcept; constexpr chrono::month month() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl);
month_day_last
is a trivially copyable class type.
month_day_last
is a standard-layout class type.
constexpr explicit month_day_last::month_day_last(const chrono::month& m) noexcept;Effects: Constructs an object of type
month_day_last
by constructingm_
withm
.constexpr month month_day_last::month() const noexcept;Returns:
m_
.constexpr bool month_day_last::ok() const noexcept;Returns:
m_.ok()
.constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept;Returns:
x.month() == y.month()
.constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(x == y)
constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept;Returns:
x.month() < y.month()
.constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(x < y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_day_last& mdl);Effects: Equivalent to:
return os << mdl.month() << "/last";23.17.10.10 Class
month_weekday
[time.calendar.month_weekday]
month_weekday
represents the nthweekday
of amonth
, of an as yet unspecifiedyear
. To do this themonth_weekday
stores amonth
and aweekday_indexed
.class month_weekday { chrono::month m_; // exposition only chrono::weekday_indexed wdi_; // exposition only public: constexpr month_weekday(const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday_indexed weekday_indexed() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd);
month_weekday
is a trivially copyable class type.
month_weekday
is a standard-layout class type.
constexpr month_weekday::month_weekday(const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept;Effects: Constructs an object of type
month_weekday
by constructingm_
withm
, andwdi_
withwdi
.constexpr month month_weekday::month() const noexcept;Returns:
m_
.constexpr weekday_indexed month_weekday::weekday_indexed() const noexcept;Returns:
wdi_
.constexpr bool month_weekday::ok() const noexcept;Returns:
m_.ok() && wdi_.ok()
.constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept;Returns:
x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed()
.constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept;Returns:
!(x == y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday& mwd);Effects: Equivalent to:
return os << mwd.month() << '/' << mwd.weekday_indexed();23.17.10.11 Class
month_weekday_last
[time.calendar.month_weekday_last]
month_weekday_last
represents the lastweekday
of amonth
, of an as yet unspecifiedyear
. To do this themonth_weekday_last
stores amonth
and aweekday_last
.class month_weekday_last { chrono::month m_; // exposition only chrono::weekday_last wdl_; // exposition only public: constexpr month_weekday_last(const chrono::month& m, const chrono::weekday_last& wdl) noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday_last weekday_last() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl);
month_weekday_last
is a trivially copyable class type.
month_weekday_last
is a standard-layout class type.
constexpr month_weekday_last::month_weekday_last(const chrono::month& m, const chrono::weekday_last& wdl) noexcept;Effects: Constructs an object of type
month_weekday_last
by constructingm_
withm
, andwdl_
withwdl
.constexpr month month_weekday_last::month() const noexcept;Returns:
m_
.constexpr weekday_last month_weekday_last::weekday_last() const noexcept;Returns:
wdl_
.constexpr bool month_weekday_last::ok() const noexcept;Returns:
m_.ok() && wdl_.ok()
.constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept;Returns:
x.month() == y.month() && x.weekday_last() == y.weekday_last()
.constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept;Returns:
!(x == y)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const month_weekday_last& mwdl);Effects: Equivalent to:
return os << mwdl.month() << '/' << mwdl.weekday_last();23.17.10.12 Class
year_month
[time.calendar.year_month]
year_month
represents a specificmonth
of a specificyear
, but with an unspecifiedday
.year_month
is a field-based time point with a resolution ofmonths
. One can observe the different components. One can assign a new value.year_month
is equality comparable and less-than comparable. One can stream out ayear_month
.class year_month { chrono::year y_; // exposition only chrono::month m_; // exposition only public: year_month() = default; constexpr year_month(const chrono::year& y, const chrono::month& m) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr year_month& operator+=(const months& dm) noexcept; constexpr year_month& operator-=(const months& dm) noexcept; constexpr year_month& operator+=(const years& dy) noexcept; constexpr year_month& operator-=(const years& dy) noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month& x, const year_month& y) noexcept; constexpr bool operator!=(const year_month& x, const year_month& y) noexcept; constexpr bool operator< (const year_month& x, const year_month& y) noexcept; constexpr bool operator> (const year_month& x, const year_month& y) noexcept; constexpr bool operator<=(const year_month& x, const year_month& y) noexcept; constexpr bool operator>=(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; constexpr months operator-(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month& ym); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month& ym); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
year_month
is a trivially copyable class type.
year_month
is a standard-layout class type.
constexpr year_month::year_month(const chrono::year& y, const chrono::month& m) noexcept;Effects: Constructs an object of type
year_month
by constructingy_
withy
, andm_
withm
.constexpr year year_month::year() const noexcept;Returns:
y_
.constexpr month year_month::month() const noexcept;Returns:
m_
.constexpr year_month& operator+=(const months& dm) noexcept;Effects:
*this = *this + dm
.Returns:
*this
.constexpr year_month& operator-=(const months& dm) noexcept;Effects:
*this = *this - dm
.Returns:
*this
.constexpr year_month& operator+=(const years& dy) noexcept;Effects:
*this = *this + dy
.Returns:
*this
.constexpr year_month& operator-=(const years& dy) noexcept;Effects:
*this = *this - dy
.Returns:
*this
.constexpr bool year_month::ok() const noexcept;Returns:
y_.ok() && m_.ok()
.constexpr bool operator==(const year_month& x, const year_month& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month()
constexpr bool operator!=(const year_month& x, const year_month& y) noexcept;Returns:
!(x == y)
constexpr bool operator< (const year_month& x, const year_month& y) noexcept;Returns: If
x.year() < y.year()
returnstrue
. Else ifx.year() > y.year()
returnsfalse
. Else returnsx.month() < y.month()
.constexpr bool operator> (const year_month& x, const year_month& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year_month& x, const year_month& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year_month& x, const year_month& y) noexcept;Returns:
!(x < y)
.constexpr year_month operator+(const year_month& ym, const months& dm) noexcept;Returns: A
year_month
valuez
such thatz - ym == dm
.Complexity: O(1) with respect to the value of
dm
.constexpr year_month operator+(const months& dm, const year_month& ym) noexcept;Returns:
ym + dm
.constexpr year_month operator-(const year_month& ym, const months& dm) noexcept;Returns:
ym + -dm
.constexpr months operator-(const year_month& x, const year_month& y) noexcept;Returns:
x.year() - y.year() + months{static_cast<int>(unsigned{x.month()}) - static_cast<int>(unsigned{y.month()})}
.constexpr year_month operator+(const year_month& ym, const years& dy) noexcept;Returns:
(ym.year() + dy) / ym.month()
.constexpr year_month operator+(const years& dy, const year_month& ym) noexcept;Returns:
ym + dy
.constexpr year_month operator-(const year_month& ym, const years& dy) noexcept;Returns:
ym + -dy
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month& ym);Effects: Equivalent to:
return os << ym.year() << '/' << ym.month();template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month& ym);Effects: Streams
ym
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month& ym, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theyear_month ym
using the format flags as specified in [time.parse].If the parse fails to decode a valid
year_month
,ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.23.17.10.13 Class
year_month_day
[time.calendar.year_month_day]
year_month_day
represents a specificyear
,month
, andday
.year_month_day
is a field-based time point with a resolution ofdays
. One can observe each field.year_month_day
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic. There is also a conversion fromsys_days
.year_month_day
is equality and less-than comparable.class year_month_day { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::day d_; // exposition only public: year_month_day() = default; constexpr year_month_day(const chrono::year& y, const chrono::month& m, const chrono::day& d) noexcept; constexpr year_month_day(const year_month_day_last& ymdl) noexcept; constexpr year_month_day(const sys_days& dp) noexcept; constexpr explicit year_month_day(const local_days& dp) noexcept; constexpr year_month_day& operator+=(const months& m) noexcept; constexpr year_month_day& operator-=(const months& m) noexcept; constexpr year_month_day& operator+=(const years& y) noexcept; constexpr year_month_day& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd); template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month_day& ymd); template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);
year_month_day
is a trivially copyable class type.
year_month_day
is a standard-layout class type.
constexpr year_month_day::year_month_day(const chrono::year& y, const chrono::month& m, const chrono::day& d) noexcept;Effects: Constructs an object of type
year_month_day
by constructingy_
withy
,m_
withm
, and,d_
withd
.constexpr year_month_day::year_month_day(const year_month_day_last& ymdl) noexcept;Effects: Constructs an object of type
year_month_day
by constructingy_
withymdl.year()
,m_
withymdl.month()
, and,d_
withymdl.day()
.Note: This conversion from
year_month_day_last
toyear_month_day
is more efficient than converting ayear_month_day_last
to asys_days
, and then converting thatsys_days
to ayear_month_day
.constexpr year_month_day::year_month_day(const sys_days& dp) noexcept;Effects: Constructs an object of type
year_month_day
which corresponds to the date represented bydp
.Remarks: For any value of
year_month_day
,ymd
, for whichymd.ok()
istrue
, this equality will also betrue
:ymd == year_month_day{sys_days{ymd}}
.constexpr explicit year_month_day::year_month_day(const local_days& dp) noexcept;Effects: Constructs an object of type
year_month_day
which corresponds to the date represented bydp
.Remarks: Equivalent to constructing with
sys_days{dp.time_since_epoch()}
.constexpr year_month_day& year_month_day::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_day::year() const noexcept;Returns:
y_
.constexpr month year_month_day::month() const noexcept;Returns:
m_
.constexpr day year_month_day::day() const noexcept;Returns:
d_
.constexpr year_month_day::operator sys_days() const noexcept;Returns: If
ok()
, returns asys_days
holding a count ofdays
from thesys_days
epoch to*this
(a negative value if*this
represents a date prior to thesys_days
epoch). Otherwise ify_.ok() && m_.ok() == true
returns asys_days
which is offset fromsys_days{y_/m_/last}
by the number ofdays
d_
is offset fromsys_days{y_/m_/last}.day()
. Otherwise the value returned is unspecified.Remarks: A
sys_days
in the range[days{-12687428}, days{11248737}]
which is converted to ayear_month_day
, shall have the same value when converted back to asys_days
.[Example:
static_assert(year_month_day{sys_days{2017y/jan/0}} == 2016y/dec/31); static_assert(year_month_day{sys_days{2017y/jan/31}} == 2017y/jan/31); static_assert(year_month_day{sys_days{2017y/jan/32}} == 2017y/feb/1);—end example]
constexpr explicit year_month_day::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};constexpr bool year_month_day::ok() const noexcept;Returns: If
y_.ok()
istrue
, andm_.ok()
istrue
, andd_
is in the range[1d, (y_/m_/last).day()]
, then returnstrue
, else returnsfalse
.constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.day() == y.day()
.constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept;Returns: If
x.year() < y.year()
, returnstrue
. Else ifx.year() > y.year()
returnsfalse
. Else ifx.month() < y.month()
, returnstrue
. Else ifx.month() > y.month()
, returnsfalse
. Else returnsx.day() < y.day()
.constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(x < y)
.constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;Returns:
(ymd.year() / ymd.month() + dm) / ymd.day()
.Remarks: If
ymd.day()
is in the range[1d, 28d]
, the resultantyear_month_day
shall returntrue
fromok()
.constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept;Returns:
ymd + dm
.constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept;Returns:
ymd + (-dm)
.constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;Returns:
(ymd.year() + dy) / ymd.month() / ymd.day()
.Remarks: If
ymd.month()
isfeb
andymd.day()
is not in the range[1d, 28d]
, the resultantyear_month_day
may returnfalse
fromok()
.constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept;Returns:
ymd + dy
.constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept;Returns:
ymd + (-dy)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day& ymd);Effects: Inserts
yyyy-mm-dd
where the number of indicated digits are prefixed with'0'
if necessary.Returns:
os
.template <class charT, class traits> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const year_month_day& ymd);Effects: Streams
ymd
intoos
using the format specified by the null-terminated arrayfmt
.fmt
encoding follows the rules specified by [time.format].Returns:
os
.template <class charT, class traits, class Alloc = allocator<charT>> basic_istream<charT, traits>& from_stream(basic_istream<charT, traits>& is, const charT* fmt, year_month_day& ymd, basic_string<charT, traits, Alloc>* abbrev = nullptr, minutes* offset = nullptr);Effects: Attempts to parse the input stream
is
into theyear_month_day ymd
using the format flags as specified in [time.parse].If the parse fails to decode a valid
year_month_day
,ios_base::failbit
will be set.If
%Z
is used and successfully parsed, that value will be assigned to*abbrev
ifabbrev
is non-null.If
%z
(or a modified variant) is used and successfully parsed, that value will be assigned to*offset
ifoffset
is non-null.Returns:
is
.23.17.10.14 Class
year_month_day_last
[time.calendar.year_month_day_last]
year_month_day_last
represents a specificyear
,month
, and the lastday
of themonth
.year_month_day_last
is a field-based time point with a resolution ofdays
, except that it is restricted to pointing to the last day of a year and month. One can observe each field. Theday
field is computed on demand.year_month_day_last
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_day_last
is equality and less-than comparable.class year_month_day_last { chrono::year y_; // exposition only chrono::month_day_last mdl_; // exposition only public: constexpr year_month_day_last(const chrono::year& y, const chrono::month_day_last& mdl) noexcept; constexpr year_month_day_last& operator+=(const months& m) noexcept; constexpr year_month_day_last& operator-=(const months& m) noexcept; constexpr year_month_day_last& operator+=(const years& y) noexcept; constexpr year_month_day_last& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::month_day_last month_day_last() const noexcept; constexpr chrono::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator> (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept; constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl);
year_month_day_last
is a trivially copyable class type.
year_month_day_last
is a standard-layout class type.
constexpr year_month_day_last::year_month_day_last(const chrono::year& y, const chrono::month_day_last& mdl) noexcept;Effects: Constructs an object of type
year_month_day_last
by constructingy_
withy
andmdl_
withmdl
.constexpr year_month_day_last& year_month_day_last::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_day_last::year() const noexcept;Returns:
y_
.constexpr month year_month_day_last::month() const noexcept;Returns:
mdl_.month()
.constexpr month_day_last year_month_day_last::month_day_last() const noexcept;Returns:
mdl_
.constexpr day year_month_day_last::day() const noexcept;Returns: A
day
representing the last day of theyear
,month
pair represented by*this
.constexpr year_month_day_last::operator sys_days() const noexcept;Effects: Equivalent to:
return sys_days{year()/month()/day()};
constexpr explicit year_month_day_last::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_day_last::ok() const noexcept;Returns:
y_.ok() && mdl_.ok()
.constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
x.year() == y.year() && x.month_day_last() == y.month_day_last()
.constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns: If
x.year() < y.year()
, returnstrue
. Else ifx.year() > y.year()
returnsfalse
. Else returnsx.month_day_last() < y.month_day_last()
.constexpr bool operator> (const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(x < y)
.constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept;Effects: Equivalent to:
return (ymdl.year() / ymdl.month() + dm) / last
.constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept;Returns:
ymdl + dm
.constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept;Returns:
ymdl + (-dm)
.constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept;Returns:
{ymdl.year()+dy, ymdl.month_day_last()}
.constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept;Returns:
ymdl + dy
.constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept;Returns:
ymdl + (-dy)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_day_last& ymdl);Effects: Equivalent to:
return os << ymdl.year() << '/' << ymdl.month_day_last();23.17.10.15 Class
year_month_weekday
[time.calendar.year_month_weekday]
year_month_weekday
represents a specificyear
,month
, and nthweekday
of themonth
.year_month_weekday
is a field-based time point with a resolution ofdays
. One can observe each field.year_month_weekday
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_weekday
is equality comparable.class year_month_weekday { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::weekday_indexed wdi_; // exposition only public: year_month_weekday() = default; constexpr year_month_weekday(const chrono::year& y, const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept; constexpr year_month_weekday(const sys_days& dp) noexcept; constexpr explicit year_month_weekday(const local_days& dp) noexcept; constexpr year_month_weekday& operator+=(const months& m) noexcept; constexpr year_month_weekday& operator-=(const months& m) noexcept; constexpr year_month_weekday& operator+=(const years& y) noexcept; constexpr year_month_weekday& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr chrono::weekday_indexed weekday_indexed() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept; constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwdi);
year_month_weekday
is a trivially copyable class type.
year_month_weekday
is a standard-layout class type.
constexpr year_month_weekday::year_month_weekday(const chrono::year& y, const chrono::month& m, const chrono::weekday_indexed& wdi) noexcept;Effects: Constructs an object of type
year_month_weekday
by constructingy_
withy
,m_
withm
, andwdi_
withwdi
.constexpr year_month_weekday(const sys_days& dp) noexcept;Effects: Constructs an object of type
year_month_weekday
which corresponds to the date represented bydp
.Remarks: For any value of
year_month_weekday
,ymdl
, for whichymdl.ok()
istrue
, this equality will also betrue
:ymdl == year_month_weekday{sys_days{ymdl}}
.constexpr explicit year_month_weekday(const local_days& dp) noexcept;Effects: Constructs an object of type
year_month_weekday
which corresponds to the date represented bydp
.Remarks: Equivalent to constructing with
sys_days{dp.time_since_epoch()}
.constexpr year_month_weekday& year_month_weekday::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_weekday::year() const noexcept;Returns:
y_
.constexpr month year_month_weekday::month() const noexcept;Returns:
m_
.constexpr weekday year_month_weekday::weekday() const noexcept;Returns:
wdi_.weekday()
.constexpr unsigned year_month_weekday::index() const noexcept;Returns:
wdi_.index()
.constexpr weekday_indexed year_month_weekday::weekday_indexed() const noexcept;Returns:
wdi_
.constexpr year_month_weekday::operator sys_days() const noexcept;Returns: If
y_.ok() && m_.ok() && wdi_.weekday().ok()
, returns asys_days
which represents the date(index() - 1)*7
days after the firstweekday()
ofyear()/month()
. Ifindex()
is0
the returnedsys_days
represents the date 7 days prior to the firstweekday()
ofyear()/month()
. Otherwise,!y_.ok() || !m_.ok() || !wdi_.weekday().ok()
and the returned value is unspecified.constexpr explicit year_month_weekday::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_weekday::ok() const noexcept;Returns: If
y_.ok()
orm_.ok()
orwdi_.ok()
returnsfalse
, returnsfalse
. Else if*this
represents a valid date, returnstrue
, else returnsfalse
.constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed()
.constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept;Returns:
!(x == y)
.constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept;Returns:
(ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed()
.constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept;Returns:
ymwd + dm
.constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept;Returns:
ymwd + (-dm)
.constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept;Returns:
{ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}
.constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept;Returns:
ymwd + dm
.constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept;Returns:
ymwd + (-dm)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday& ymwd);Effects: Equivalent to:
return os << ymwdi.year() << '/' << ymwdi.month() << '/' << ymwdi.weekday_indexed();23.17.10.16 Class
year_month_weekday_last
[time.calendar.year_month_weekday_last]
year_month_weekday_last
represents a specificyear
,month
, and lastweekday
of themonth
.year_month_weekday_last
is a field-based time point with a resolution ofdays
, except that it is restricted to pointing to the last weekday of a year and month. One can observe each field.year_month_weekday_last
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_weekday_last
is equality comparable.class year_month_weekday_last { chrono::year y_; // exposition only chrono::month m_; // exposition only chrono::weekday_last wdl_; // exposition only public: constexpr year_month_weekday_last(const chrono::year& y, const chrono::month& m, const chrono::weekday_last& wdl) noexcept; constexpr year_month_weekday_last& operator+=(const months& m) noexcept; constexpr year_month_weekday_last& operator-=(const months& m) noexcept; constexpr year_month_weekday_last& operator+=(const years& y) noexcept; constexpr year_month_weekday_last& operator-=(const years& y) noexcept; constexpr chrono::year year() const noexcept; constexpr chrono::month month() const noexcept; constexpr chrono::weekday weekday() const noexcept; constexpr chrono::weekday_last weekday_last() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl);
year_month_weekday_last
is a trivially copyable class type.
year_month_weekday_last
is a standard-layout class type.
constexpr year_month_weekday_last::year_month_weekday_last(const chrono::year& y, const chrono::month& m, const chrono::weekday_last& wdl) noexcept;Effects: Constructs an object of type
year_month_weekday_last
by constructingy_
withy
,m_
withm
, andwdl_
withwdl
.constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_weekday_last::year() const noexcept;Returns:
y_
.constexpr month year_month_weekday_last::month() const noexcept;Returns:
m_
.constexpr weekday year_month_weekday_last::weekday() const noexcept;Returns:
wdl_.weekday()
.constexpr weekday_last year_month_weekday_last::weekday_last() const noexcept;Returns:
wdl_
.constexpr year_month_weekday_last::operator sys_days() const noexcept;Returns: If
ok() == true
, returns asys_days
which represents the lastweekday()
ofyear()/month()
. Otherwise the returned value is unspecified.constexpr explicit year_month_weekday_last::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_weekday_last::ok() const noexcept;Returns: If
y_.ok() && m_.ok() && wdl_.ok()
.constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.weekday_last() == y.weekday_last()
.constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;Returns:
!(x == y)
.constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept;Effects: Equivalent to:
return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last()
.constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept;Returns:
ymwdl + dm
.constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept;Returns:
ymwdl + (-dm)
.constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept;Returns:
{ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}
.constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept;Returns:
ymwdl + dy
.constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept;Returns:
ymwdl + (-dy)
.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const year_month_weekday_last& ymwdl);Effects: Equivalent to:
return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last();23.17.10.17 civil calendar conventional syntax operators [time.calendar.operators]
A set of overloaded
operator/()
provide a conventional syntax for the creation of civil calendar dates. The year, month and day ordering are accepted in any of the following 3 orders:
y/m/d
m/d/y
d/m/y
Anywhere a "day" is required one can also specify one of:
last
weekday[i]
weekday[last]
Partial-date-types such as
year_month
andmonth_day
can be created by simply not applying the second division operator for any of the three orders. For example:year_month ym = 2015y/apr; month_day md1 = apr/4; month_day md2 = 4d/apr;Everything not intended as above is ill-formed, with the notable exception of an expression that consists of nothing but
int
, which has typeint
.auto a = 2015/4/4; // a == int(125) auto b = 2015y/4/4; // b == year_month_day{year(2015), month(4), day(4)} auto c = 2015y/4d/apr; // error: invalid operands to binary expression ('chrono::year' and 'chrono::day') auto d = 2015/apr/4; // error: invalid operands to binary expression ('int' and 'const chrono::month')
year_month
:constexpr year_month operator/(const year& y, const month& m) noexcept;Returns:{y, m}
.constexpr year_month operator/(const year& y, int m) noexcept;Returns:y / month(m)
.
month_day
:constexpr month_day operator/(const month& m, const day& d) noexcept;Returns:{m, d}
.constexpr month_day operator/(const month& m, int d) noexcept;Returns:m / day(d)
.constexpr month_day operator/(int m, const day& d) noexcept;Returns:month(m) / d
.constexpr month_day operator/(const day& d, const month& m) noexcept;Returns:m / d
.constexpr month_day operator/(const day& d, int m) noexcept;Returns:month(m) / d
.
month_day_last
:constexpr month_day_last operator/(const month& m, last_spec) noexcept;Returns:month_day_last{m}
.constexpr month_day_last operator/(int m, last_spec) noexcept;Returns:month(m) / last
.constexpr month_day_last operator/(last_spec, const month& m) noexcept;Returns:m / last
.constexpr month_day_last operator/(last_spec, int m) noexcept;Returns:month(m) / last
.
month_weekday
:constexpr month_weekday operator/(const month& m, const weekday_indexed& wdi) noexcept;Returns:{m, wdi}
.constexpr month_weekday operator/(int m, const weekday_indexed& wdi) noexcept;Returns:month(m) / wdi
.constexpr month_weekday operator/(const weekday_indexed& wdi, const month& m) noexcept;Returns:m / wdi
.constexpr month_weekday operator/(const weekday_indexed& wdi, int m) noexcept;Returns:month(m) / wdi
.
month_weekday_last
:constexpr month_weekday_last operator/(const month& m, const weekday_last& wdl) noexcept;Returns:{m, wdl}
.constexpr month_weekday_last operator/(int m, const weekday_last& wdl) noexcept;Returns:month(m) / wdl
.constexpr month_weekday_last operator/(const weekday_last& wdl, const month& m) noexcept;Returns:m / wdl
.constexpr month_weekday_last operator/(const weekday_last& wdl, int m) noexcept;Returns:month(m) / wdl
.
year_month_day
:constexpr year_month_day operator/(const year_month& ym, const day& d) noexcept;Returns:{ym.year(), ym.month(), d}
.constexpr year_month_day operator/(const year_month& ym, int d) noexcept;Returns:ym / day(d)
.constexpr year_month_day operator/(const year& y, const month_day& md) noexcept;Returns:y / md.month() / md.day()
.constexpr year_month_day operator/(int y, const month_day& md) noexcept;Returns:year(y) / md
.constexpr year_month_day operator/(const month_day& md, const year& y) noexcept;Returns:y / md
.constexpr year_month_day operator/(const month_day& md, int y) noexcept;Returns:year(y) / md
.
year_month_day_last
:constexpr year_month_day_last operator/(const year_month& ym, last_spec) noexcept;Returns:{ym.year(), month_day_last{ym.month()}}
.constexpr year_month_day_last operator/(const year& y, const month_day_last& mdl) noexcept;Returns:{y, mdl}
.constexpr year_month_day_last operator/(int y, const month_day_last& mdl) noexcept;Returns:year(y) / mdl
.constexpr year_month_day_last operator/(const month_day_last& mdl, const year& y) noexcept;Returns:y / mdl
.constexpr year_month_day_last operator/(const month_day_last& mdl, int y) noexcept;Returns:year(y) / mdl
.
year_month_weekday
:constexpr year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) noexcept;Returns:{ym.year(), ym.month(), wdi}
.constexpr year_month_weekday operator/(const year& y, const month_weekday& mwd) noexcept;Returns:{y, mwd.month(), mwd.weekday_indexed()}
.constexpr year_month_weekday operator/(int y, const month_weekday& mwd) noexcept;Returns:year(y) / mwd
.constexpr year_month_weekday operator/(const month_weekday& mwd, const year& y) noexcept;Returns:y / mwd
.constexpr year_month_weekday operator/(const month_weekday& mwd, int y) noexcept;Returns:year(y) / mwd
.
year_month_weekday_last
:constexpr year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) noexcept;Returns:{ym.year(), ym.month(), wdl}
.constexpr year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) noexcept;Returns:{y, mwdl.month(), mwdl.weekday_last()}
.constexpr year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) noexcept;Returns:year(y) / mwdl
.constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) noexcept;Returns:y / mwdl
.constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) noexcept;Returns:year(y) / mwdl
.
Add new section [time.time_of_day] after 23.17.10 The civil calendar [time.calendar]:
23.17.11 Class
time_of_day
[time.time_of_day]The
time_of_day
class breaks aduration
which represents the time elapsed since midnight, into a "broken" down time such as hours:minutes:seconds. TheDuration
template parameter dictates the precision to which the time is broken down. This can vary from a course precision of hours to a very fine precision of nanoseconds.time_of_day
is primarily a formatting tool.template <class Duration> class time_of_day;There are 4 specializations of
time_of_day
to handle four precisions:
template <> class time_of_day<hours>This specialization handles hours since midnight.
template <> class time_of_day<minutes>This specialization handles hours:minutes since midnight.
template <> class time_of_day<seconds>This specialization handles hours:minutes:seconds since midnight.
template <class Rep, class Period> class time_of_day<duration<Rep, Period>>This specialization is restricted to
Rep
types that are integral, andPeriod
s that are not an integral number of seconds. Typical uses are with milliseconds, microseconds and nanoseconds. This specialization handles hours:minute:seconds.fractional_seconds since midnight.Each specialization of
time_of_day
is a trivially copyable class type.
Each specialization oftime_of_day
is a standard-layout class type.
template <> class time_of_day<hours> { public: using precision = hours; time_of_day() = default; constexpr explicit time_of_day(hours since_midnight) noexcept; constexpr hours hours() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; constexpr void make24() noexcept; constexpr void make12() noexcept; };constexpr explicit time_of_day<hours>::time_of_day(hours since_midnight) noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding tosince_midnight
hours after 00:00:00.Postconditions:
hours()
returns the integral number of hourssince_midnight
is after 00:00:00.constexpr hours time_of_day<hours>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr explicit time_of_day<hours>::operator precision() const noexcept;Returns: The number of hours since midnight.
constexpr precision to_duration() const noexcept;Returns:
precision{*this}
.constexpr void time_of_day<hours>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.constexpr void time_of_day<hours>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<hours>& t);Effects: If
t
is a 24-hour time, outputs toos
according to the format: "%H00" ([time.format]). Elset
is a 12-hour time, outputs toos
according to the format: "%I%p" ([time.format]).Returns:
os
.Example:
0100 // 1 in the morning in 24-hour format 1800 // 6 in the evening in 24-hour format 1am // 1 in the morning in 12-hour format 6pm // 6 in the evening in 12-hour formattemplate <> class time_of_day<minutes> { public: using precision = minutes; time_of_day() = default; constexpr explicit time_of_day(minutes since_midnight) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; void make24() noexcept; void make12() noexcept; };constexpr explicit time_of_day<minutes>::time_of_day(minutes since_midnight) noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding tosince_midnight
minutes after 00:00:00.Postconditions:
hours()
returns the integral number of hourssince_midnight
is after 00:00:00.minutes()
returns the integral number of minutessince_midnight
is after (00:00:00 +hours()
).constexpr hours time_of_day<minutes>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr minutes time_of_day<minutes>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr explicit time_of_day<minutes>::operator precision() const noexcept;Returns: The number of minutes since midnight.
constexpr precision to_duration() const noexcept;Returns:
precision{*this}
.void time_of_day<minutes>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<minutes>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<minutes>& t);Effects: If
t
is a 24-hour time, outputs toos
according to the format: "%H:%M" ([time.format]). Elset
is a 12-hour time, outputs toos
according to the format: "%I:%M%p" ([time.format]).Returns:
os
.Example:
01:08 // 1:08 in the morning in 24-hour format 18:15 // 6:15 in the evening in 24-hour format 1:08am // 1:08 in the morning in 12-hour format 6:15pm // 6:15 in the evening in 12-hour formattemplate <> class time_of_day<seconds> { public: using precision = seconds; time_of_day() = default; constexpr explicit time_of_day(seconds since_midnight) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr seconds seconds() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; void make24() noexcept; void make12() noexcept; };constexpr explicit time_of_day<seconds>::time_of_day(seconds since_midnight) noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding tosince_midnight
seconds after 00:00:00.Postconditions:
hours()
returns the integral number of hourssince_midnight
is after 00:00:00.minutes()
returns the integral number of minutessince_midnight
is after (00:00:00 +hours()
).seconds()
returns the integral number of secondssince_midnight
is after (00:00:00 +hours()
+minutes()
).constexpr hours time_of_day<seconds>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr minutes time_of_day<seconds>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr seconds time_of_day<seconds>::seconds() const noexcept;Returns: The stored second of
*this
.constexpr explicit time_of_day<seconds>::operator precision() const noexcept;Returns: The number of seconds since midnight.
constexpr precision to_duration() const noexcept;Returns:
precision{*this}
.void time_of_day<seconds>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<seconds>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<seconds>& t);Effects: If
t
is a 24-hour time, outputs toos
according to the format: "%T" ([time.format]). Elset
is a 12-hour time, outputs toos
according to the format: "%I:%M%:S%p" ([time.format]).Returns:
os
.Example:
01:08:03 // 1:08:03 in the morning in 24-hour format 18:15:45 // 6:15:45 in the evening in 24-hour format 1:08:03am // 1:08:03 in the morning in 12-hour format 6:15:45pm // 6:15:45 in the evening in 12-hour formattemplate <class Rep, class Period> class time_of_day<duration<Rep, Period>> { public: using precision = duration<Rep, Period>; time_of_day() = default; constexpr explicit time_of_day(precision since_midnight) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr seconds seconds() const noexcept; constexpr precision subseconds() const noexcept; constexpr explicit operator precision() const noexcept; constexpr precision to_duration() const noexcept; void make24() noexcept; void make12() noexcept; };This specialization shall not exist unless
treat_as_floating_point<Rep>::value
isfalse
andduration<Rep, Period>
is not convertible toseconds
.constexpr explicit time_of_day<duration<Rep, Period>>::time_of_day(precision since_midnight) noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding tosince_midnight precision
fractional seconds after 00:00:00.Postconditions:
hours()
returns the integral number of hourssince_midnight
is after 00:00:00.minutes()
returns the integral number of minutessince_midnight
is after (00:00:00 +hours()
).seconds()
returns the integral number of secondssince_midnight
is after (00:00:00 +hours()
+minutes()
).subseconds()
returns the integral number of fractional precision secondssince_midnight
is after (00:00:00 +hours()
+minutes()
+seconds
).constexpr hours time_of_day<duration<Rep, Period>>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr minutes time_of_day<duration<Rep, Period>>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr seconds time_of_day<duration<Rep, Period>>::seconds() const noexcept;Returns: The stored second of
*this
.constexpr duration<Rep, Period> time_of_day<duration<Rep, Period>>::subseconds() const noexcept;Returns: The stored subsecond of
*this
.constexpr explicit time_of_day<duration<Rep, Period>>::operator precision() const noexcept;Returns: The number of subseconds since midnight.
constexpr precision to_duration() const noexcept;Returns:
precision{*this}
.void time_of_day<duration<Rep, Period>>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<duration<Rep, Period>>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const time_of_day<duration<Rep, Period>>& t);Effects: If
t
is a 24-hour time, outputs toos
according to the format: "%T" ([time.format]). Elset
is a 12-hour time, outputs toos
according to the format: "%I:%M:%S" ([time.format]).Returns:
os
.Example:
01:08:03.007 // 1:08:03.007 in the morning in 24-hour format (assuming millisecond precision) 18:15:45.123 // 6:15:45.123 in the evening in 24-hour format (assuming millisecond precision) 1:08:03.007am // 1:08:03.007 in the morning in 12-hour format (assuming millisecond precision) 6:15:45.123pm // 6:15:45.123 in the evening in 12-hour format (assuming millisecond precision)
Add new section [time.timezone] after 23.17.11 Class time_of_day
[time.time_of_day]:
23.17.12 Time Zones [time.timezone]
This clause creates an API which exposes the IANA Time Zone database, and interfaces with
sys_time
andlocal_time
. By using only this interface, time zone support is provided not only to the civil calendar types, but also to other user-written calendars that interface withsys_time
andlocal_time
.23.17.12.1 The time zone database [time.timezone.database]
The following data structure is the time zone database, and the following functions access it.
struct tzdb { string version; vector<time_zone> zones; vector<link> links; vector<leap> leaps; const time_zone* locate_zone(string_view tz_name) const; const time_zone* current_zone() const; }; class tzdb_list { atomic<tzdb*> head_{nullptr}; // exposition only public: class const_iterator; const tzdb& front() const noexcept; const_iterator erase_after(const_iterator p) noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; };The
tzdb_list
database is a singleton. Access is granted to it via theget_tzdb_list()
function which returns a reference to it. However this access is only needed for those applications which need to have long uptimes and have a need to update the time zone database while running. Other applications can implicitly access thefront()
of this list via the read-only namespace scope functionsget_tzdb()
,locate_zone()
andcurrent_zone()
. Eachvector
intzdb
is sorted to enable fast lookup. One can iterate over and inspect this database. And multiple versions of the database can be used at once, via thetzdb_list
.const time_zone* tzdb::locate_zone(string_view tz_name) const;Returns: If a
time_zone
is found for whichname() == tz_name
, returns a pointer to thattime_zone
. Otherwise if alink
is found wheretz_name == link.name()
, then a pointer is returned to thetime_zone
for whichzone.name() == link.target()
[Note: Alink
is an alternative name for atime_zone
. — end note]Throws: If a
const time_zone*
can not be found as described in the Returns clause, throws aruntime_error
. [Note: On non-exceptional return, the return value is always a pointer to a validtime_zone
. — end note]const time_zone* tzdb::current_zone() const;Returns: A
const time_zone*
referring to the time zone which your computer has set as its local time zone.list<tzdb>& get_tzdb_list();Effects: If this is the first access to the database, will initialize the database. If this call initializes the database, the resulting database will be a
tzdb_list
which holds a single initializedtzdb
.Returns: A reference to the database.
Thread Safety: It is safe to call this function from multiple threads at one time.
Throws:
runtime_error
if for any reason a reference can not be returned to a validlist<tzdb>&
containing one or more validtzdb
.const tzdb& get_tzdb();Returns:
get_tzdb_list().front()
.const time_zone* locate_zone(string_view tz_name);Returns:
get_tzdb().locate_zone(tz_name)
which will initialize the timezone database if this is the first reference to the database.const time_zone* current_zone();Returns:
get_tzdb().current_zone()
.tzdb_list::const_iterator
is a constant iterator which meets the forward iterator requirements and has a value type oftzdb
.const tzdb& tzdb_list::front() const noexcept;Returns:
*head_
.Remarks: this operation is thread safe with respect to
reload_tzdb()
. [Note:reload_tzdb()
pushes a newtzdb
onto the front of this container. — end note]tzdb::const_iterator tzdb::erase_after(const_iterator p) noexcept;Requires: The iterator following
p
is dereferenceable.Effects: Erases the
tzdb
referred to by the iterator followingp
.Returns: An iterator pointing to the element following the one that was erased, or
end()
if no such element exists.Remarks: No pointers, references or iterators are invalidated except those referring to the erased
tzdb
.Note: It is not possible to erase the
tzdb
referred to bybegin()
.tzdb::const_iterator tzdb::begin() const noexcept;Returns: An iterator referring to the firsttzdb
in the container.tzdb::const_iterator tzdb::end() const noexcept;Returns: An iterator referring to the position one past the lasttzdb
in the container.tzdb::const_iterator tzdb::cbegin() const noexcept;Returns:begin()
.tzdb::const_iterator tzdb::cend() const noexcept;Returns:end()
.23.17.12.1.1 Remote time zone database support [time.timezone.database.remote]
The local time zone database is that supplied by the implementation when the application first accesses the database, for example via
current_zone()
. While the application is running, the implementation may choose to update the time zone database. This update shall not impact the application in any way unless the application calls the functions in this section. This potentially updated time zone database is referred to as the remote time zone database.const tzdb& reload_tzdb();Effects: This function first checks the version of the remote time zone database. If the version of the local and remote databases are the same, there are no effects. Otherwise the remote database is pushed to the front of the
tzdb_list
accessed byget_tzdb_list()
.Returns:
get_tzdb_list().front()
.Remarks: No pointers, references or iterators are invalidated.
Thread Safety: This function is thread safe with respect to
get_tzdb_list().front()
andget_tzdb_list().erase_after()
.Throws:
runtime_error
if for any reason a reference can not be returned to a validtzdb
.string remote_version();Returns: The latest remote database version. If the remote version s not available, the empty string is returned.
Note: If non-empty, this can be compared with
get_tzdb().version
to discover if the local and remote databases are equivalent.23.17.12.2 Exception classes [time.timezone.exception]
nonexistent_local_time
is thrown when one attempts to convert a non-existentlocal_time
to asys_time
without specifyingchoose::earliest
orchoose::latest
.class nonexistent_local_time : public runtime_error { public: template <class Duration> nonexistent_local_time(local_time<Duration> tp, const local_info& i); };template <class Duration> nonexistent_local_time::nonexistent_local_time(local_time<Duration> tp, const local_info& i);Requires:
i.result == local_info::nonexistent
.Effects: Constructs a
nonexistent_local_time
by initializing the base class with a sequence ofchar
equivalent to that produced byos.str()
initialized as shown below:ostringstream os; os << tp << " is in a gap between\n" << local_seconds{i.first.end.time_since_epoch()} + i.first.offset << ' ' << i.first.abbrev << " and\n" << local_seconds{i.second.begin.time_since_epoch()} + i.second.offset << ' ' << i.second.abbrev << " which are both equivalent to\n" << i.first.end << " UTC";[Example:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; try { auto zt = zoned_time{"America/New_York", local_days{sun[2]/mar/2016} + 2h + 30min}; } catch (const nonexistent_local_time& e) { std::cout << e.what() << '\n'; } }Which outputs:
2016-03-13 02:30:00 is in a gap between 2016-03-13 02:00:00 EST and 2016-03-13 03:00:00 EDT which are both equivalent to 2016-03-13 07:00:00 UTC— end example:]
ambiguous_local_time
is thrown when one attempts to convert an ambiguouslocal_time
to asys_time
without specifyingchoose::earliest
orchoose::latest
.class ambiguous_local_time : public runtime_error { public: template <class Duration> ambiguous_local_time(local_time<Duration> tp, const local_info& i); };template <class Duration> ambiguous_local_time::ambiguous_local_time(local_time<Duration> tp, const local_info& i);Requires:
i.result == local_info::ambiguous
.Effects: Constructs an
ambiguous_local_time
by initializing the base class with a sequence ofchar
equivalent to that produced byos.str()
initialized as shown below:ostringstream os; os << tp << " is ambiguous. It could be\n" << tp << ' ' << i.first.abbrev << " == " << tp - i.first.offset << " UTC or\n" << tp << ' ' << i.second.abbrev << " == " << tp - i.second.offset << " UTC";[Example:
#include <chrono> #include <iostream> int main() { using namespace std::chrono; try { auto zt = zoned_time{"America/New_York", local_days{sun[1]/nov/2016} + 1h + 30min}; } catch (const ambiguous_local_time& e) { std::cout << e.what() << '\n'; } }Which outputs:
2016-11-06 01:30:00 is ambiguous. It could be 2016-11-06 01:30:00 EDT == 2016-11-06 05:30:00 UTC or 2016-11-06 01:30:00 EST == 2016-11-06 06:30:00 UTC— end example:]
23.17.12.3 Information classes [time.timezone.info]
A
sys_info
structure can be obtained from the combination of atime_zone
and either asys_time
, orlocal_time
. It can also be obtained from azoned_time
which is effectively apair
of atime_zone
andsys_time
.This structure represents a lower-level API. Typical conversions from
sys_time
tolocal_time
will use this structure implicitly, not explicitly.struct sys_info { sys_seconds begin; sys_seconds end; seconds offset; minutes save; string abbrev; };The
begin
andend
fields indicate that for the associatedtime_zone
andtime_point
, theoffset
andabbrev
are in effect in the range[begin, end)
. This information can be used to efficiently iterate the transitions of atime_zone
.The
offset
field indicates the UTC offset in effect for the associatedtime_zone
andtime_point
. The relationship betweenlocal_time
andsys_time
is:offset = local_time - sys_timeThe
save
field is "extra" information not normally needed for conversion betweenlocal_time
andsys_time
. Ifsave != 0min
, thissys_info
is said to be on "daylight saving" time, andoffset - save
suggests what thistime_zone
might use if it were off daylight saving. However this information should not be taken as authoritative. The only sure way to get such information is to query thetime_zone
with atime_point
that returns ansys_info
wheresave == 0min
. There is no guarantee whattime_point
might return such ansys_info
except that it is guaranteed not to be in the range[begin, end)
(ifsave != 0min
for thissys_info
).The
abbrev
field indicates the current abbreviation used for the associatedtime_zone
andtime_point
. Abbreviations are not unique among thetime_zone
s, and so one can not reliably map abbreviations back to atime_zone
and UTC offset.A
sys_info
can be streamed out in an unspecified format:template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const sys_info& r);A
local_info
structure represents a lower-level API. Typical conversions fromlocal_time
tosys_time
will use this structure implicitly, not explicitly.struct local_info { enum {unique, nonexistent, ambiguous} result; sys_info first; sys_info second; };When a
local_time
tosys_time
conversion is unique,result == unique
,first
will be filled out with the correctsys_info
andsecond
will be zero-initialized. If the conversion stems from a nonexistentlocal_time
thenresult == nonexistent
,first
will be filled out with thesys_info
that ends just prior to thelocal_time
andsecond
will be filled out with thesys_info
that begins just after thelocal_time
. If the conversion stems from an ambiguouslocal_time
thenresult == ambiguous
,first
will be filled out with thesys_info
that ends just after thelocal_time
andsecond
will be filled out with thesys_info
that starts just before thelocal_time
.A
local_info
can be streamed out in an unspecified format:template <class charT, class traits> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const local_info& r);23.17.12.4 Class
time_zone
[time.timezone.time_zone]A
time_zone
represents all time zone transitions for a specific geographic area.time_zone
construction is undocumented, and done during the database initialization. You can gainconst
access to atime_zone
via functions such aslocate_zone
.class time_zone { public: time_zone(const time_zone&) = delete; time_zone& operator=(const time_zone&) = delete; const string& name() const noexcept; template <class Duration> sys_info get_info(sys_time<Duration> st) const; template <class Duration> local_info get_info(local_time<Duration> tp) const; template <class Duration> sys_time<typename common_type<Duration, seconds>::type> to_sys(local_time<Duration> tp) const; template <class Duration> sys_time<typename common_type<Duration, seconds>::type> to_sys(local_time<Duration> tp, choose z) const; template <class Duration> local_time<typename common_type<Duration, seconds>::type> to_local(sys_time<Duration> tp) const; }; bool operator==(const time_zone& x, const time_zone& y) noexcept; bool operator!=(const time_zone& x, const time_zone& y) noexcept; bool operator< (const time_zone& x, const time_zone& y) noexcept; bool operator> (const time_zone& x, const time_zone& y) noexcept; bool operator<=(const time_zone& x, const time_zone& y) noexcept; bool operator>=(const time_zone& x, const time_zone& y) noexcept;const string& time_zone::name() const noexcept;Returns: The name of the
time_zone
.Example: "America/New_York".
Note: Here is an unofficial list of
time_zone
names: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.template <class Duration> sys_info time_zone::get_info(sys_time<Duration> st) const;Returns: A
sys_info
i
for whichst
is in the range[i.begin, i.end)
.template <class Duration> local_info time_zone::get_info(local_time<Duration> tp) const;Returns: A
local_info
fortp
.template <class Duration> sys_time<typename common_type<Duration, seconds>::type> time_zone::to_sys(local_time<Duration> tp) const;Returns: A
sys_time
that is at least as fine asseconds
, and will be finer if the argumenttp
has finer precision. Thissys_time
is the UTC equivalent oftp
according to the rules of thistime_zone
.Throws: If the conversion from
tp
to asys_time
is ambiguous, throwsambiguous_local_time
. If the conversion fromtp
to asys_time
is nonexistent, throwsnonexistent_local_time
.template <class Duration> sys_time<typename common_type<Duration, seconds>::type> time_zone::to_sys(local_time<Duration> tp, choose z) const;Returns: A
sys_time
that is at least as fine asseconds
, and will be finer if the argumenttp
has finer precision. Thissys_time
is the UTC equivalent oftp
according to the rules of thistime_zone
. If the conversion fromtp
to asys_time
is ambiguous, returns the earliersys_time
ifz == choose::earliest
, and returns the latersys_time
ifz == choose::latest
. If thetp
represents a non-existent time between two UTCtime_point
s, then the two UTCtime_point
s will be the same, and that UTCtime_point
will be returned.template <class Duration> local_time<typename common_type<Duration, seconds>::type> time_zone::to_local(sys_time<Duration> tp) const;Returns: The
local_time
associated withtp
and thistime_zone
.bool operator==(const time_zone& x, const time_zone& y) noexcept;Returns:
x.name() == y.name()
.bool operator!=(const time_zone& x, const time_zone& y) noexcept;Returns:
!(x == y)
.bool operator<(const time_zone& x, const time_zone& y) noexcept;Returns:
x.name() < y.name()
.bool operator>(const time_zone& x, const time_zone& y) noexcept;Returns:
y < x
.bool operator<=(const time_zone& x, const time_zone& y) noexcept;Returns:
!(y < x)
.bool operator>=(const time_zone& x, const time_zone& y) noexcept;Returns:
!(x < y)
.23.17.12.5 Class
zoned_traits
[time.timezone.zoned_traits]
zoned_traits
provides a means for customizing the behavior ofzoned_time<Duration, TimeZonePtr>
for thezoned_time
default constructor, and constructors takingstring_view
. A specialization forconst time_zone*
is provided by the implementation.template <class T> struct zoned_traits {}; template <> struct zoned_traits<const time_zone*> { static const time_zone* default_zone(); static const time_zone* locate_zone(string_view name); };static const time_zone* zoned_traits<const time_zone*>::default_zone();Returns:
std::chrono::locate_zone("UTC")
.static const time_zone* zoned_traits<const time_zone*>::locate_zone(string_view name);Returns:
std::chrono::locate_zone(name)
.23.17.12.6 Class
zoned_time
[time.timezone.zoned_time]
zoned_time
represents a logical paring oftime_zone
and atime_point
with precisionDuration
.template <class Duration, class TimeZonePtr = const time_zone*> class zoned_time { public: using duration = common_type_t<Duration, seconds>; private: TimeZonePtr zone_; // exposition only sys_time<duration> tp_; // exposition only public: zoned_time(); zoned_time(const zoned_time&) = default; zoned_time& operator=(const zoned_time&) = default; zoned_time(const sys_time<Duration>& st); explicit zoned_time(TimeZonePtr z); explicit zoned_time(string_view name); template <class Duration2> zoned_time(const zoned_time<Duration2>& zt) noexcept; zoned_time(TimeZonePtr z, const sys_time<Duration>& st); zoned_time(string_view name, const sys_time<Duration>& st); zoned_time(TimeZonePtr z, const local_time<Duration>& tp); zoned_time(string_view name, const local_time<Duration>& tp); zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c); zoned_time(string_view name, const local_time<Duration>& tp, choose c); template <class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt); template <class Duration2, class TimeZonePtr2> zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& zt, choose); zoned_time(string_view name, const zoned_time<Duration>& zt); zoned_time(string_view name, const zoned_time<Duration>& zt, choose); zoned_time& operator=(const sys_time<Duration>& st); zoned_time& operator=(const local_time<Duration>& ut); operator sys_time<duration>() const; explicit operator local_time<duration>() const; TimeZonePtr get_time_zone() const; local_time<duration> get_local_time() const; sys_time<duration> get_sys_time() const; sys_info get_info() const; }; template <class Duration1, class Duration2, class TimeZonePtr> bool operator==(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y); template <class Duration1, class Duration2, class TimeZonePtr> bool operator!=(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y); template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const zoned_time<Duration, TimeZonePtr>& t); template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const zoned_time<Duration, TimeZonePtr>& tp); zoned_time() -> zoned_time<seconds>; template <class Duration> zoned_time(sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>>; template <class TimeZonePtr, class Duration> zoned_time(TimeZonePtr, sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>, TimeZonePtr>; template <class TimeZonePtr, class Duration> zoned_time(TimeZonePtr, local_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>, TimeZonePtr>; template <class TimeZonePtr, class Duration> zoned_time(TimeZonePtr, zoned_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>, TimeZonePtr>; zoned_time(string_view) -> zoned_time<seconds>; template <class Duration> zoned_time(string_view, sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>>; template <class Duration> zoned_time(string_view, local_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>>; template <class Duration, class TimeZonePtr, class TimeZonePtr2> zoned_time(TimeZonePtr, zoned_time<Duration, TimeZonePtr2>) -> zoned_time<Duration, TimeZonePtr>; template <class Duration, class TimeZonePtr, class TimeZonePtr2> zoned_time(TimeZonePtr, zoned_time<Duration, TimeZonePtr2>, choose) -> zoned_time<Duration, TimeZonePtr>;An invariant of
zoned_time<Duration>
is that it always refers to a validtime_zone
, and represents a point in time that exists and is not ambiguous.zoned_time<Duration, TimeZonePtr>::zoned_time();Remarks: This constructor does not participate in overload resolution unless the expression
zoned_traits<TimeZonePtr>::default_zone()
is well formed.Effects: Constructs a
zoned_time
by initializingzone_
withzoned_traits<TimeZonePtr>::default_zone()
and default constructingtp_
.zoned_time<Duration, TimeZonePtr>::zoned_time(const zoned_time&) = default; zoned_time<Duration, TimeZonePtr>& zoned_time<Duration>::operator=(const zoned_time&) = default;The copy members transfer the associated
time_zone
from the source to the destination. After copying, source and destination compare equal. IfDuration
hasnoexcept
copy members, thenzoned_time<Duration>
hasnoexcept
copy members.zoned_time<Duration, TimeZonePtr>::zoned_time(const sys_time<Duration>& st);Remarks: This constructor does not participate in overload resolution unless the expression
zoned_traits<TimeZonePtr>::default_zone()
is well formed.Effects: Constructs a
zoned_time
by initializingzone_
withzoned_traits<TimeZonePtr>::default_zone()
andtp_
withst
.explicit zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z);Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
initializingzone_
withstd::move(z)
.explicit zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name);Remarks: This constructor does not participate in overload resolution unless the expression
zoned_traits<TimeZonePtr>::locate_zone(string_view{})
is well formed andzoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(string_view{})
.Effects: Constructs a
zoned_time
by initializingzone_
withzoned_traits<TimeZonePtr>::locate_zone(name)
and default constructingtp_
.template <class Duration2, TimeZonePtr> zoned_time<Duration>::zoned_time(const zoned_time<Duration2, TimeZonePtr>& y) noexcept;Remarks: Does not participate in overload resolution unless
sys_time<Duration2>
is implicitly convertible tosys_time<Duration>
.Effects: Constructs a
zoned_time
x
such thatx == y
.zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const sys_time<Duration>& st);Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
by initializingzone_
withstd::move(z)
andtp_
withst
.zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const sys_time<Duration>& st);Remarks: This constructor does not participate in overload resolution unless
zoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(name)
andst
.Effects: Equivalent to construction with
{zoned_traits<TimeZonePtr>::locate_zone(name), st}
.zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& tp);Requires:
z
refers to a validtime_zone
.Remarks: This constructor does not participate in overload resolution unless
declval<TimeZonePtr&>()->to_sys(local_time<Duration>{})
is convertible tosys_time<duration>
.Effects: Constructs a
zoned_time
by initializingzone_
withstd::move(z)
andtp_
withzone_->to_sys(t)
.zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const local_time<Duration>& tp);Remarks: This constructor does not participate in overload resolution unless
zoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(name)
andtp
.Effects: Equivalent to construction with
{zoned_traits<TimeZonePtr>::locate_zone(name), tp}
.zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c);Requires:
z
refers to a validtime_zone
.Remarks: This constructor does not participate in overload resolution unless
decltype(declval<TimeZonePtr&>()->to_sys(local_time<Duration>{}, choose::earliest))
is convertible tosys_time<duration>
.Effects: Constructs a
zoned_time
by initializingzone_
withstd::move(z)
andtp_
withzone_->to_sys(t, c)
.zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const local_time<Duration>& tp, choose c);Remarks: This constructor does not participate in overload resolution unless
zoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(name)
,local_time<Duration>
andchoose
.Effects: Equivalent to construction with
{zoned_traits<TimeZonePtr>::locate_zone(name), tp, c}
.template <class Duration2, TimeZonePtr> zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y);Remarks: Does not participate in overload resolution unless
sys_time<Duration2>
is implicitly convertible tosys_time<Duration>
.Requires:
z
refers to a valid time zone.Effects: Constructs a
zoned_time
by initializingzone_
withstd::move(z)
andtp_
withz.tp_
.template <class Duration2, TimeZonePtr> zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const zoned_time<Duration2, TimeZonePtr2>& y, choose);Remarks: Does not participate in overload resolution unless
sys_time<Duration2>
is implicitly convertible tosys_time<Duration>
.Requires:
z
refers to a valid time zone.Effects: Equivalent to construction with
{z, y}
.Note: The
choose
parameter is allowed here, but has no impact.zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const zoned_time<Duration>& y);Remarks: This constructor does not participate in overload resolution unless
zoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(name)
andzoned_time
.Effects: Equivalent to construction with
{zoned_traits<TimeZonePtr>::locate_zone(name), y}
.zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const zoned_time<Duration>& y, choose c);Remarks: This constructor does not participate in overload resolution unless
zoned_time
is constructible from the return type ofzoned_traits<TimeZonePtr>::locate_zone(name)
,zoned_time
, andchoose
.Effects: Equivalent to construction with
{locate_zone(name), y, c}
.Note: The
choose
parameter is allowed here, but has no impact.zoned_time<Duration, TimeZonePtr>& zoned_time<Duration, TimeZonePtr>::operator=(const sys_time<Duration>& st);Effects: After assignment
get_sys_time() == st
. This assignment has no effect on the return value ofget_time_zone()
.Returns:
*this
.zoned_time<Duration, TimeZonePtr>& zoned_time<Duration, TimeZonePtr>::operator=(const local_time<Duration>& lt);Effects: After assignment
get_local_time() == lt
. This assignment has no effect on the return value ofget_time_zone()
.Returns:
*this
.zoned_time<Duration, TimeZonePtr>::operator sys_time<duration>() const;Returns:
get_sys_time()
.explicit zoned_time<Duration, TimeZonePtr>::operator local_time<duration>() const;Returns:
get_local_time()
.TimeZonePtr zoned_time<Duration, TimeZonePtr>::get_time_zone() const;Returns:
zone_
.local_time<typename zoned_time<Duration, TimeZonePtr>::duration> zoned_time<Duration, TimeZonePtr>::get_local_time() const;Returns:
zone_->to_local(tp_)
.sys_time<typename zoned_time<Duration, TimeZonePtr>::duration> zoned_time<Duration, TimeZonePtr>::get_sys_time() const;Returns:
tp_
.sys_info zoned_time<Duration, TimeZonePtr>::get_info() const;Returns:
zone_->get_info(tp_)
.template <class Duration1, class Duration2, class TimeZonePtr> bool operator==(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y);Returns:
x.zone_ == y.zone_ && x.tp_ == y.tp_
.template <class Duration1, class Duration2, class TimeZonePtr> bool operator!=(const zoned_time<Duration1, TimeZonePtr>& x, const zoned_time<Duration2, TimeZonePtr>& y);Returns:
!(x == y)
.template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const zoned_time<Duration, TimeZonePtr>& t)Effects: Streams
t
toos
using the format "%F %T %Z" and the value returned fromt.get_local_time()
.Returns:
os
.template <class charT, class traits, class Duration, class TimeZonePtr> basic_ostream<charT, traits>& to_stream(basic_ostream<charT, traits>& os, const charT* fmt, const zoned_time<Duration, TimeZonePtr>& tp);Effects: First obtains a
sys_info
viatp.get_info()
which for exposition purposes will be referred to asinfo
. Then callsto_stream(os, fmt, tp.get_local_time(), &info.abbrev, &info.offset)
.Returns:
os
.
Add a new section 23.17.12.7 leap [time.timezone.leap]:
23.17.12.7 class
leap
[time.timezone.leap]class leap { sys_seconds date_; // exposition only public: leap(const leap&) = default; leap& operator=(const leap&) = default; // Undocumented constructors sys_seconds date() const; }; bool operator==(const leap& x, const leap& y); bool operator!=(const leap& x, const leap& y); bool operator< (const leap& x, const leap& y); bool operator> (const leap& x, const leap& y); bool operator<=(const leap& x, const leap& y); bool operator>=(const leap& x, const leap& y); template <class Duration> bool operator==(const const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator==(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator!=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator!=(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator< (const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator< (const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator> (const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator> (const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator<=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator<=(const sys_time<Duration>& x, const leap& y); template <class Duration> bool operator>=(const leap& x, const sys_time<Duration>& y); template <class Duration> bool operator>=(const sys_time<Duration>& x, const leap& y);
leap
is a copyable class that is constructed and stored in the time zone database when initialized. You can explicitly convert it to asys_seconds
with the member functiondate()
and that will be the date of the leap second insertion.leap
is equality and less-than comparable, both with itself, and withsys_time<Duration>
.[Example:
Here is the date of all of the leap second insertions at the time of this writing:
for (auto& l : get_tzdb().leaps) cout << l.date() << '\n';which outputs:
1972-07-01 00:00:00 1973-01-01 00:00:00 1974-01-01 00:00:00 1975-01-01 00:00:00 1976-01-01 00:00:00 1977-01-01 00:00:00 1978-01-01 00:00:00 1979-01-01 00:00:00 1980-01-01 00:00:00 1981-07-01 00:00:00 1982-07-01 00:00:00 1983-07-01 00:00:00 1985-07-01 00:00:00 1988-01-01 00:00:00 1990-01-01 00:00:00 1991-01-01 00:00:00 1992-07-01 00:00:00 1993-07-01 00:00:00 1994-07-01 00:00:00 1996-01-01 00:00:00 1997-07-01 00:00:00 1999-01-01 00:00:00 2006-01-01 00:00:00 2009-01-01 00:00:00 2012-07-01 00:00:00 2015-07-01 00:00:00 2017-01-01 00:00:00— end example]
sys_seconds leap::date() constReturns:
date_
.bool operator==(const leap& x, const leap& y)Returns:
x.date() == y.date()
.bool operator!=(const leap& x, const leap& y)Returns:
!(x == y)
.bool operator<(const leap& x, const leap& y)Returns:
x.date() < y.date()
.bool operator>(const leap& x, const leap& y)Returns:
y < x
.bool operator<=(const leap& x, const leap& y)Returns:
!(y < x)
.bool operator>=(const leap& x, const leap& y)Returns:
!(x < y)
.template <class Duration> bool operator==(const const leap& x, const sys_time<Duration>& y)Returns:
x.date() == y
.template <class Duration> bool operator==(const sys_time<Duration>& x, const leap& y)Returns:
y == x
.template <class Duration> bool operator!=(const leap& x, const sys_time<Duration>& y)Returns:
!(x == y)
.template <class Duration> bool operator!=(const sys_time<Duration>& x, const leap& y)Returns:
!(x == y)
.template <class Duration> bool operator< (const leap& x, const sys_time<Duration>& y)Returns:
x.date() < y
.template <class Duration> bool operator< (const sys_time<Duration>& x, const leap& y)Returns:
x < y.date()
.template <class Duration> bool operator> (const leap& x, const sys_time<Duration>& y)Returns:
y < x
.template <class Duration> bool operator> (const sys_time<Duration>& x, const leap& y)Returns:
y < x
.template <class Duration> bool operator<=(const leap& x, const sys_time<Duration>& y)Returns:
!(y < x)
.template <class Duration> bool operator<=(const sys_time<Duration>& x, const leap& y)Returns:
!(y < x)
.template <class Duration> bool operator>=(const leap& x, const sys_time<Duration>& y)Returns:
!(x < y)
.template <class Duration> bool operator>=(const sys_time<Duration>& x, const leap& y)Returns:
!(x < y)
.
Add a new section 23.17.12.8 link [time.timezone.link]:
23.17.12.8 class
link
[time.timezone.link]class link { private: string name_; // exposition only string target_; // exposition only public: link(const link&) = default; link& operator=(const link&) = default; // Undocumented constructors const string& name() const; const string& target() const; }; bool operator==(const link& x, const link& y); bool operator!=(const link& x, const link& y); bool operator< (const link& x, const link& y); bool operator> (const link& x, const link& y); bool operator<=(const link& x, const link& y); bool operator>=(const link& x, const link& y);A
link
is an alternative name for atime_zone
. The alternative name isname()
. The name of thetime_zone
for which this is an alternative name istarget()
.link
s will be constructed for you when the time zone database is initialized.const string& link::name() constReturns:
name_
.const string& link::target() constReturns:
target_
.bool operator==(const link& x, const link& y)Returns:
x.name() == y.name()
.bool operator!=(const link& x, const link& y)Returns:
!(x == y)
.bool operator< (const link& x, const link& y)Returns:
x.name() < y.name()
.bool operator> (const link& x, const link& y)Returns:
y < x
.bool operator<=(const link& x, const link& y)Returns:
!(y < x)
.bool operator>=(const link& x, const link& y);Returns:
!(x < y)
.
Modify the synopsis in section [fs.filesystem.syn] 30.10.6 Header <filesystem>
synopsis:
using file_time_type = chrono::time_point<trivial-clockchrono::file_clock>;
Add to [thread.req.paramname] 33.2.1 Template parameter names:
1 Throughout this Clause, the names of template parameters are used to express type requirements. If a template parameter is named
Predicate
,operator()
applied to the template argument shall return a value that is convertible tobool
. A program that instantiates a template with a template parameter namedClock
with a type for whichchrono::is_clock_v<Clock>
isfalse
, is ill-formed.
A database parser is nothing without its database. I would like to thank the founding contributor of the IANA Time Zone Database Arthur David Olson. I would also like to thank the entire group of people who continually maintain it, and especially the IESG-designated TZ Coordinator, Paul Eggert. Without the work of these people, this software would have no data to parse.
I would also like to thank Jiangang Zhuang and Bjarne Stroustrup for invaluable feedback for the timezone portion of this library, which ended up also influencing the date.h library. Thanks also to Jonathan Wakely for agreeing to present this paper in Oulu for me. Thank you Daniel Krügler for the incredibly thorough review. Thank you Tomasz Kamiński for the very helpful changes to the proposed wording.
And I would also especially like to thank the growing list of contributors to this library.