<chrono>
to Calendars and Time Zones
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 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>
clock 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, and OS X.
The API stresses:
<chrono>
library.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 auto zt = make_zoned("Asia/Tokyo", tp); cout << zt << '\n'; // 2016-05-29 16:30:06.153 JST
The helper function make_zoned
creates a type zoned_time
which
is templated on the duration type of tp
. The use of make_zoned
deduces that you desire milliseconds precision 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 = make_zoned("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 it has no clock::now()
functionality. 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 = make_zoned("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 << make_zoned("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", make_zoned("Europe/Helsinki", zt)) << '\n'; // 2016-06-21 16:00 +0300
Or perhaps properly localized:
cout << format(locale{"fi_FI"}, "%c", make_zoned("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 << make_zoned(current_zone(), system_clock::now()) << '\n'; // 2016-05-30 13:57:30.694574 EDT
Current time in Budapest?
cout << make_zoned("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 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
Text in grey boxes is not proposed wording.
Append to synopsis in 20.15.2 Header
<chrono>
synopsis [time.syn]:
namespace std { namespace chrono { // ... 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>>>; template <class Duration> using sys_time = time_point<system_clock, Duration>; using sys_days = sys_time<days>; using sys_seconds = sys_time<seconds>; 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> basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, const sys_days& dp); struct local_t {}; template <class Duration> using local_time = time_point<local_t, Duration>; using local_days = local_time<days>; using local_seconds = local_time<seconds>; template <class CharT, class Traits, class Duration> basic_ostream<CharT, Traits>& operator<<(basic_ostream<CharT, Traits>& os, const local_time<Duration>& tp); // civil calendar 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const day& d); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const month& m); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const year& y); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const weekday& wd); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const month_day& md); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const year_month& ym); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const year_month_day& ymd); 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class 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 enum {am = 1, pm}; template <class Duration> class time_of_day; time_of_day<hours> time_of_day<minutes> time_of_day<seconds> time_of_day<duration<Rep, Period>> template<class CharT, class Traits> basic_ostream<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const time_of_day<hours>& t); template<class CharT, class Traits> basic_ostream<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const time_of_day<minutes>& t); template<class CharT, class Traits> basic_ostream<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const time_of_day<seconds>& t); template<class CharT, class Traits, class Rep, class Period> basic_ostream<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const time_of_day<duration<Rep, Period>>& t); template <class Rep, class Period> constexpr time_of_day<duration<Rep, Period>> make_time(duration<Rep, Period> d) noexcept; constexpr time_of_day<hours> make_time(hours h, unsigned md) noexcept; constexpr time_of_day<minutes> make_time(hours h, minutes m, unsigned md) noexcept; constexpr time_of_day<seconds> make_time(hours h, minutes m, seconds s, unsigned md) noexcept; template <class Rep, class Period> constexpr time_of_day<duration<Rep, Period>> make_time(hours h, minutes m, seconds s, duration<Rep, Period> sub_s, unsigned md) noexcept; // time zone database struct TZ_DB; const TZ_DB& get_tzdb(); const time_zone* locate_zone(const string& tz_name); const time_zone* current_zone(); // Remote time zone database -- Needs discussion const TZ_DB& reload_tzdb(); string remote_version(); bool remote_download(const string& version); bool remote_install(const string& version); // exception classes class nonexistent_local_time; class ambiguous_local_time; struct sys_info; ostream& operator<<(ostream& os, const sys_info& si); struct local_info; ostream& operator<<(ostream& os, const local_info& li); enum class choose {earliest, latest}; class time_zone; bool operator==(const time_zone& x, const time_zone& y); bool operator!=(const time_zone& x, const time_zone& y); bool operator<(const time_zone& x, const time_zone& y); bool operator>(const time_zone& x, const time_zone& y); bool operator<=(const time_zone& x, const time_zone& y); bool operator>=(const time_zone& x, const time_zone& y); ostream& operator<<(ostream& os, const time_zone& z); template <class Duration> class zoned_time; using zoned_seconds = zoned_time<seconds>; template <class Duration1, class Duration2> bool operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y); template <class Duration1, class Duration2> bool operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y); template <class Duration> basic_ostream<class CharT, class Traits>& operator<<(basic_ostream<class CharT, class Traits>& os, const zoned_time<Duration>& t); // make_zoned template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(sys_time<Duration> tp); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, local_time<Duration> tp); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, local_time<Duration> tp); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, local_time<Duration> tp, choose c); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, local_time<Duration> tp, choose c); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const zoned_time<Duration>& zt); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const zoned_time<Duration>& zt); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const zoned_time<Duration>& zt, choose c); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const zoned_time<Duration>& zt, choose c); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const sys_time<Duration>& st); template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const sys_time<Duration>& st); // format template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, local_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, local_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, const zoned_time<Duration>& tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, const zoned_time<Duration>& tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, sys_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, sys_time<Duration> tp); // const CharT* formats template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, local_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, local_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, const zoned_time<Duration>& tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, const zoned_time<Duration>& tp); template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, sys_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, sys_time<Duration> tp); // parse template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); // const CharT* formats template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); // leap second support class utc_clock; template <class Duration> using utc_time = time_point<utc_clock, Duration>; using utc_seconds = utc_time<seconds>; template <class Duration> utc_time<common_type_t<Duration, seconds>> to_utc_time(sys_time<Duration> t); template <class Duration> sys_time<common_type_t<Duration, seconds>> to_sys_time(utc_time<Duration> u) 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 { // ... constexpr chrono::last_spec last{}; constexpr chrono::weekday sun{0}; constexpr chrono::weekday mon{1}; constexpr chrono::weekday tue{2}; constexpr chrono::weekday wed{3}; constexpr chrono::weekday thu{4}; constexpr chrono::weekday fri{5}; constexpr chrono::weekday sat{6}; constexpr chrono::month jan{1}; constexpr chrono::month feb{2}; constexpr chrono::month mar{3}; constexpr chrono::month apr{4}; constexpr chrono::month may{5}; constexpr chrono::month jun{6}; constexpr chrono::month jul{7}; constexpr chrono::month aug{8}; constexpr chrono::month sep{9}; constexpr chrono::month oct{10}; constexpr chrono::month nov{11}; 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.point.io] after 20.15.6.7 time_point_cast [time.point.cast]::
template <class Duration> ostream& operator<<(ostream& os, const time_point<system_clock, 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} << ' ' << make_time(tp-dp);Returns:
os
.
ostream& operator<<(ostream& os, const sys_days& dp);
Effects:
os << year_month_day{dp};Returns:
os
.
template <class Duration> ostream& operator<<(ostream& os, const local_time<Duration>& lt);
Effects:
os << sys_time<Duration>{lt.time_since_epoch()};Returns:
os
.
Add new section [time.calendar] after 20.15.7 Clocks [time.clocks]:
The types in this subclause describe the civil (Gregorian) calendar and its relationship
to sys_days
and local_days
.
last_spec
[time.calendar.last]
The struct last_spec
is used in conjunction with other calendar types to
indicate 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 named last
in the
chrono_literals
namespace.
struct last_spec { explicit last_spec() = default; };
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 any unsigned
value, which will be subsequently truncated to fit into
day
's unspecified internal storage. day
is equality and less-than
comparable, and participates in basic arithmetic with days
representing the
quantity between any two day
's. One can form a day
literal with
d
. And one can stream out a day
.
day
has explicit conversions to and from unsigned
.
class day { unsigned char d_; // exposition only public: 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; ostream& operator<<(ostream& os, const day& d);
day
is a trivially copyable class type.
day
is a standard-layout class type.
day
is a literal class type.
explicit constexpr day::day(unsigned d) noexcept;
Effects: Constructs an object of type
day
by constructingd_
withd
.
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})}
.
ostream& operator<<(ostream& os, const day& d);
Effects: Inserts a decimal integral text representation of
d
intoos
. Single digit values are prefixed with'0'
.Returns:
os
.
constexpr day operator "" d(unsigned long long d) noexcept;
Returns:
day{static_cast<unsigned>(d)}
.
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 any unsigned
value, which will be
subsequently truncated to fit into month
's unspecified internal
storage. month
is equality and less-than comparable, and
participates in basic arithmetic with months
representing the
quantity between any two month
's. One can stream out a
month
. month
has explicit conversions to and from
unsigned
. There are 12 month
constants, one for each
month of the year in the chrono_literals
namespace.
class month { unsigned char m_; // exposition only public: 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; ostream& operator<<(ostream& os, const month& m);
month
is a trivially copyable class type.
month
is a standard-layout class type.
month
is a literal class type.
explicit constexpr month::month(unsigned m) noexcept;
Effects: Constructs an object of type
month
by constructingm_
withm
.
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
. That is, repeated increments or decrements is not a valid implementation.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;
Requires:
x.ok() == true
andy.ok() == true
.Returns: A value of
months
in the range ofmonths{0}
tomonths{11}
inclusive.Remarks: The returned value
m
shall satisfy the equality:y + m == x
.Example:
jan - feb == months{11}
.
ostream& operator<<(ostream& 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
.
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 any
int
value, which will be subsequently truncated to fit into
year
's internal unspecified storage. year
is equality and less-than
comparable, and participates in basic arithmetic with years
representing the
quantity between any two year
's. One can form a year
literal
with y
. And one can stream out a year
.
year
has explicit conversions to and from int
.
class year { short y_; // exposition only public: 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 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; ostream& operator<<(ostream& os, const year& y);
year
is a trivially copyable class type.
year
is a standard-layout class type.
year
is a literal class type.
explicit constexpr year::year(int y) noexcept;
Effects: Constructs an object of type
year
by constructingy_
withy
.
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 bool year::is_leap() const noexcept;
Returns:
true
if*this
represents a leap year, else returnsfalse
.
constexpr explicit year::operator int() const noexcept;
Returns:
y_
.
constexpr bool year::ok() const noexcept;
Returns:
true
.
static constexpr year year::min() noexcept;
Returns:
year{numeric_limits<decltype(y_)>::min()}
.
static constexpr year year::max() noexcept;
Returns:
year{numeric_limits<decltype(y_)>::max()}
.
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}}
.
ostream& operator<<(ostream& os, const year& y);
Effects: Inserts a signed decimal integral text representation of
y
intoos
. If the year is less than four decimal digits, pads the year with'0'
to four digits. If the year is negative, prefixes with'-'
.Returns:
os
.
constexpr year operator "" y(unsigned long long y) noexcept;
Returns:
year{static_cast<int>(y)}
.
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 thru
Saturday. However it may hold non-negative values outside this range. It can be
constructed with any unsigned
value, which will be subsequently
truncated to fit into weekday
'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 thru Saturday only because this is consistent with existing C and C++
practice. However weekday
'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 a weekday
. weekday
has explicit
conversions to and from unsigned
. There are 7 weekday
constants, one for each day of the week in the chrono_literals
namespace.
A weekday
can be implicitly constructed from a sys_days
. This
is the computation that discovers the day of the week of an arbitrary date.
A weekday
can be indexed with either unsigned
or
last
. 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: 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; ostream& operator<<(ostream& os, const weekday& wd);
weekday
is a trivially copyable class type.
weekday
is a standard-layout class type.
weekday
is a literal class type.
explicit constexpr weekday::weekday(unsigned wd) noexcept;
Effects: Constructs an object of type
weekday
by constructingwd_
withwd
.
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
shall represent 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
. That is, repeated increments or decrements is not a valid implementation.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;
Requires:
x.ok() == true
andy.ok() == true
.Returns: A value of
days
in the range ofdays{0}
todays{6}
inclusive.Remarks: The returned value
d
shall satisfy the equality:y + d == x
.Example:
sun - mon == days{6}
.
ostream& operator<<(ostream& 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
.
weekday_indexed
[time.calendar.weekday_indexed]
weekday_indexed
represents a weekday
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 a weekday
.
[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: 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; ostream& operator<<(ostream& os, const weekday_indexed& wdi);
weekday_indexed
is a trivially copyable class type.
weekday_indexed
is a standard-layout class type.
weekday_indexed
is a literal 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
.
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)
.
ostream& operator<<(ostream& os, const weekday_indexed& wdi);
Effects: Inserts
os << wdi.weekday() << '[' << wdi.index() << ']'
.Returns:
os
.
weekday_last
[time.calendar.weekday_last]
weekday_last
represents the last weekday
of a month.
It is most easily constructed by indexing a weekday
with last
.
[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; ostream& operator<<(ostream& os, const weekday_last& wdl);
weekday_last
is a trivially copyable class type.
weekday_last
is a standard-layout class type.
weekday_last
is a literal 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)
.
ostream& operator<<(ostream& os, const weekday_last& wdl);
Effects: Inserts
os << wdi.weekday() << "[last]"
.Returns:
os
.
month_day
[time.calendar.month_day]
month_day
represents a specific day
of a specific
month
, but with an unspecified year
. 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 a month_day
.
class month_day { chrono::month m_; // exposition only chrono::day d_; // exposition only public: 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; ostream& operator<<(ostream& os, const month_day& md);
month_day
is a trivially copyable class type.
month_day
is a standard-layout class type.
month_day
is a literal 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)
.
ostream& operator<<(ostream& os, const month_day& md);
Effects: Inserts
os << md.month() << '/' << md.day()
.Returns:
os
.
month_day_last
[time.calendar.month_day_last]
month_day_last
represents the last day
of a month
.
It is most easily constructed using the expression m/last
or
last/m
, where m
is an expression with type month
.
[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; ostream& operator<<(ostream& os, const month_day_last& mdl);
month_day_last
is a trivially copyable class type.
month_day_last
is a standard-layout class type.
month_day_last
is a literal 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)
.
ostream& operator<<(ostream& os, const month_day_last& mdl);
Effects: Inserts
os << mdl.month() << "/last"
.Returns:
os
.
month_weekday
[time.calendar.month_weekday]
month_weekday
represents the nth weekday
of a
month
, of an as yet unspecified year
. To do this the
month_weekday
stores a month
and a weekday_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; ostream& operator<<(ostream& os, const month_weekday& mwd);
month_weekday
is a trivially copyable class type.
month_weekday
is a standard-layout class type.
month_weekday
is a literal 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)
.
ostream& operator<<(ostream& os, const month_weekday& mwd);
Effects: Inserts
os << mwd.month() << '/' << mwd.weekday_indexed()
.Returns:
os
.
month_weekday_last
[time.calendar.month_weekday_last]
month_weekday_last
represents the last weekday
of a
month
, of an as yet unspecified year
. To do this the
month_weekday_last
stores a month
and a
weekday_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; ostream& operator<<(ostream& os, const month_weekday_last& mwdl);
month_weekday_last
is a trivially copyable class type.
month_weekday_last
is a standard-layout class type.
month_weekday_last
is a literal 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)
.
ostream& operator<<(ostream& os, const month_weekday_last& mwdl);
Effects: Inserts
os << mwdl.month() << '/' << mwdl.weekday_last()
.Returns:
os
.
year_month
[time.calendar.year_month]
year_month
represents a specific month
of a specific
year
, but with an unspecified day
. year_month
is a
field-based time point with a resolution of months
. 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 a year_month
.
class year_month { chrono::year y_; // exposition only chrono::month m_; // exposition only public: 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; ostream& operator<<(ostream& os, const year_month& ym);
year_month
is a trivially copyable class type.
year_month
is a standard-layout class type.
year_month
is a literal 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: The number of
months
one must add toy
to getx
.
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
.
ostream& operator<<(ostream& os, const year_month& ym);
Effects: Inserts
os << ym.year() << '/' << ym.month()
.Returns:
os
.
year_month_day
[time.calendar.year_month_day]
year_month_day
represents a specific year
, month
,
and day
. year_month_day
is a field-based time point with a
resolution of days
. One can observe each field. year_month_day
supports years
and months
oriented arithmetic, but not
days
oriented arithmetic. For the latter, there is a conversion to
sys_days
which efficiently supports days
oriented arithmetic.
There is also a conversion from sys_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: 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; ostream& operator<<(ostream& os, const year_month_day& ymd);
year_month_day
is a trivially copyable class type.
year_month_day
is a standard-layout class type.
year_month_day
is a literal 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;
Requires:
ok() == true
.Returns: A
sys_days
which represents the date represented by*this
.Remarks: A
sys_days
which is converted to ayear_month_day
, shall have the same value when converted back to asys_days
. The round trip conversion sequence shall be loss-less.
constexpr explicit year_month_day::operator local_days() const noexcept;
Requires:
ok() == true
.Returns: A
local_days
which represents the date represented by*this
.Remarks: Shall return a value equivalent to
local_days{static_cast<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;
Requires:
ymd.month().ok()
istrue
.Returns:
(ymd.year() / ymd.month() + dm) / ymd.day()
.Remarks: If
ymd.day()
is in the range[1d, 28d]
, the resultantyear_month_day
is guaranteed to 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
is not guaranteed to returntrue
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)
.
ostream& operator<<(ostream& 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
.
year_month_day_last
[time.calendar.year_month_day_last]
year_month_day_last
represents a specific year
,
month
, and the last day
of the month
.
year_month_day_last
is a field-based time point with a resolution of
days
, except that it is restricted to pointing to the last day of a year and
month. One can observe each field. The day
field is computed on demand.
year_month_day_last
supports years
and months
oriented arithmetic, but not days
oriented arithmetic. For the latter, there
is a conversion to sys_days
which efficiently supports days
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; ostream& operator<<(ostream& 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.
year_month_day_last
is a literal 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;
Requires:
ok() == true
.Returns: A
sys_days
which represents the date represented by*this
.
constexpr explicit year_month_day_last::operator local_days() const noexcept;
Requires:
ok() == true
.Returns: A
local_days
which represents the date represented by*this
.Remarks: Shall return a value equivalent to
local_days{static_cast<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;
Requires:
ymdl.ok()
istrue
.Returns:
(ymdl.year() / ymdl.month() + dm) / last
.Postconditions: The resultant
year_month_day_last
will returntrue
fromok()
.Complexity: O(1) with respect to the value of
dm
.
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)
.
ostream& operator<<(ostream& os, const year_month_day_last& ymdl);
Effects: Inserts
os << ymdl.year() << '/' << ymdl.month_day_last()
.Returns:
os
.
year_month_weekday
[time.calendar.year_month_weekday]
year_month_weekday
represents a specific year
,
month
, and nth weekday
of the month
.
year_month_weekday
is a field-based time point with a resolution of
days
. One can observe each field. year_month_weekday
supports
years
and months
oriented arithmetic, but not days
oriented arithmetic. For the latter, there is a conversion to sys_days
which
efficiently supports days
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: 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; ostream& operator<<(ostream& os, const year_month_weekday& ymwdi);
year_month_weekday
is a trivially copyable class type.
year_month_weekday
is a standard-layout class type.
year_month_weekday
is a literal 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;
Requires:
ok() == true
.Returns: A
sys_days
which represents the date represented by*this
.
constexpr explicit year_month_weekday::operator local_days() const noexcept;
Requires:
ok() == true
.Returns: A
local_days
which represents the date represented by*this
.Remarks: Shall return a value equivalent to
local_days{static_cast<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;
Requires:
ymwd.ok()
istrue
.Returns:
(ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed()
.Postconditions: The resultant
year_month_weekday
will returntrue
fromok()
.Complexity: O(1) with respect to the value of
dm
.
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)
.
ostream& operator<<(ostream& os, const year_month_weekday& ymwd);
Effects: Inserts
os << ymwdi.year() << '/' << ymwdi.month() << '/' << ymwdi.weekday_indexed()
.Returns:
os
.
year_month_weekday_last
[time.calendar.year_month_weekday_last]
year_month_weekday_last
represents a specific year
,
month
, and last weekday
of the month
.
year_month_weekday_last
is a field-based time point with a resolution of
days
, 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
supports
years
and months
oriented arithmetic, but not days
oriented arithmetic. For the latter, there is a conversion to sys_days
which
efficiently supports days
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; ostream& operator<<(ostream& 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.
year_month_weekday_last
is a literal 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;
Requires:
ok() == true
.Returns: A
sys_days
which represents the date represented by*this
.
constexpr explicit year_month_weekday_last::operator local_days() const noexcept;
Requires:
ok() == true
.Returns: A
local_days
which represents the date represented by*this
.Remarks: Shall return a value equivalent to
local_days{static_cast<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;
Requires:
ymwdl.ok()
istrue
.Returns:
(ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last()
.Postconditions: The resultant
year_month_weekday_last
will returntrue
fromok()
.Complexity: O(1) with respect to the value of
dm
.
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)
.
ostream& operator<<(ostream& os, const year_month_weekday_last& ymwdl);
Effects: Inserts
os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last()
.Returns:
os
.
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
and month_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 caught as a compile-time error, with the notable
exception of an expression that consists of nothing but int
, which of course
has type int
.
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')
The last example may be clear to a human reader. But the compiler doesn't know if
2015
refers to a year
or a day
. Instead of
guessing, the compiler flags it as an error.
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 20.15.8 The civil calendar [time.calendar]:
time_of_day
[time.time_of_day]
The time_of_day
class breaks a duration
which
represents the time elapsed since midnight, into a "broken" down time such as
hours:minutes:seconds. The Duration
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:
time_of_day<hours>
This specialization handles hours since midnight.
time_of_day<minutes>
This specialization handles hours:minutes since midnight.
time_of_day<seconds>
This specialization handles hours:minutes:seconds since midnight.
time_of_day<duration<Rep, Period>>
This specialization is restricted to
Period
s that are shorter than 1 second. 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 of time_of_day
is a standard-layout class type.
Each specialization of time_of_day
is a literal class type.
time_of_day<hours> { public: using precision = hours; constexpr explicit time_of_day(hours since_midnight) noexcept; constexpr time_of_day(hours h, unsigned md) noexcept; constexpr hours hours() const noexcept; constexpr unsigned mode() 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<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.mode()
returns0
.
constexpr time_of_day<hours>::time_of_day(hours h, unsigned md) noexcept;
Preconditions:
md == am
ormd == pm
.Effects: Constructs an object of type
time_of_day
in 12-hour format corresponding toh
hours after 00:00:00.Postconditions:
hours()
returnsh
, andmode()
returnsmd
.
constexpr hours time_of_day<hours>::hours() const noexcept;
Returns: The stored hour of
*this
.
constexpr unsigned time_of_day<hours>::mode() const noexcept;
Returns: 0 if
*this
is in 24-hour format. Otherwise returnsam
orpm
corresponding to whether this represents a before-noon time or afternoon time.
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}
.
void time_of_day<hours>::make24() noexcept;
Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.
void time_of_day<hours>::make12() noexcept;
Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.
ostream& operator<<(ostream& os, const time_of_day<hours>& t);
Effects: If
t
is a 24-hour time, outputs toos
according to thestrftime
format: "%H00". "%H" will emit a leading 0 for hours less than 10. Elset
is a 12-hour time, outputs toos
according to thestrftime
format: "%I%p" according to the C locale, except that no leading zero is output for hours less than 10.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 format
time_of_day<minutes> { public: using precision = minutes; constexpr explicit time_of_day(minutes since_midnight) noexcept; constexpr time_of_day(hours h, minutes m, unsigned md) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr unsigned mode() 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()
).mode()
returns0
.
constexpr time_of_day<minutes>::time_of_day(hours h, minutes m, unsigned md) noexcept;
Preconditions:
md == am
ormd == pm
.Effects: Constructs an object of type
time_of_day
in 12-hour format corresponding toh
hours andm
minutes after 00:00:00.Postconditions:
hours()
returnsh
,minutes()
returnsm
, andmode()
returnsmd
.
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 unsigned time_of_day<minutes>::mode() const noexcept;
Returns: 0 if
*this
is in 24-hour format. Otherwise returnsam
orpm
corresponding to whether this represents a before-noon time or afternoon time.
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.
ostream& operator<<(ostream& os, const time_of_day<minutes>& t);
Effects: If
t
is a 24-hour time, outputs toos
according to thestrftime
format: "%H:%M". "%H" will emit a leading 0 for hours less than 10. Elset
is a 12-hour time, outputs toos
according to thestrftime
format: "%I:%M%p" according to the C locale, except that no leading zero is output for hours less than 10.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 format
time_of_day<seconds> { public: using precision = seconds; constexpr explicit time_of_day(seconds since_midnight) noexcept; constexpr time_of_day(hours h, minutes m, seconds s, unsigned md) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr seconds seconds() const noexcept; constexpr unsigned mode() 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()
).mode()
returns0
.
constexpr time_of_day<seconds>::time_of_day(hours h, minutes m, seconds s, unsigned md) noexcept;
Preconditions:
md == am
ormd == pm
.Effects: Constructs an object of type
time_of_day
in 12-hour format corresponding toh
hours,m
minutes, ands
seconds after 00:00:00.Postconditions:
hours()
returnsh
.minutes()
returnsm
.seconds()
returnss
.mode()
returnsmd
.
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 unsigned time_of_day<seconds>::mode() const noexcept;
Returns: 0 if
*this
is in 24-hour format. Otherwise returnsam
orpm
corresponding to whether this represents a before-noon time or afternoon time.
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.
ostream& operator<<(ostream& os, const time_of_day<seconds>& t);
Effects: If
t
is a 24-hour time, outputs toos
according to thestrftime
format: "%H:%M%S". "%H" will emit a leading 0 for hours less than 10. Elset
is a 12-hour time, outputs toos
according to thestrftime
format: "%I:%M%S%p" according to the C locale, except that no leading zero is output for hours less than 10.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 format
time_of_day<duration<Rep, Period>> { public: using precision = duration<Rep, Period>; constexpr explicit time_of_day(precision since_midnight) noexcept; constexpr time_of_day(hours h, minutes m, seconds s, precision sub_s, unsigned md) noexcept; constexpr hours hours() const noexcept; constexpr minutes minutes() const noexcept; constexpr seconds seconds() const noexcept; constexpr precision subseconds() const noexcept; constexpr unsigned mode() 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 duration<Rep, Period>{1} < 1s
.
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
).mode()
returns0
.
constexpr time_of_day<duration<Rep, Period>>::time_of_day(hours h, minutes m, seconds s, precision sub_s, unsigned md) noexcept;
Preconditions:
md == am
ormd == pm
.Effects: Constructs an object of type
time_of_day
in 12-hour format corresponding toh
hours,m
minutes, ands + sub_s
seconds after 00:00:00.Postconditions:
hours()
returnsh
.minutes()
returnsm
.seconds()
returnss
.subseconds()
returnssub_s
.mode()
returnsmd
.
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 unsigned time_of_day<duration<Rep, Period>>::mode() const noexcept;
Returns: 0 if
*this
is in 24-hour format. Otherwise returnsam
orpm
corresponding to whether this represents a before-noon time or afternoon time.
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.
ostream& operator<<(ostream& os, const time_of_day<duration<Rep, Period>>& t);
Effects: If
t
is a 24-hour time, outputs toos
according to thestrftime
format: "%H:%M%S.%s". "%H" will emit a leading 0 for hours less than 10. "%s" is not astrftime
code and represents the fractional seconds. Elset
is a 12-hour time, outputs toos
according to thestrftime
format: "%I:%M%S.%s%p" according to the C locale, except that no leading zero is output for hours less than 10.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)
make_time
[time.time_of_day.make_time]
These helper functions ease the construction of time_of_day
objects by
deducing the precision for the time_of_day
return type from the argument to
the helper function.
template <class Rep, class Period> constexpr time_of_day<duration<Rep, Period>> make_time(duration<Rep, Period> d) noexcept;
Returns:
time_of_day<duration<Rep, Period>>(d)
.
constexpr time_of_day<hours> make_time(hours h, unsigned md) noexcept;
Returns:
time_of_day<hours>(h, md)
.
constexpr time_of_day<minutes> make_time(hours h, minutes m, unsigned md) noexcept;
Returns:
time_of_day<minutes>(h, m, md)
.
constexpr time_of_day<seconds> make_time(hours h, minutes m, seconds s, unsigned md) noexcept;
Returns:
time_of_day<seconds>(h, m, s, md)
.
template <class Rep, class Period, class = enable_if_t<ratio_less<Period, ratio<1>>::value>> constexpr time_of_day<duration<Rep, Period>> make_time(hours h, minutes m, seconds s, duration<Rep, Period> sub_s, unsigned md) noexcept
Returns:
time_of_day<duration<Rep, Period>>(h, m, s, sub_s, md)
.
Add new section [time.timezone] after 20.15.9 Class
time_of_day
[time.time_of_day]:
This clause creates an API which exposes the IANA Time Zone database, and
interfaces with sys_time
and local_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 with
sys_time
and local_time
.
The following data structure is the time zone database, and the following functions access it.
struct TZ_DB { string version; vector<time_zone> zones; vector<link> links; vector<leap> leaps; };
The reload_tzdb()
which re-initializes it.
Each vector
is sorted to enable fast lookup. You can iterate over
and inspect this database.
const TZ_DB& get_tzdb();
Effects: If this is the first access to the database, will initialize the database.
Returns: A
const
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 validTZ_DB
.
const time_zone* locate_zone(const string& tz_name);
Effects: Calls
get_tzdb()
which will initialize the timezone database if this is the first reference to the database.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: Any exception propagated from
get_tzdb()
. If aconst 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* current_zone();
Effects: Callslocate_zone()
which will initialize the timezone database if this is the first reference to the database.Returns: A
const time_zone*
referring to the time zone which your computer has set as its local time zone.Throws: Any exception propagated from
locate_zone()
. [Note: On non-exceptional return, the return value is always a pointer to a validtime_zone
. — end note]
This subsection is optional/seperable and needs further discussion in the LEWG. No other sections depend upon this subsection.
const TZ_DB& reload_tzdb();
Effects: This function first checks the latest version at the IANA website. If the IANA website is unavailable, or if the latest version is already installed, there are no effects. Otherwise, a new version is available. It is downloaded and installed, and then the program re-initializes the
TZ_DB
singleton from the new disk files.Returns: A
const
reference to the database.Thread Safety: This function is not thread safe. You must provide your own synchronization among threads accessing the time zone database to safely use this function. If this function re-initializes the database, all outstanding
const time_zone*
are invalidated (including those held withinzoned_time
objects). And afterwards, all outstandingsys_info
may hold obsolete data.Throws:
runtime_error
if for any reason a reference can not be returned to a validTZ_DB
.
string remote_version();
Returns: The latest database version number from the IANA website. If the IANA website can not be reached, or if it can be reached but the latest version number is unexpectedly not available, the empty string is returned.
Note: If non-empty, this can be compared with
get_tzdb().version
to discover if you have the latest database installed.
bool remote_download(const string& version);
Effects: If
version == remote_version()
this function will download the compressed tar file holding the latest time zone database from the IANA website. The tar file will be placed at an unspecified location.Returns:
true
if the database was successfully downloaded, elsefalse
.Thread safety: If called by multiple threads, there will be a race on the creation of the tar file.
bool remote_install(const string& version);
Effects: If
version
refers to the file successfully downloaded byremote_download()
this function will remove the existing time zone database, then extract a new database from the tar file, and will then delete the tar file.This function does not cause your program to re-initialize itself from this new database. In order to do that, you must call
reload_tzdb()
(orget_tzdb()
if the database has yet to be initialized).Returns:
true
if the database was successfully replaced by the tar file , elsefalse
.Thread safety: If called by multiple threads, there will be a race on the creation of the new database.
nonexistent_local_time
is thrown when one attempts to convert a
non-existent local_time
to a sys_time
without specifying
choose::earliest
or choose::latest
.
class nonexistent_local_time : public runtime_error { public: // Construction is undocumented };
[Example:
#include "tz.h" #include <iostream> int main() { using namespace std::chrono; try { auto zt = make_zoned("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 ambiguous
local_time
to a sys_time
without specifying
choose::earliest
or choose::latest
.
class ambiguous_local_time : public runtime_error { public: // Construction is undocumented };
[Example:
#include "tz.h" #include <iostream> int main() { using namespace std::chrono; try { auto zt = make_zoned("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:]
A sys_info
structure can be obtained from the combination of a time_zone
and
either a sys_time
, or local_time
. It can also be obtained
from a zoned_time
which is effectively a pair
of
a time_zone
and sys_time
.
This structure represents a lower-level API. Typical conversions from
sys_time
to local_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
and end
fields indicate that for the
associated time_zone
and time_point
, the
offset
and abbrev
are in effect in the range
[begin, end)
. This information can be used to efficiently iterate the
transitions of a time_zone
.
The offset
field indicates the UTC offset in effect for the associated
time_zone
and time_point
. The relationship between
local_time
and sys_time
is:
offset = local_time - sys_time
The save
field is "extra" information not normally needed for
conversion between local_time
and sys_time
. If
save != 0min
, this sys_info
is said to be on "daylight
saving" time, and offset - save
suggests what this
time_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 the time_zone
with a
time_point
that returns an sys_info
where
save == 0min
. There is no guarantee what time_point
might return such
an sys_info
except that it is guaranteed not to be in the range
[begin, end)
(if save != 0min
for this sys_info
).
The abbrev
field indicates the current abbreviation used for the
associated time_zone
and time_point
. Abbreviations
are not unique among the time_zone
s, and so one can not reliably
map abbreviations back to a time_zone
and UTC offset.
A sys_info
can be streamed out in an unspecified format:
ostream& operator<<(ostream& os, const sys_info& r);
A local_info
structure represents a lower-level API. Typical conversions from
local_time
to sys_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
to sys_time
conversion is unique,
result == unique
, first
will be filled out with the
correct sys_info
and second
will be zero-initialized.
If the conversion stems from a nonexistent local_time
then
result == nonexistent
, first
will be filled out with
the sys_info
that ends just prior to the local_time
and second
will be filled out with the sys_info
that
begins just after the local_time
. If the conversion stems from an
ambiguous local_time
then result == ambiguous
,
first
will be filled out with the sys_info
that ends
just after the local_time
and second
will be filled
out with the sys_info
that starts just before the
local_time
.
A local_info
can be streamed out in an unspecified format:
ostream& operator<<(ostream& os, const local_info& r);
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 gain const
access to a
time_zone
via functions such as locate_zone
.
class time_zone { public: time_zone(const time_zone&) = delete; time_zone& operator=(const time_zone&) = delete; const string& name() const; 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); bool operator!=(const time_zone& x, const time_zone& y); bool operator< (const time_zone& x, const time_zone& y); bool operator> (const time_zone& x, const time_zone& y); bool operator<=(const time_zone& x, const time_zone& y); bool operator>=(const time_zone& x, const time_zone& y); ostream& operator<<(ostream& os, const time_zone& z)
const string& time_zone::name() const;
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);
Returns:
x.name() == y.name()
.
bool operator!=(const time_zone& x, const time_zone& y);
Returns:
!(x == y)
.
bool operator<(const time_zone& x, const time_zone& y);
Returns:
x.name() < y.name()
.
bool operator>(const time_zone& x, const time_zone& y);
Returns:
y < x
.
bool operator<=(const time_zone& x, const time_zone& y);
Returns:
!(y < x)
.
bool operator>=(const time_zone& x, const time_zone& y);
Returns:
!(x < y)
.
ostream& operator<<(ostream& os, const time_zone& z)
Produces an unspecified output representing the
time_zone
.
zoned_time
[time.timezone.zoned_time]
zoned_time
represents a logical paring of time_zone
and a
time_point
with precision Duration
. If seconds
is not implicitly convertible to Duration
, the instantiation is ill-formed.
[Note: There exist time_zone
s with UTC offsets that require a
precision of seconds
. — end note:]
template <class Duration> class zoned_time { const time_zone* zone_; // exposition only sys_time<Duration> tp_; // exposition only public: zoned_time(const zoned_time&) = default; zoned_time& operator=(const zoned_time&) = default; zoned_time(sys_time<Duration> st); explicit zoned_time(const time_zone* z); explicit zoned_time(const string& name); template <class Duration2> zoned_time(const zoned_time<Duration2>& zt) noexcept; zoned_time(const time_zone* z, local_time<Duration> tp); zoned_time(const string& name, local_time<Duration> tp); zoned_time(const time_zone* z, local_time<Duration> tp, choose c); zoned_time(const string& name, local_time<Duration> tp, choose c); zoned_time(const time_zone* z, const zoned_time<Duration>& zt); zoned_time(const string& name, const zoned_time<Duration>& zt); zoned_time(const time_zone* z, const zoned_time<Duration>& zt, choose); zoned_time(const string& name, const zoned_time<Duration>& zt, choose); zoned_time(const time_zone* z, const sys_time<Duration>& st); zoned_time(const string& name, const sys_time<Duration>& st); zoned_time& operator=(sys_time<Duration> st); zoned_time& operator=(local_time<Duration> ut); operator sys_time<Duration>() const; explicit operator local_time<Duration>() const; const time_zone* 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> bool operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y); template <class Duration1, class Duration2> bool operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
An invariant of zoned_time<Duration>
is that it always refers
to a valid time_zone
, and represents a point in time that exists
and is not ambiguous.
zoned_time<Duration>::zoned_time(const zoned_time&) = default; zoned_time<Duration>& 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>::zoned_time(sys_time<Duration> st);
Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()->name() == "UTC"
, andzt.get_sys_time() == st
.
explicit zoned_time<Duration>::zoned_time(const time_zone* z);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_sys_time() == sys_seconds{}
.
explicit zoned_time<Duration>::zoned_time(const string& name);
Effects: Equivalent to construction with
locate_zone(name)
.Throws: Any exception propagating out of
locate_zone(name)
.
template <class Duration2> zoned_time<Duration>::zoned_time(const zoned_time<Duration2>& 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>::zoned_time(const time_zone* z, local_time<Duration> tp);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_local_time() == tp
.Throws: Any exception that
z->to_sys(tp)
would throw.
zoned_time<Duration>::zoned_time(const string& name, local_time<Duration> tp);
Effects: Equivalent to construction with
{locate_zone(name), tp}
.
zoned_time<Duration>::zoned_time(const time_zone* z, local_time<Duration> tp, choose c);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_sys_time() == z->to_sys(tp, c)
.
zoned_time<Duration>::zoned_time(const string& name, local_time<Duration> tp, choose c);
Effects: Equivalent to construction with
{locate_zone(name), tp, c}
.
zoned_time<Duration>::zoned_time(const time_zone* z, const zoned_time<Duration>& y);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_sys_time() == y.get_sys_time()
.
zoned_time<Duration>::zoned_time(const string& name, const zoned_time<Duration>& y);
Effects: Equivalent to construction with
{locate_zone(name), y}
.
zoned_time<Duration>::zoned_time(const time_zone* z, const zoned_time<Duration>& y, choose);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_sys_time() == y.get_sys_time()
.Note: The
choose
parameter is allowed here, but has no impact.
zoned_time<Duration>::zoned_time(const string& name, const zoned_time<Duration>& y, choose);
Effects: Equivalent to construction with
{locate_zone(name), y}
.Note: The
choose
parameter is allowed here, but has no impact.
zoned_time<Duration>::zoned_time(const time_zone* z, const sys_time<Duration>& st);
Requires:
z
refers to a validtime_zone
.Effects: Constructs a
zoned_time
zt
such thatzt.get_time_zone()-> == z
, andzt.get_sys_time() == st
.
zoned_time<Duration>::zoned_time(const string& name, const sys_time<Duration>& st);
Effects: Equivalent to construction with
{locate_zone(name), st}
.
zoned_time<Duration>& zoned_time<Duration>::operator=(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>& zoned_time<Duration>::operator=(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>::operator sys_time<Duration>() const;
Returns:
get_sys_time()
.
explicit zoned_time<Duration>::operator local_time<Duration>() const;
Returns:
get_local_time()
.
const time_zone* zoned_time<Duration>::get_time_zone() const;
Returns:
zone_
.
local_time<Duration> zoned_time<Duration>::get_local_time() const;
Returns:
zone_->to_local(tp_)
.
sys_time<Duration> zoned_time<Duration>::get_sys_time() const;
Returns:
tp_
.
sys_info zoned_time<Duration>::get_info() const;
Returns:
zone_->get_info(tp_)
.
template <class Duration1, class Duration2> bool operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
Returns:
x.zone_ == y.zone_ && x.tp_ == y.tp_
.
template <class Duration1, class Duration2> bool operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
Returns:
!(x == y)
.
templateostream& operator<<(ostream& os, const zoned_time & t)
Effects: Streams
t
toos
using the format "%F %T %Z" and the value returned fromt.get_local_time()
.Returns:
os
.
make_zoned
[time.timezone.make_zoned]
There exist several overloaded functions named make_zoned
which serve as factory functions for zoned_time<Duration>
and
will deduce the correct Duration
from the argument list. In every
case the correct return type is
zoned_time<common_type_t<Duration, seconds>>
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(sys_time<Duration> tp)
Returns:
{tp}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, local_time<Duration> tp)
Returns:
{zone, tp}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, local_time<Duration> tp)
Returns:
{name, tp}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, local_time<Duration> tp, choose c)
Returns:
{zone, tp, c}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, local_time<Duration> tp, choose c)
Returns:
{name, tp, c}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const zoned_time<Duration>& zt)
Returns:
{zone, zt}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const zoned_time<Duration>& zt)
Returns:
{name, zt}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const zoned_time<Duration>& zt, choose c)
Returns:
{zone, zt, c}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const zoned_time<Duration>& zt, choose c)
Returns:
{name, zt, c}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const time_zone* zone, const sys_time<Duration>& st)
Returns:
{zone, st}
.
template <class Duration> zoned_time<common_type_t<Duration, seconds>> make_zoned(const string& name, const sys_time<Duration>& st)
Returns:
{name, st}
.
template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, local_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, local_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, const zoned_time<Duration>& tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, const zoned_time<Duration>& tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(const locale& loc, basic_string<class CharT, class Traits> format, sys_time<Duration> tp); template <class CharT, class Traits, class Duration> basic_string<class CharT, class Traits> format(basic_string<class CharT, class Traits> format, sys_time<Duration> tp); // const CharT* formats template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, local_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, local_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, const zoned_time<Duration>& tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, const zoned_time<Duration>& tp); template <class CharT, class Duration> basic_string<class CharT> format(const locale& loc, const CharT* format, sys_time<Duration> tp); template <class CharT, class Duration> basic_string<class CharT> format(const CharT* format, sys_time<Duration> tp);
Effects: These functions create a formatted time stamp using the arguments, returning the result in a
string
.If a
locale
is passed in, then thatlocale
is used for any formatting that requires alocale
. If nolocale
is passed in, then if alocale
is required for formatting, a default constructedlocale
will be used (which makes a copy of the globallocale
).The
format
string follows the rules as specified fortime_put
with the following exceptions:
If
%S
or%T
appears in theformat
string and the argumenttp
has precision finer than seconds, then seconds are formatted as a decimal floating point number with a fixed format and a precision matching that of the precision oftp
. The character for the decimal point is localized according to thelocale
.If
%z
appears in the format, the behavior depends on the type oftp
:
local_time
: An exception of typeruntime_error
is thrown.zoned_time
: The offset associated withtp.get_time_zone()
is used.sys_time
:"+0000"
is used.If
%Z
appears in the format, the behavior depends on the type oftp
:
local_time
: An exception of typeruntime_error
is thrown.zoned_time
: The abbreviation associated withtp.get_time_zone()
is used.sys_time
:"UTC"
is used.For the overloads taking a
zoned_time
it is the value returned bytz.get_local_time()
that is formatted.Returns: The formatted string.
One can parse in a sys_time<Duration>
or a
local_time<Duration>
. Optionally, one can also pass in a reference
to a string
in order to capture the time zone abbreviation, or one
can pass in a reference to a minutes
to capture a time zone
UTC offset (formatted as +0000
), or one can pass in both in either order.
template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, sys_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const basic_string<CharT, Traits>& format, local_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); // const CharT* formats template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, sys_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, basic_string<CharT, Traits>& abbrev, minutes& offset); template <class CharT, class Traits, class Duration> void parse(basic_istream<CharT, Traits>& is, const CharT* format, local_time<Duration>& tp, minutes& offset, basic_string<CharT, Traits>& abbrev);
Effects: These functions attempt to parse a
time_point
out ofis
according toformat
. If the parse is unsuccessful, callsis.setstate(ios::failbit)
which may throw an exception.tp
,abbrev
, andoffset
are altered only in the event of a successful parse.The
format
string follows the rules as specified fortime_get
with the following exceptions:
If
%S
or%T
appears in theformat
string and the argumenttp
has precision finer than seconds, then the seconds are parsed as adouble
, and if that parse is successful contributes to the time stamp as ifround<Duration>(duration<double>{s})
wheres
is a local variable holding the parseddouble
.If
%z
appears in theformat
string and an offset is successfully parsed, the overloads takingsys_time
interprets the parsed time as a local time and subtracts the offset prior to assigning the value totp
, resulting in a value oftp
representing a UTC timestamp. The overloads takinglocal_time
require a valid parse of the offset, but then ignore the offset in assigning a value to thelocal_time<Duration>& tp
. Ifoffset
is passed in, on successful parse it will hold the value represented by%z
if present, or will be assigned0min
if%z
is not present.If
%Z
appears in theformat
string then an abbreviation is required in that position for a successful parse. The abbreviation will be parsed as astring
(delimited by white space). The parsed abbreviation does not have to be a valid time zone abbreviation, and has no impact on the value parsed intotp
. Using the overloads that take astring&
one can discover what that parsed abbreviation is. On successful parse,abbrev
will be assigned the value represented by%Z
if present, or assigned the empty string if%Z
is not present.Note: There is no unique mapping from a time zone abbreviation to a
time_zone
. But given a time zone abbreviation and asys_time
orlocal_time
, one could make a list of potentialtime_zone
s. Given a UTC offset, one might even narrow that list down further.
class utc_clock { public: using duration = system_clock::duration; using rep = duration::rep; using period = duration::period; using time_point = chrono::time_point<utc_clock>; static constexpr bool is_steady = true; static time_point now() noexcept; template <class Duration> static utc_time<common_type_t<Duration, seconds>> sys_to_utc(sys_time<Duration> t); template <class Duration> static sys_time<common_type_t<Duration, seconds>> utc_to_sys(utc_time<Duration> u); };
In contrast to sys_time
which does not take leap seconds into
account, utc_clock
and its associated time_point
,
utc_time
, counts time, including leap seconds, since
1970-01-01 00:00:00 UTC. It also provides functions for converting between
utc_time
and sys_time
. These functions consult
get_tzdb().leaps
to decide how many seconds to add/subtract
in performing those conversions.
static utc_clock::time_point utc_clock::now() noexcept;
Returns:
sys_to_utc(system_clock::now())
.
template <class Duration> static utc_time<common_type_t<Duration, seconds>> utc_clock::sys_to_utc(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 ambiguous on this issue (i.e. corresponds to the date of leap second insertion), then the conversion counts that leap second as inserted.
template <class Duration> static sys_time<common_type_t<Duration, seconds>> utc_clock::utc_to_sys(utc_time<Duration> u);
Returns: A
sys_time
t
, such thatutc_clock::sys_to_utc(t) == u
.
template <class Duration> utc_time<common_type_t<Duration, seconds>> to_utc_time(sys_time<Duration> t)
Returns:
utc_clock::sys_to_utc(t)
.
template <class Duration> sys_time<common_type_t<Duration, seconds>> to_sys_time(utc_time<Duration> u)
Returns:
utc_clock::utc_to_sys(u)
.
[Example:
#include "tz.h" #include <iostream> int main() { using namespace std::chrono; auto t0 = sys_days{1972y/jul/1} - 1ms; auto u0 = to_utc_time(t0); auto t1 = to_sys_time(u0); std::cout << t0 << ":\n"; std::cout << (u0.time_since_epoch() - t0.time_since_epoch()).count() << "ms\n"; std::cout << (t1 - t0).count() << "ms\n\n"; t0 += 1ms; u0 = to_utc_time(t0); t1 = to_sys_time(u0); std::cout << t0 << ":\n"; std::cout << (u0.time_since_epoch() - t0.time_since_epoch()).count() << "ms\n"; std::cout << (t1 - t0).count() << "ms\n"; }Output:
1972-06-30 23:59:59.999: 0ms 0ms 1972-07-01 00:00:00.000: 1000ms 0ms
— end example]
leap
[time.timezone.leap]class leap { 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 a sys_seconds
with the member function date()
and that will be the date of the leap second
insertion. leap
is equality and less-than comparable, both with itself, and
with sys_time<Duration>
.
link
[time.timezone.link]class link { 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 a time_zone
. The alternative
name is name()
. The name of the time_zone
for which this is
an alternative name is target()
. link
s will be constructed
for you when the time zone database is initialized.
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.
And I would also especially like to thank contributors to this library: gmcode, Ivan Pizhenko, tomy2105 and Ville Voutilainen.
N. Dershowitz and E. Reingold, Calendrical Calculations 3rd ed., Cambridge University Press 2008.