date
This paper fully documents a date and time library for use with C++11 and C++14.
This entire library is implemented in a single header: date.h and is open source.
It uses the algorithms from
chrono
-Compatible Low-Level Date Algorithms.
If you want detailed explanations of the algorithms, go there.
It performs best with C++14, which has vastly improved constexpr
rules.
However, the library will auto-adopt to C++11, sacrificing several constexpr
declarations. In C++11, this will effectively transfer some computations that should be
done at compile-time to run-time. Porting to C++98/03 has not been attempted.
Here is an overview of all the types we are going to talk about at some point. They are all fully covered in the reference section. This link is just there to give you a view of everything on one quick page so that you don't get lost or overwhelmed. Many of these types will never need to be explicitly named in typical use cases.
date_types.jpeg
This library builds date and date/time support on top of the <chrono>
library. However it does not support timezones nor leap seconds. A
separate library is provided, built on top of this one, for timezone
and leap second support. Thus you only pay for such support if you need it.
A date on a calendar is a time point with a resolution of one day. This is not
conceptually different from std::chrono::system_clock::time_point
which is a
time point with a resolution of std::chrono::system_clock::period
(typically
on the order of a microsecond or nanosecond). Time points are divided into two basic
types:
This terminology is gratefully borrowed from
N3344. In
short, a serial-based time point stores a single count of time durations from some epoch.
std::chrono::system_clock::time_point
is an example of a serial-based
time point. A count of days from some epoch is also a serial-based time point.
A field-based time point represents the same concept, but with several fields that
are typically used for human consumption. For example one might represent the time of day
with the number of seconds since midnight (serial-based), or with a structure such
as {hours, minutes, seconds}
since midnight (field-based). Similarly
one can represent a date with a count of days, or with a {year, month, day}
structure. Both representations are useful, and each has its strengths and weaknesses.
This library is composed of many types. But here are the most important ones:
sys_days
: A count of days since system_clock
's epoch. This
is a serial-based time point with a resolution of one day.year_month_day
: A type that holds a year (e.g. 2015), a month
(encoded as 1 thru 12), and a day (encoded as 1 thru 31). This is a field-based time
point with a resolution of one day.year_month_weekday
: A type that holds a year (e.g. 2015), a month
(encoded as 1 thru 12), a day of the week (encoded as 0 thru 6), and an index in the range
[1, 5] indicating if this is the first, second, etc. weekday of the indicated month. This
is a field-based time point with a resolution of one day.
The entire library is in namespace date
. The examples in this
overview assume:
using namespace date; using namespace std::chrono;
in order to cut down on the verbosity.
year_month_day
constexpr
dates can be constructed from literals in any one of 3 orders:
constexpr auto x1 = 2015_y/March/22; constexpr auto x2 = March/22/2015; constexpr auto x3 = 22_d/March/2015;
x1
, x2
and x3
all have the type:
year_month_day
, and are all equal to one another. Any other order,
or any ambiguity is caught at compile time. These three orders were chosen
because these are the
three orders that people actually use.
Integral types can be converted to year
, month
, or
day
to create run time values:
int y = 2015; int m = 3; int d = 22; auto x1 = year{y}/m/d; auto x2 = month{m}/d/y; auto x3 = day{d}/m/y;
As long as the type of the first date component is known, the following components become
unambiguous and can be formed either with the proper type, or with an int
expression. And since there is only one order with day
in the middle, that
order need only properly type the day
to remain unambiguous:
auto x = m/day{d}/y;
No matter the order of the year
, month
and
day
specifiers, and no matter whether some of the fields implicitly
convert from int
, the type of these expressions is
year_month_day
. However because of auto
, it is very
often unimportant how to spell the somewhat verbose type name
year_month_day
. The compiler knows how to spell the type, and the
meaning is clear to the human reader without an explicit type.
If there is any ambiguity, the code will not compile. If the code does compile, it will be unambiguous and quite readable.
year_month_day_last
Anywhere you can specify a day
you can instead specify last
to indicate the last day of the month for that year:
constexpr auto x1 = 2015_y/February/last; constexpr auto x2 = February/last/2015; constexpr auto x3 = last/February/2015;
Instead of constructing a year_month_day
, these expressions construct a
year_month_day_last
. This type always represents the last day of a
year
and month
. year_month_day_last
will
implicitly convert to year_month_day
. Note though that because of
auto
both the reader and the writer of the code can very often remain
blissfully ignorant of the spelling of year_month_day_last
. The API of
year_month_day
and year_month_day_last
are virtually identical
so that the learning curve is shallow, and generic code usually does not need to know
which type it is operating on.
year_month_weekday
Anywhere you can specify a day
you can instead specify an indexed
weekday
to indicate the nth weekday of the month for that year:
constexpr auto x1 = 2015_y/March/Sunday[4]; constexpr auto x2 = March/Sunday[4]/2015; constexpr auto x3 = Sunday[4]/March/2015;
The type constructed is year_month_weekday
which will implicitly convert to
and from a sys_days
. If you want to convert to a
year_month_day
you can do so explicitly, which will implicitly convert to
sys_days
and back:
constexpr auto x4 = year_month_day{x3};
year_month_weekday_last
weekday
's can be indexed with last
and used as above:
constexpr auto x1 = 2015_y/March/Sunday[last]; constexpr auto x2 = March/Sunday[last]/2015; constexpr auto x3 = Sunday[last]/March/2015; constexpr auto x4 = year_month_day{x3}; cout << x3 << '\n'; cout << x4 << '\n';
This creates an object of type year_month_weekday_last
. The above code
outputs:
Escape hatch from the conventional syntax2015/Mar/Sun[last] 2015-03-29
If you hate the conventional syntax, don't use it. Every type has a descriptive name, and public type-safe constructors to do the same job. The "conventional syntax" is a non-friended and zero-abstraction-penalty layer on top of a complete lower-level API.
constexpr auto x1 = 2015_y/March/Sunday[last]; constexpr auto x2 = year_month_weekday_last{year{2015}, month{3u}, weekday_last{weekday{0u}}}; static_assert(x1 == x2, "No matter the API, x1 and x2 have the same value ..."); static_assert(is_same<decltype(x1), decltype(x2)>::value, "... and are the same type"); cout << x1 << '\n'; cout << x2 << '\n'; 2015/Mar/Sun[last] 2015/Mar/Sun[last]
To get today as a sys_days
, use system_clock::now()
and
floor
to convert the time_point
to a
sys_days
:
auto today = floor<days>(system_clock::now()); cout << today << '\n';
Currently this outputs for me:
2015-03-22
To get today as a year_month_day
, get a sys_days
as above and
convert it to a year_month_day
:
auto today = year_month_day{floor<days>(system_clock::now())}; cout << today << '\n';
Which again currently outputs for me:
2015-03-22
To get today as a year_month_weekday
, get a sys_days
as above and
convert it to a year_month_weekday
:
auto today = year_month_weekday{floor<days>(system_clock::now())}; cout << today << '\n';
Currently this outputs for me:
2015/Mar/Sun[4]
This indicates that today (2015-03-22) is the fourth Sunday of Mar., 2015.
Just about everything C++ has for date handling, it inherits from C. I thought it would be fun to contrast an example that comes from the C standard with this library.
From the C standard: 7.27.2.3 The mktime
function, paragraph 4:
EXAMPLE What day of the week is July 4, 2001?
#include <stdio.h> #include <time.h> static const char *const wday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "-unknown-" }; int main() { struct tm time_str; time_str.tm_year = 2001 - 1900; time_str.tm_mon = 7 - 1; time_str.tm_mday = 4; time_str.tm_hour = 0; time_str.tm_min = 0; time_str.tm_sec = 0; time_str.tm_isdst = -1; if (mktime(&time_str) == (time_t)(-1)) time_str.tm_wday = 7; printf("%s\n", wday[time_str.tm_wday]); }
This program outputs:
Wednesday
Coding the same problem up in this library looks like:
#include "date.h" #include <iostream> int main() { using namespace date; std::cout << weekday{July/4/2001} << '\n'; }
which outputs:
Wed
And if we really want to show off, this can all be done at compile time:
#include "date.h" int main() { using namespace date; static_assert(weekday{2001_y/July/4} == Wednesday, ""); }
(Date ordering was switched simply to assure the gentle reader that we're not hung up on m/d/y ordering.)
No exceptions are thrown in the entire library, except those that might be thrown from
std::ostream
when streaming values to a std::ostream
. Most of
the types have a constexpr const
member function named ok()
which returns true
if the object represents a valid date, or date component,
and otherwise returns false
. However it is perfectly fine (and sometimes
actually useful) for these objects to contain invalid dates or date components. For
example, here is a very simple and remarkably efficient program to output the odd Fridays
of every month in 2015:
int main() { using namespace std; using namespace date; for (auto m = 1; m <= 12; ++m) { auto meet = year_month_day{m/Friday[1]/2015}; cout << meet << '\n'; meet = meet.year()/meet.month()/(meet.day()+weeks{2}); cout << meet << '\n'; meet = meet.year()/meet.month()/(meet.day()+weeks{2}); if (meet.ok()) cout << meet << '\n'; } }
There is a relatively expensive (expense is relative here — maybe as much as 100ns)
conversion from year_month_weekday
to year_month_day
at the top
of the loop to find the first Friday of the month. This computation can never fail. And
after that it is dirt cheap to find the 3rd Friday — you just have to add 2 weeks to
the day field. This computation also can never fail. And it is similarly cheap to find
the 5th Friday of each month. However, not every month has a fifth Friday. But
nevertheless it is ok to form such a year_month_day
. The computation can
never fail, though it may render an invalid date. Afterwards one can simply ask: Did I
create a valid date? If so, print it out, otherwise just continue on.
This program is easy to read, easy to write, will fail to compile if any careless errors are made, and extremely high performance. The date computations are dwarfed by the run time costs of the I/O.
Because practically nothing throws exceptions, this entire library is liberally sprinkled
with noexcept
.
A few of the operations have a precondition that ok() == true
. These are
generally conversions to sys_days
, and month-oriented and weekday-oriented
arithmetic. Anywhere there is a precondition, and those places are few, the precondition
is checkable with ok()
.
This library catches many errors (especially ambiguity errors) at compile time. What's
left over is left up to ok()
. Sometimes !ok()
will represent an
error, and other times it will simply represent something innocuous that can be ignored
(such as in the example above). If !ok()
actually represents an error that
must be dealt with, the choice of whether to assert or throw is made by the client of
this library.
In N3344
Pacifico, Meredith and Lakos present a thorough survey of date types and their performance.
This library has been strongly influenced by this excellent paper.
year_month_day
is equivalent to what N3344 terms YMD_4
. And
sys_days
is equivalent to what N3344 terms HH_SERIAL_RAW_4
.
N3344
aptly demonstrates that field-based date structures are good at some operations and poor
at others. And serial-based implementations are generally good at what the field-based
data structures are poor at, and poor at what the field-based data structures are good at.
Indeed, this is the genesis of the design of this library: Provide both data structures
and let the conversions among the data structures be provided by algorithms as shown in
chrono
-Compatible Low-Level Date Algorithms.
And additionally, just provide the API for each data structure that it can do efficiently.
Field types are good at returning the values of the fields. Serial types aren't (except
for weekdays). So year_month_day
has accessors for year
,
month
and day
. And sys_days
does not.
Field types are good at month and year-oriented arithmetic. Serial types aren't.
So year_month_day
has month and year-oriented arithmetic. And
sys_days
does not.
Serial types are good at day-oriented arithmetic. Field types aren't.
So sys_days
has day-oriented arithmetic. And year_month_day
does not. Though one can perform day-oriented arithmetic on the day field of a
year_month_day
, with no impact on the other fields.
To efficiently compute a day of the week, one first needs to compute a serial date. So
weekday
is constructible from sys_days
.
To demonstrate the efficiency of constructing a year_month_day
, a hypothetical
factory function has been created in the table below. And this is compared with a
simplistic struct YMD_4
and an obvious factory function for that. Each is
compiled using clang at an optimization of -O2 or higher.
year_month_day
constructor assembly date::year_month_day make_year_month_day(int y, int m, int d) { using namespace date; return year{y}/m/d; } struct YMD_4 { std::int16_t year; std::uint8_t month; std::uint8_t day; }; YMD_4 make_YMD_4(int y, int m, int d) { return {static_cast<std::int16_t>(y), static_cast<std::uint8_t>(m), static_cast<std::uint8_t>(d)}; } .globl __Z19make_year_month_dayiii .align 4, 0x90 __Z19make_year_month_dayiii: .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp shll $24, %edx shll $16, %esi andl $16711680, %esi movzwl %di, %eax orl %edx, %eax orl %esi, %eax popq %rbp retq .cfi_endproc .globl __Z10make_YMD_4iii .align 4, 0x90 __Z10make_YMD_4iii: .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp shll $24, %edx shll $16, %esi andl $16711680, %esi movzwl %di, %eax orl %esi, %eax orl %edx, %eax popq %rbp retq .cfi_endproc
One can see that the generated assembler is virtually identical for these two factory
functions. I.e. the code size and run time overhead of the "cute syntax" for constructing
a year_month_day
is zero, at least in optimized builds.
A similar experiment is made for constructing a sys_days
from a count of
days held in an int
. To do this one must first create a days
duration, and then construct the sys_days
from the days
duration. This is contrasted with the very simplistic struct SERIAL_4
.
sys_days
constructor assembly date::sys_days make_day_point(int z) { using namespace date; return sys_days{days{z}}; } struct SERIAL_4 { std::int32_t count; }; SERIAL_4 make_SERIAL_4(int z) { return {z}; } .globl __Z14make_day_pointi .align 4, 0x90 __Z14make_day_pointi: .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp movl %edi, %eax popq %rbp retq .cfi_endproc .globl __Z13make_SERIAL_4i .align 4, 0x90 __Z13make_SERIAL_4i: .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp movl %edi, %eax popq %rbp retq .cfi_endproc
It is easy to see that the generated code is identical, and thus there is no overhead
associated with the sys_days
type. It is also noteworthy that the code for
this construction does not actually come from this date
library, but instead
comes from your std::lib header <chrono>
. days
is nothing
but a type-alias for a std::chrono::duration
, and
sys_days
is nothing but a type-alias for a
std::chrono::time_point
(thus the inspiration for the name
sys_days
). So this is also evidence that there is zero overhead for the
type-safe system of the <chrono>
library.
One final example taken from real-world code. Below are two ways of implementing a system
which counts seconds since Jan. 1, 2000: One that uses this library and another that
simply stores the count of seconds in a long
. A utility is needed to convert
that count to Unix Time, which simply
involves shifting the epoch to Jan. 1, 1970.
Shift epoch from January/1/2000
toJanuary/1/1970
using time_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>; time_point shift_epoch(time_point t) { using namespace date; return t + (sys_days(January/1/2000) - sys_days(January/1/1970)); } long shift_epoch(long t) { return t + 946684800; } .globl __Z11shift_epochNSt3__16chrono10time_pointINS0... .align 4, 0x90 __Z11shift_epochNSt3__16chrono10time_pointINS0... .cfi_startproc ## BB#0: pushq %rbp Ltmp0: .cfi_def_cfa_offset 16 Ltmp1: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp2: .cfi_def_cfa_register %rbp leaq 946684800(%rdi), %rax popq %rbp retq .cfi_endproc .globl __Z11shift_epochl .align 4, 0x90 __Z11shift_epochl: .cfi_startproc ## BB#0: pushq %rbp Ltmp0: .cfi_def_cfa_offset 16 Ltmp1: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp2: .cfi_def_cfa_register %rbp leaq 946684800(%rdi), %rax popq %rbp retq .cfi_endproc
On the left we have a strongly typed solution which makes it explicit that the code is
adding a time duration equal to the difference between the two epochs. Though verbose,
the code is easy to read. On the right we have the maximally efficient, and yet relatively
cryptic implementation with long
. As it turns out, there are 946,684,800
seconds between these two epochs ... who knew?
clang generates identical assembly for these two functions at -O2 and higher. That
is, the sub-expression (sys_days(January/1/2000) - sys_days(January/1/1970))
is
reduced down to a number of days (10,957) at compile time, and then this
sub-expression, which has type days
is added to a time_point
with a resolution of seconds
, which causes the compiler to convert
days{10957}
to seconds{946684800}
, again at compile time.
And in the strongly typed case, if in the future one decides that one wants to count milliseconds instead of seconds, that can be changed in one place:
using time_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
Upon recompile the compiler automatically updates the compile-time constant in
shift_epoch
from 946684800 to 946684800000 (and everywhere else such as
where you perform the epoch shift in the reverse direction).
You already have a good one. It is called
std::chrono::system_clock::time_point
. And it is completely interoperable
with this library. std::chrono::system_clock::time_point
is a pointer to
a particular instant of time, with high precision (that precision is specified differently
on each platform). As we saw earlier, one can get a high-precision time_point
representing now with:
auto tp = system_clock::now();
This library provides a stream insertion operator for
system_clock::time_point
(in namespace date
).
std::cout << tp << '\n';
This currently outputs for me:
2015-04-19 18:24:42.770911
One can turn that into a time_point
with the precision of a day (which
has a type alias called sys_days
) with:
auto dp = floor<days>(tp);
And one can convert that day-oriented time_point
into a
{year, month, day}
field type with:
auto ymd = year_month_day{dp};
This section explains how to extract the time of day from the above information.
dp
can also be though of as a time_point
to the beginning of the
current day (in the UTC timezone). And so one can get the time duration
since midnight by subtracting the day-precision time_point
from the high
precision time_point
: tp-dp
. This results in a high precision
std::chrono::duration
representing the time since midnight.
This high precision duration
can be broken down into hours, minutes, seconds,
and fractions of a second with a time_of_day
object, which is most easily
created by using the make_time
factory function:
auto time = make_time(tp-dp);
Now both ymd
and time
can simply be printed out:
std::cout << ymd << ' ' << time << '\n';
Which will result in something like:
2015-04-19 18:24:42.770911
Indeed, this is exactly what the stream insertion operator for
system_clock::time_point
does. So if you don't like the default format,
this is how you pick apart a system_clock::time_point
so you can output it
in whatever format you prefer.
The above is the current date and time in the UTC timezone with microsecond precision.
On the platform I'm writing this, system_clock::time_point
counts
microseconds. When you run this code on your platform, the library will automatically
adapt to the precision supported by your platform's implementation of
system_clock::time_point
.
If you prefer output in a local time zone, you will need to discover your current UTC
offset and add that to tp
prior to applying floor
.
Your current UTC offset is a function of both your UTC time point tp
, and
your location. This functionality is not offered by this library, but can be built on top
of it. For example here is such a library. But as a simplistic
example, here is code that assumes an Eastern US location and daylight savings rules
currently in effect:
std::chrono::hours utc_offset_Eastern_US(std::chrono::system_clock::time_point tp) { using namespace date; using namespace std::chrono; constexpr auto EST = -5h; constexpr auto EDT = -4h; const auto y = year_month_day{floor<days>(tp)}.year(); const auto begin = sys_days{Sunday[2]/March/y} + 2h - EST; // EDT begins at this UTC time const auto end = sys_days{Sunday[1]/November/y} + 2h - EDT; // EST begins at this UTC time if (tp < begin || end <= tp) return EST; return EDT; } ... auto tp = system_clock::now(); tp += utc_offset_Eastern_US(tp); // tp now in Eastern US timezone std::cout << tp << '\n'; 2015-04-19 14:24:42.770911
And if you prefer your output in a 12-hour format with a precision of only minutes, that is also easily accomplished:
auto tp = system_clock::now(); tp += utc_offset_Eastern_US(tp); const auto tpm = floor<minutes>(tp); // truncate to minutes precision const auto dp = floor<days>(tpm); const auto ymd = year_month_day{dp}; auto time = make_time(tpm-dp); // minutes since midnight time.make12(); // change to 12-hour format std::cout << ymd << ' ' << time << '\n'; 2015-04-19 2:24pm
The hub of this library is sys_days
. This is a serial-based time
point which simply counts the days since (or before) January/1/1970
. And
ironically this all important hub is nothing but a type alias to a std-defined type. That
is, the central theme this library is built around is nothing more than this:
using sys_days = std::chrono::time_point<std::chrono::system_clock, days>;
Types such as year_month_day
and year_month_weekday
provide
implicit conversions to and from sys_days
, and because of this, the C++
language provides explicit conversions between year_month_day
and
year_month_weekday
.
You can easily build your own types that implicitly convert to and from
sys_days
, and when you do, you automatically gain explicit convertibility to
and from every other type which ties into sys_days
. For example, here is
how you could create a custom type that models the ISO week-based calendar:
class iso_week { date::year y_; date::weeks w_; date::weekday wd_; public: constexpr iso_week(date::sys_days dp) noexcept : iso_week(iso_week_from_day_point(dp)) {} constexpr iso_week(date::year y, date::weeks w, date::weekday wd) noexcept : y_(y) , w_(w) , wd_(wd) {} constexpr operator date::sys_days() const noexcept { using namespace date; return iso_week_start(y_) + w_ - weeks{1} + (wd_ - Monday); } friend std::ostream& operator<<(std::ostream& os, const iso_week& x) { return os << x.y_ << "-W(" << x.w_.count() << ")-" << x.wd_; } private: static constexpr date::sys_days iso_week_start(date::year y) noexcept { using namespace date; return sys_days{Thursday[1]/January/y} - (Thursday-Monday); } static constexpr iso_week iso_week_from_day_point(date::sys_days dp) noexcept { using namespace date; using namespace std::chrono; auto y = year_month_day{dp}.year(); auto start = iso_week_start(y); if (dp < start) { --y; start = iso_week_start(y); } else { auto const next_start = iso_week_start(y+years{1}); if (dp >= next_start) { ++y; start = next_start; } } return {y, duration_cast<weeks>(dp - start) + weeks{1}, weekday{dp}}; } };
The rules for the ISO week-based calendar are fairly simple:
With that in mind, one can easily create a field-based data structure that holds
a year
, a week number, and a day of the week, and then provides conversions
to and from sys_days
.
The key points of this class (for interoperability) are the constructor
iso_week(date::sys_days dp)
and the operator date::sys_days()
.
To aid in these computations a private helper function is created to compute the
sys_days
corresponding to the first day of the week-based year. And according
to rule 2, this can be elegantly coded as:
return sys_days{Thursday[1]/January/y} - (Thursday-Monday);
That is, first find the first Thursday in January for year y
, and then subtract
the number of days required to find the Monday before this day. This could have been done
with days{3}
. But I chose to code this as (Thursday-Monday)
.
Computationally and performance wise, these two choices are identical: they both subtract
the literal 3. I chose the latter because I believe it to be more readable.
"3
" is just a magic constant. But "(Thursday-Monday)
" is the number of
days Thursday is past Monday.
The constructor iso_week(date::sys_days dp)
has to first discover which
ISO week-based year the sys_days dp
falls into. Most often this is the
same as the civil (year_month_day
) year number associated dp
.
But because the week-based year may start a few days earlier or later than
January/1
, the week-based year number may be one less or one greater than the
civil year number associated dp
. Once the proper start of the week-based year
is nailed down (in start
), the translation to the field-based
iso_week
is trivial:
return {y, duration_cast<weeks>(dp - start) + weeks{1}, weekday{dp}};
The conversion from iso_week
to sys_days
is even easier:
return iso_week_start(y_) + w_ - weeks{1} + (wd_ - Monday);
It is the the start of the week-based year, plus the number of weeks (minus one since this
count is 1-based), plus the number of days the weekday
is past Monday. Note
that because weekday
subtraction is treated as a circular range (always
results in a number of days in the range [0, 6]), the logic at this level is simplified.
That is, Sunday is 6 days past Monday, not one day before it (and Monday is still one day
past Sunday). So the encoding used for weekday
is irrelevant; safely
encapsulated within weekday
. Said differently, weekday
arithmetic is unsigned, modulo 7.
With the above code, one can now write programs such as the one below which demonstrates
easy convertibility among the date
field-types and your custom
field-type.
int main() { using namespace date; using namespace std; using namespace std::chrono; auto dp = floor<days>(system_clock::now()); auto ymd = year_month_day{dp}; cout << ymd << '\n'; auto iso = iso_week{ymd}; cout << iso << '\n'; auto ymwd = year_month_weekday{iso}; cout << ymwd << '\n'; assert(year_month_day{iso} == ymd); }
Which will output something like:
2015-05-20 2015-W(21)-Wed 2015/May/Wed[3]
As long as you can relate your custom field-based structure (be it the Julian
calendar, the Hindu calendar, or the Maya calendar) to the number of days before and after
civil 1970-01-01, you can achieve interoperability with every other field-based
structure that does so. And obviously you can then also convert your custom calendar to
UTC (std::chrono::system_clock::time_point
). This is the Rosetta Stone of
time keeping.
For an example of a fully developed
ISO week date calendar
which is fully interoperable with this library via the technique described above see
iso_week
.
As with all numerical representations with a fixed storage size, duration
s,
time_point
s, and year_month_day
s have a fixed range, outside
of which they overflow. With this library, and with <chrono>
, the
range varies with precision.
On one side nanoseconds
is represented by a int64_t
which has a range of about +/- 292 years. And on the other side year
is represented by a int16_t
which has a range of about +/- 32 thousand
years. It is informative and educational to write software which explores the
intersection of these two constraints for various precisions, and outputs the result
in terms of a sys_time
.
Here is a function which will discover the limits for a single durration D
:
#include "date.h" #include <iomanip> #include <iostream> #include <cstdint> template <class D> void limit(const std::string& msg) { using namespace date; using namespace std; using namespace std::chrono; using dsecs = sys_time<duration<double>>; constexpr auto ymin = sys_days{year::min()/January/1}; constexpr auto ymax = sys_days{year::max()/12/last}; constexpr auto dmin = sys_time<D>::min(); constexpr auto dmax = sys_time<D>::max(); cout << left << setw(24) << msg << " : ["; if (ymin > dsecs{dmin}) cout << ymin; else cout << dmin; cout << ", "; if (ymax < dsecs{dmax}) cout << ymax; else cout << dmax; cout << "]\n"; }
The best way to explore limits without risking overflow during the comparison operation
itself is to use double
-based seconds
for the comparison. By
using seconds
you guarantee that the conversion to the comparison type
won't overflow the compile-time machinery of finding the common_type
of the
duration
s, and by using double
you make overflow or underflow
nearly impossible. The use of double
sacrifices precision, but this is
rarely needed for limits comparisons as the two operands of the comparison are typically
orders of magnitude apart.
So the code above creates a sys_time<double>
time_point
with which to perform the comparisons. Then it finds the min and max of both the
year_month_day
object, and the duration D
. It then prints
out the intersection of these two ranges.
This code can be exercised like so:
void limits() { using namespace std::chrono; using namespace std; using picoseconds = duration<int64_t, pico>; using fs = duration<int64_t, ratio_multiply<ratio<100>, nano>>; limit<picoseconds>("picoseconds range is"); limit<nanoseconds>("nanoseconds range is"); limit<fs>("VS system_clock range is"); limit<microseconds>("microseconds range is"); limit<milliseconds>("milliseconds range is"); limit<seconds>("seconds range is"); limit<minutes>("minutes range is"); limit<hours>("hours range is"); }
I've included two extra units: picoseconds
, and the units used by Visual
Studio's system_clock::time_point
. Units finer than picoseconds
do not work with this date library because the conversion factors needed to convert to
units such as days
overflow the compile-time machinery. As a practical
matter this is not important as the range of a 64 bit femtosecond is only about +/- 2.5
hours. On the other side, units coarser than hours
, if represented by at
least 32 bits, will always have a range far greater than a 16 bit year
.
The output of this function on Visual Studio, and on clang using libc++ with
-arch i386
is:
picoseconds range is : [1969-09-16 05:57:07.963145224192, 1970-04-17 18:02:52.036854775807] nanoseconds range is : [1677-09-21 00:12:43.145224192, 2262-04-11 23:47:16.854775807] VS system_clock range is : [-27258-04-19 21:11:54.5224192, 31197-09-14 02:48:05.4775807] microseconds range is : [-32768-01-01, 32767-12-31] milliseconds range is : [-32768-01-01, 32767-12-31] seconds range is : [-32768-01-01, 32767-12-31] minutes range is : [-2114-12-08 21:52, 6053-01-23 02:07] hours range is : [-32768-01-01, 32767-12-31]
Using gcc or clang/libc++ with -arch x86_64
the output is:
picoseconds range is : [1969-09-16 05:57:07.963145224192, 1970-04-17 18:02:52.036854775807] nanoseconds range is : [1677-09-21 00:12:43.145224192, 2262-04-11 23:47:16.854775807] VS system_clock range is : [-27258-04-19 21:11:54.5224192, 31197-09-14 02:48:05.4775807] microseconds range is : [-32768-01-01, 32767-12-31] milliseconds range is : [-32768-01-01, 32767-12-31] seconds range is : [-32768-01-01, 32767-12-31] minutes range is : [-32768-01-01, 32767-12-31] hours range is : [-32768-01-01, 32767-12-31]
The only difference between these two outputs is that associated with
minutes
. When minutes
is represented with 32 bits the range is
only about +/- 4000 years from 1970. When minutes
is represented with 64
bits, the limits of the 16 bit year takes precedence.
The take-away point here is two-fold:
If you need to check range, do the check using duration<double>
to
ensure your comparison is not itself vulnerable to overflow.
If you are dealing units finer than microseconds
, you may well
accidentally experience overflow in surprisingly mundane-looking code. When
dealing with dates that may be hundreds of years away from 1970, keep an eye on
the precision. And in a surprise move, 32 bit minutes
can bite if
you are several thousand years away from 1970.
Finally note that the civil calendar itself models the rotation and orbit of the
earth with an accuracy of only one day in several thousand years. So dates more
than several thousand years in the past or future (with a precision of a single
day) are of limited practical use with or without numerical overflow. The chief
motivation for having large ranges of date computation before overflow happens
is to make range checking superflous for most reasonable computations. If you
need to handle ranges dealing with geological or astrophysical phenomenon,
<chrono>
can handle it (attoseconds
to
exaseconds
), but year_month_day
is the wrong tool for
such extremes.
Here is a detailed specification of the entire library. This specification is detailed enough that you could write your own implementation from it if desired. But feel free to use this one instead. Each type, and each operation is simple and predictable.
Everything here is contained in the namespace date
. The literal operators,
and the constexpr field literals (e.g. Sunday
, January
, etc.) are
in namespace date::literals
and imported into namespace date
.
days
days
is astd::chrono::duration
with a tick period of 24 hours. This definition is not an SI unit but is accepted for use with SI.days
is the resultant type when subtracting twosys_days
s.using days = std::chrono::duration <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
weeks
weeks
is astd::chrono::duration
with a tick period of 7 days. This definition is widely recognized and predates the Gregorian calendar. It is consistent with ISO 8601.weeks
will implicitly convert todays
but not vice-versa.using weeks = std::chrono::duration <int, std::ratio_multiply<std::ratio<7>, days::period>>;
years
years
is astd::chrono::duration
with a tick period of 365.2425 days. This definition accurately describes the length of the average year in the Gregorian calendar.years
is the resultant type when subtracting twoyear
field-based time points.years
is not implicitly convertible todays
orweeks
nor vice-versa. Howeveryears
will implicitly convert tomonths
.using years = std::chrono::duration <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;
months
months
is astd::chrono::duration
with a tick period of 1/12 of a year. This definition accurately describes the length of the average month in the Gregorian calendar.months
is the resultant type when subtracting twomonth
field-based time points.months
is not implicitly convertible todays
orweeks
nor vice-versa.months
will not implicitly convert toyears
.using months = std::chrono::duration <int, std::ratio_divide<years::period, std::ratio<12>>>;
template <class CharT, class Traits, class Rep, class Period> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const std::chrono::duration<Rep, Period>& d);
Effects: Inserts
d
, converted to thecommon_type<duration, seconds>
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%H
,%I
,%M
,%p
,%r
,%R
,%S
,%T
,%X
,%n
,%t
or%%
.Returns:
os
.
template <class Rep, class Period, class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, std::chrono::duration<Rep, Period>& d, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);
Effects: Extracts
d
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%H
,%I
,%M
,%p
,%r
,%R
,%S
,%T
,%X
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andd
will not be altered.Returns:
is
.
template <class CharT, class Traits, class Rep, class Period> std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const std::chrono::duration<Rep, Period>& d);
Effects: Equivalent to:
os << to_string<CharT, Traits>(d.count()) + detail::get_units<CharT>(duration<Rep, typename Period::type>{});Where
to_string
is pseudo code that returns astd::basic_string<CharT, Traits>
representation ofd.count()
, anddetail::get_units<CharT>()
returns a null-terminated string ofCharT
which depends only onPeriod::type
as follows (letperiod
be the typePeriod::type
):
- If
period
is typestd::atto
,as
, else- if
period
is typestd::femto
,fs
, else- if
period
is typestd::pico
,ps
, else- if
period
is typestd::nano
,ns
, else- if
period
is typestd::micro
,µs
(U+00B5), else- if
period
is typestd::milli
,ms
, else- if
period
is typestd::centi
,cs
, else- if
period
is typestd::deci
,ds
, else- if
period
is typestd::ratio<1>
,s
, else- if
period
is typestd::deca
,das
, else- if
period
is typestd::hecto
,hs
, else- if
period
is typestd::kilo
,ks
, else- if
period
is typestd::mega
,Ms
, else- if
period
is typestd::giga
,Gs
, else- if
period
is typestd::tera
,Ts
, else- if
period
is typestd::peta
,Ps
, else- if
period
is typestd::exa
,Es
, else- if
period
is typestd::ratio<60>
,min
, else- if
period
is typestd::ratio<3600>
,h
, else- if
period::den == 1
,[num]s
, else[num/den]s
.In the list above the use of
num
andden
refer to the static data members ofperiod
which are converted to arrays ofCharT
using a decimal conversion with no leading zeroes.Returns:
os
.
sys_time
sys_time
is a convenience template alias for creating asystem_clock::time_point
but of arbitrary precision. This family of types represents "system time", which closely models UTC. Seeutc_time
in tz.h for a variation ofsys_time
that accurately takes leap seconds into account when subtractingtime_point
s.template <class Duration> using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
sys_days
sys_days
is astd::chrono::time_point
usingstd::chrono::system_clock
anddays
. This makessys_days
interoperable withstd::chrono::system_clock::time_point
. It is simply a count of days since the epoch ofstd::chrono::system_clock
which in every implementation is Jan. 1, 1970.sys_days
is a serial-based time point with a resolution ofdays
.using sys_days = sys_time<days>;
sys_seconds
sys_seconds
is astd::chrono::time_point
usingstd::chrono::system_clock
andstd::chrono::seconds
. This makessys_seconds
interoperable withstd::chrono::system_clock::time_point
. It is simply a count of non-leap seconds since the epoch ofstd::chrono::system_clock
which in every implementation is Jan. 1, 1970 00:00:00 UTC.sys_seconds
is a serial-based time point with a resolution ofseconds
.sys_seconds
is also widely known as Unix Time.using sys_seconds = sys_time<std::chrono::seconds>;
template <class CharT, class Traits, class Duration> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const sys_time<Duration>& tp);
Effects: Inserts
tp
, converted to thecommon_type<Duration, seconds>
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. If%Z
is in the formatting string"UTC"
will be used. If%z
is in the formatting string"+0000"
will be used.Returns:
os
.
template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, sys_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);
Effects: Extracts
tp
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. If%z
is present, the parsed offset will be subtracted from the parsed time. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andtp
will not be altered.Returns:
is
.
local_time
local_time
is a convenience template alias for creating atime_point
of arbitrary precision which is not based on any clock at all. This family of types represents a time not associated with any time zone. It is handy in disambiguating calendar timestamps referring to an unspecified timezone, and those referring to UTC.For example, we can say that the upcoming 2017 New Years will be commonly celebrated at
local_time<days>{2017_y/January/1} + 0s
. For those in a time zone with a zero offset from UTC, it will be celebrated at the concrete time ofsys_days{2017_y/January/1} + 0s
. These two timestamps have different types, though both have the exact same representation (a count of seconds), because they mean two subtly different things, and are both quite useful.struct local_t {}; template <class Duration> using local_time = std::chrono::time_point<local_t, Duration>;
local_days
local_days
is a convient way to writelocal_time<days>
. The upcoming 2017 New Years will be commonly celebrated atlocal_days{2017_y/January/1} + 0s
.using local_days = local_time<days>;
local_seconds
local_seconds
is a convient way to writelocal_time<seconds>
.using local_seconds = local_time<std::chrono::seconds>;
template <class CharT, class Traits, class Duration> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const local_time<Duration>& tp, const std::string* abbrev = nullptr, const std::chrono::seconds* offset_sec = nullptr);
Effects: Inserts
tp
, converted to thecommon_type<Duration, seconds>
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. If%Z
is in the formatting string*abbrev
will be used. If%z
is in the formatting string*offset_sec
will be used.If
%Z
is in the formatting string andabbrev == nullptr
, or if%z
is in the formatting string andoffset_sec == nullptr
,failbit
will be set foros
.Returns:
os
.
template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, local_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);
Effects: Extracts
tp
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andtp
will not be altered.Returns:
is
.
last_spec
last_spec
is astruct
that isCopyConstructible
. There exists aconstexpr
instance oflast_spec
namedlast
. This is simply a tag type. It is used to indicate the last day of a month, or the last weekday of a month.struct last_spec { explicit last_spec() = default; }; inline namespace literals { constexpr last_spec last{}; }
day
Synopsis
class day { unsigned char d_; // exposition only public: day() = default; explicit constexpr day(unsigned d) noexcept; constexpr day& operator++() noexcept; constexpr day operator++(int) noexcept; constexpr day& operator--() noexcept; constexpr day operator--(int) noexcept; constexpr day& operator+=(const days& d) noexcept; constexpr day& operator-=(const days& d) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const day& x, const day& y) noexcept; constexpr bool operator!=(const day& x, const day& y) noexcept; constexpr bool operator< (const day& x, const day& y) noexcept; constexpr bool operator> (const day& x, const day& y) noexcept; constexpr bool operator<=(const day& x, const day& y) noexcept; constexpr bool operator>=(const day& x, const day& y) noexcept; constexpr day operator+(const day& x, const days& y) noexcept; constexpr day operator+(const days& x, const day& y) noexcept; constexpr day operator-(const day& x, const days& y) noexcept; constexpr days operator-(const day& x, const day& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const day& d); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const day& d); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, day& d, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr); inline namespace literals { constexpr day operator "" _d(unsigned long long d) noexcept; }Overview
day
represents a day of a month. It should only be representing values in the range 1 to 31. However it may hold values outside this range. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intoday
's internal storage.day
is equality and less-than comparable, and participates in basic arithmetic withdays
representing the quantity between any twoday
's. One can form aday
literal with_d
. And one can stream out aday
for debugging purposes.day
has explicit conversions to and fromunsigned
.Specification
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
. The value held is unspecified ifd
is not in the range[0, 255]
.constexpr day& day::operator++() noexcept;Effects:
++d_
.Returns:
*this
.constexpr day day::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr day& day::operator--() noexcept;Effects:
--d_
.Returns:
*this
.constexpr day day::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr day& day::operator+=(const days& d) noexcept;Effects:
*this = *this + d
.Returns:
*this
.constexpr day& day::operator-=(const days& d) noexcept;Effects:
*this = *this - d
.Returns:
*this
.constexpr explicit day::operator unsigned() const noexcept;Returns:
d_
.constexpr bool day::ok() const noexcept;Returns:
1 <= d_ && d_ <= 31
.constexpr bool operator==(const day& x, const day& y) noexcept;Returns:
unsigned{x} == unsigned{y}
.constexpr bool operator!=(const day& x, const day& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const day& x, const day& y) noexcept;Returns:
unsigned{x} < unsigned{y}
.constexpr bool operator> (const day& x, const day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const day& x, const day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const day& x, const day& y) noexcept;Returns:
!(x < y)
.constexpr day operator+(const day& x, const days& y) noexcept;Returns:
day{unsigned{x} + y.count()}
.constexpr day operator+(const days& x, const day& y) noexcept;Returns:
y + x
.constexpr day operator-(const day& x, const days& y) noexcept;Returns:
x + -y
.constexpr days operator-(const day& x, const day& y) noexcept;Returns:
days{static_cast<days::rep>(unsigned{x} - unsigned{y})}
.constexpr day operator "" _d(unsigned long long d) noexcept;Returns:
day{static_cast<unsigned>(d)}
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const day& d);Effects: Inserts a decimal integral text representation of
d
intoos
. Single digit values are prefixed with'0'
.Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const day& d);Effects: Inserts
d
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%d
,%e
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, day& d, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
d
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%e
,%e
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andd
will not be altered. In particular!d.ok()
is not an indication of error.Returns:
is
.
month
Synopsis
class month { unsigned char m_; // exposition only public: month() = default; explicit constexpr month(unsigned m) noexcept; constexpr month& operator++() noexcept; constexpr month operator++(int) noexcept; constexpr month& operator--() noexcept; constexpr month operator--(int) noexcept; constexpr month& operator+=(const months& m) noexcept; constexpr month& operator-=(const months& m) noexcept; constexpr explicit operator unsigned() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month& x, const month& y) noexcept; constexpr bool operator!=(const month& x, const month& y) noexcept; constexpr bool operator< (const month& x, const month& y) noexcept; constexpr bool operator> (const month& x, const month& y) noexcept; constexpr bool operator<=(const month& x, const month& y) noexcept; constexpr bool operator>=(const month& x, const month& y) noexcept; constexpr month operator+(const month& x, const months& y) noexcept; constexpr month operator+(const months& x, const month& y) noexcept; constexpr month operator-(const month& x, const months& y) noexcept; constexpr months operator-(const month& x, const month& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month& m); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const month& m); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month& m, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr); inline namespace literals { constexpr month January{1}; constexpr month February{2}; constexpr month March{3}; constexpr month April{4}; constexpr month May{5}; constexpr month June{6}; constexpr month July{7}; constexpr month August{8}; constexpr month September{9}; constexpr month October{10}; constexpr month November{11}; constexpr month December{12}; }Overview
month
represents a month of a year. It should only be representing values in the range 1 to 12. However it may hold values outside this range. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intomonth
's internal storage.month
is equality and less-than comparable, and participates in basic arithmetic withmonths
representing the quantity between any twomonth
's. One can stream out amonth
for debugging purposes.month
has explicit conversions to and fromunsigned
. There are 12month
constants, one for each month of the year.Specification
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
. The value held is unspecified ifm
is not in the range[0, 255]
.constexpr month& month::operator++() noexcept;Effects: If
m_ != 12
,++m_
. Otherwise setsm_
to 1.Returns:
*this
.constexpr month month::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr month& month::operator--() noexcept;Effects: If
m_ != 1
,--m_
. Otherwise setsm_
to 12.Returns:
*this
.constexpr month month::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr month& month::operator+=(const months& m) noexcept;Effects:
*this = *this + m
.Returns:
*this
.constexpr month& month::operator-=(const months& m) noexcept;Effects:
*this = *this - m
.Returns:
*this
.constexpr explicit month::operator unsigned() const noexcept;Returns:
m_
.constexpr bool month::ok() const noexcept;Returns:
1 <= m_ && m_ <= 12
.constexpr bool operator==(const month& x, const month& y) noexcept;Returns:
unsigned{x} == unsigned{y}
.constexpr bool operator!=(const month& x, const month& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const month& x, const month& y) noexcept;Returns:
unsigned{x} < unsigned{y}
.constexpr bool operator> (const month& x, const month& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month& x, const month& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month& x, const month& y) noexcept;Returns:
!(x < y)
.constexpr month operator+(const month& x, const months& y) noexcept;Returns: A
month
for whichok() == true
and is found as if by incrementing (or decrementing ify < months{0}
)x
,y
times. Ifmonth.ok() == false
prior to this operation, behaves as if*this
is first brought into the range [1, 12] by modular arithmetic. [Note: For examplemonth{0}
becomesmonth{12}
, andmonth{13}
becomesmonth{1}
. — end note]Complexity: O(1) with respect to the value of
y
. That is, repeated increments or decrements is not a valid implementation.Example:
February + months{11} == January
.constexpr month operator+(const months& x, const month& y) noexcept;Returns:
y + x
.constexpr month operator-(const month& x, const months& y) noexcept;Returns:
x + -y
.constexpr months operator-(const month& x, const month& y) noexcept;Returns: If
x.ok() == true
andy.ok() == true
, returns a value ofmonths
in the range ofmonths{0}
tomonths{11}
inclusive. Otherwise the value returned is unspecified.Remarks: If
x.ok() == true
andy.ok() == true
, the returned valuem
shall satisfy the equality:y + m == x
.Example:
January - February == months{11}
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month& m);Effects: If
ok() == true
outputs the same string that would be output for the month field byasctime
. Otherwise outputsunsigned{m} << " is not a valid month"
.Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const month& m);Effects: Inserts
m
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%h
,%m
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month& m, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
m
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%h
,%m
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andy
will not be altered. In particular!m.ok()
is not an indication of error.Returns:
is
.
year
Synopsis
class year { short y_; // exposition only public: year() = default; explicit constexpr year(int y) noexcept; constexpr year& operator++() noexcept; constexpr year operator++(int) noexcept; constexpr year& operator--() noexcept; constexpr year operator--(int) noexcept; constexpr year& operator+=(const years& y) noexcept; constexpr year& operator-=(const years& y) noexcept; constexpr year operator-() const noexcept; constexpr year operator+() const noexcept; constexpr bool is_leap() const noexcept; constexpr explicit operator int() const noexcept; constexpr bool ok() const noexcept; static constexpr year min() noexcept; static constexpr year max() noexcept; }; constexpr bool operator==(const year& x, const year& y) noexcept; constexpr bool operator!=(const year& x, const year& y) noexcept; constexpr bool operator< (const year& x, const year& y) noexcept; constexpr bool operator> (const year& x, const year& y) noexcept; constexpr bool operator<=(const year& x, const year& y) noexcept; constexpr bool operator>=(const year& x, const year& y) noexcept; constexpr year operator+(const year& x, const years& y) noexcept; constexpr year operator+(const years& x, const year& y) noexcept; constexpr year operator-(const year& x, const years& y) noexcept; constexpr years operator-(const year& x, const year& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year& y); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year& y); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year& y, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr); inline namespace literals { constexpr year operator "" _y(unsigned long long y) noexcept; }Overview
year
represents a year in the Gregorian calendar. It shall represent values in the range[min(), max()]
. It can be constructed with anyint
value, which will be subsequently truncated to fit intoyear
's internal storage. Theyear
prior toyear{1}
isyear{0}
, and is a leap year. Theyear
prior toyear{0}
isyear{-1}
. This is commonly referred to as the proleptic Gregorian calendar.year
is equality and less-than comparable, and participates in basic arithmetic withyears
representing the quantity between any twoyear
's. One can form ayear
literal with_y
. And one can stream out ayear
for debugging purposes.year
has explicit conversions to and fromint
.Specification
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
. The value held is unspecified ify
is not in the range[-32767, 32767]
.constexpr year& year::operator++() noexcept;Effects:
++y_
.Returns:
*this
.constexpr year year::operator++(int) noexcept;Effects:
++(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr year& year::operator--() noexcept;Effects:
--y_
.Returns:
*this
.constexpr year year::operator--(int) noexcept;Effects:
--(*this)
.Returns: A copy of
*this
as it existed on entry to this member function.constexpr year& year::operator+=(const years& y) noexcept;Effects:
*this = *this + y
.Returns:
*this
.constexpr year& year::operator-=(const years& y) noexcept;Effects:
*this = *this - y
.Returns:
*this
.constepxr year year::operator-() const noexcept;Returns:
year{-y_}
.constepxr year year::operator+() const noexcept;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{-32767}
.static constexpr year year::max() noexcept;Returns:
year{32767}
.constexpr bool operator==(const year& x, const year& y) noexcept;Returns:
int{x} == int{y}
.constexpr bool operator!=(const year& x, const year& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year& x, const year& y) noexcept;Returns:
int{x} < int{y}
.constexpr bool operator> (const year& x, const year& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year& x, const year& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year& x, const year& y) noexcept;Returns:
!(x < y)
.constexpr year operator+(const year& x, const years& y) noexcept;Returns:
year{int{x} + y.count()}
.constexpr year operator+(const years& x, const year& y) noexcept;Returns:
y + x
.constexpr year operator-(const year& x, const years& y) noexcept;Returns:
x + -y
.constexpr years operator-(const year& x, const year& y) noexcept;Returns:
years{int{x} - int{y}}
.constexpr year operator "" _y(unsigned long long y) noexcept;Returns:
year{static_cast<int>(y)}
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& 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
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year& y);Effects: Inserts
y
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%C
,%y
,%Y
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year& y, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
y
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%C
,%y
,%Y
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andy
will not be altered. In particular!y.ok()
is not an indication of error.Returns:
is
.
weekday
Synopsis
class weekday { unsigned char wd_; // exposition only public: weekday() = default; explicit constexpr weekday(unsigned wd) noexcept; constexpr weekday(const sys_days& dp) noexcept; constexpr explicit weekday(const local_days& dp) noexcept; constexpr weekday& operator++() noexcept; constexpr weekday operator++(int) noexcept; constexpr weekday& operator--() noexcept; constexpr weekday operator--(int) noexcept; constexpr weekday& operator+=(const days& d) noexcept; constexpr weekday& operator-=(const days& d) noexcept; constexpr unsigned c_encoding() const noexcept; constexpr unsigned iso_encoding() const noexcept; constexpr bool ok() const noexcept; constexpr weekday_indexed operator[](unsigned index) const noexcept; constexpr weekday_last operator[](last_spec) const noexcept; }; constexpr bool operator==(const weekday& x, const weekday& y) noexcept; constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; constexpr weekday operator+(const weekday& x, const days& y) noexcept; constexpr weekday operator+(const days& x, const weekday& y) noexcept; constexpr weekday operator-(const weekday& x, const days& y) noexcept; constexpr days operator-(const weekday& x, const weekday& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday& wd); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const weekday& wd); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, weekday& wd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr); constexpr weekday Monday{1}; constexpr weekday Tuesday{2}; constexpr weekday Wednesday{3}; constexpr weekday Thursday{4}; constexpr weekday Friday{5}; constexpr weekday Saturday{6}; constexpr weekday Sunday{7};Overview
weekday
represents a day of the week in the Gregorian calendar. It can be constructed with anyunsigned
value, which will be subsequently truncated to fit intoweekday
's internal storage. The values [1, 6] map to Monday thru Saturday. Both 0 and 7 map to Sunday. Other values in the range [8, 255] will be stored, and will represent values ofweekday
that are!ok()
.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.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 aweekday
for debugging purposes.weekday
has explicit conversions to and fromunsigned
. There are 7weekday
constants, one for each day of the week.A
weekday
can be implicitly constructed from asys_days
. This is the computation that discovers the day of the week of an arbitrary date.A
weekday
can be indexed with eitherunsigned
orlast
. This produces new types which represent the first, second, third, fourth, fifth or last weekdays of a month.Specification
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
which represents a day of the week according to the ISO 8601 mapping of integers to days of the week. Additionally, ifwd == 0
, Sunday is represented. [Note: Sunday can be constructed from both 0 and 7 — end note]. Ifwd
is in the range [8, 255],wd_
is initialized with wd. If wd is not in the range [0, 255], the value held is unspecified.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 unsigned c_encoding() const noexcept;Returns:
wd_
.constexpr unsigned iso_encoding() const noexcept;Returns:
wd_ == 0u ? 7u : wd_
.constexpr bool weekday::ok() const noexcept;Returns:
true
if*this
holds a value in the range Monday thru Sunday, else returnsfalse
.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:
x.wd_ == y.wd_
.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:
Monday + days{6} == Sunday
.constexpr weekday operator+(const days& x, const weekday& y) noexcept;Returns:
y + x
.constexpr weekday operator-(const weekday& x, const days& y) noexcept;Returns:
x + -y
.constexpr days operator-(const weekday& x, const weekday& y) noexcept;Returns: If
x.ok() == true
andy.ok() == true
, returns a value ofdays
in the range ofdays{0}
todays{6}
inclusive. Otherwise the value returned is unspecified.Remarks: If
x.ok() == true
andy.ok() == true
, the returned valued
shall satisfy the equality:y + d == x
.Example:
Sunday - Monday == days{6}
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday& wd);Effects: If
ok() == true
outputs the same string that would be output for the weekday field byasctime
. Otherwise outputsunsigned{wd} << " is not a valid weekday"
.Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const weekday& wd);Effects: Inserts
wd
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%a
,%A
,%u
,%w
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, weekday& wd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
wd
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%a
,%A
,%u
,%w
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andwd
will not be altered. In particular!wd.ok()
is not an indication of error.Returns:
is
.
weekday_indexed
Synopsis
class weekday_indexed { date::weekday wd_; // exposition only unsigned char index_; // exposition only public: constexpr weekday_indexed(const date::weekday& wd, unsigned index) noexcept; constexpr date::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday_indexed& wdi);Overview
weekday_indexed
represents aweekday
and a small index in the range 1 to 5. This class is used to represent the first, second, third, fourth or fifth weekday of a month. It is most easily constructed by indexing aweekday
.[Example:
constexpr auto wdi = Sunday[2]; // wdi is the second Sunday of an as yet unspecified month static_assert(wdi.weekday() == Sunday); static_assert(wdi.index() == 2);— end example:]
Specification
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 date::weekday& wd, unsigned index) noexcept;Effects: Constructs an object of type
weekday_indexed
by constructingwd_
withwd
andindex_
withindex
. The values held are unspecified if!wd.ok()
orindex
is not in the range[1, 5]
.constexpr weekday weekday_indexed::weekday() const noexcept;Returns:
wd_
.constexpr unsigned weekday_indexed::index() const noexcept;Returns:
index_
.constexpr bool weekday_indexed::ok() const noexcept;Returns:
wd_.ok() && 1 <= index_ && index_ <= 5
.constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept;Returns:
x.weekday() == y.weekday() && x.index() == y.index()
.constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept;Returns:
!(x == y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday_indexed& wdi);Effects: Inserts
os << wdi.weekday() << '[' << wdi.index() << ']'
.Returns:
os
.
weekday_last
Synopsis
class weekday_last { date::weekday wd_; // exposition only public: explicit constexpr weekday_last(const date::weekday& wd) noexcept; constexpr date::weekday weekday() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday_last& wdl);Overview
weekday_last
represents the lastweekday
of a month. It is most easily constructed by indexing aweekday
withlast
.[Example:
constexpr auto wdl = Sunday[last]; // wdl is the last Sunday of an as yet unspecified month static_assert(wdl.weekday() == Sunday);— end example:]
Specification
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 date::weekday& wd) noexcept;Effects: Constructs an object of type
weekday_last
by constructingwd_
withwd
.constexpr weekday weekday_last::weekday() const noexcept;Returns:
wd_
.constexpr bool weekday_last::ok() const noexcept;Returns:
wd_.ok()
.constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept;Returns:
x.weekday() == y.weekday()
.constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept;Returns:
!(x == y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday_last& wdl);Effects: Inserts
os << wdi.weekday() << "[last]"
.Returns:
os
.
month_day
Synopsis
class month_day { date::month m_; // exposition only date::day d_; // exposition only public: month_day() = default; constexpr month_day(const date::month& m, const date::day& d) noexcept; constexpr date::month month() const noexcept; constexpr date::day day() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; constexpr bool operator!=(const month_day& x, const month_day& y) noexcept; constexpr bool operator< (const month_day& x, const month_day& y) noexcept; constexpr bool operator> (const month_day& x, const month_day& y) noexcept; constexpr bool operator<=(const month_day& x, const month_day& y) noexcept; constexpr bool operator>=(const month_day& x, const month_day& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_day& md); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const month_day& md); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month_day& md, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Overview
month_day
represents a specificday
of a specificmonth
, but with an unspecifiedyear
. One can observe the different components. One can assign a new value.month_day
is equality comparable and less-than comparable. One can stream out amonth_day
for debugging purposes.Specification
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 date::month& m, const date::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 if1_d <= d_
, and ifd_ <=
the number of days in monthm_
. Form_ == February
the number of days is considered to be 29. Otherwise returnsfalse
.constexpr bool operator==(const month_day& x, const month_day& y) noexcept;Returns:
x.month() == y.month() && x.day() == y.day()
constexpr bool operator!=(const month_day& x, const month_day& y) noexcept;Returns:
!(x == y)
constexpr bool operator< (const month_day& x, const month_day& y) noexcept;Returns: If
x.month() < y.month()
returnstrue
. Else ifx.month() > y.month()
returnsfalse
. Else returnsx.day() < y.day()
.constexpr bool operator> (const month_day& x, const month_day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month_day& x, const month_day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month_day& x, const month_day& y) noexcept;Returns:
!(x < y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_day& md);Effects: Inserts
os << md.month() << '/' << md.day()
.Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const month_day& md);Effects: Inserts
md
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%d
,%e
,%h
,%m
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month_day& md, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
md
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%d
,%e
,%h
,%m
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andmd
will not be altered. In particular!md.ok()
is not an indication of error.Returns:
is
.
month_day_last
Synopsis
class month_day_last { date::month m_; // exposition only public: constexpr explicit month_day_last(const date::month& m) noexcept; constexpr date::month month() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept; constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_day_last& mdl);Overview
month_day_last
represents the lastday
of amonth
. It is most easily constructed using the expressionm/last
orlast/m
, wherem
is an expression with typemonth
.[Example:
constexpr auto mdl = February/last; // mdl is the last day of February of an as yet unspecified year static_assert(mdl.month() == February);— end example:]
Specification
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 date::month& m) noexcept;Effects: Constructs an object of type
month_day_last
by constructingm_
withm
.constexpr month month_day_last::month() const noexcept;Returns:
m_
.constexpr bool month_day_last::ok() const noexcept;Returns:
m_.ok()
.constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept;Returns:
x.month() == y.month()
.constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(x == y)
constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept;Returns:
x.month() < y.month()
.constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept;Returns:
!(x < y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_day_last& mdl);Effects: Inserts
os << mdl.month() << "/last"
.Returns:
os
.
month_weekday
Synopsis
class month_weekday { date::month m_; // exposition only date::weekday_indexed wdi_; // exposition only public: constexpr month_weekday(const date::month& m, const date::weekday_indexed& wdi) noexcept; constexpr date::month month() const noexcept; constexpr date::weekday_indexed weekday_indexed() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_weekday& mwd);Overview
month_weekday
represents the nthweekday
of amonth
, of an as yet unspecifiedyear
. To do this themonth_weekday
stores amonth
and aweekday_indexed
.Specification
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 date::month& m, const date::weekday_indexed& wdi) noexcept;Effects: Constructs an object of type
month_weekday
by constructingm_
withm
, andwdi_
withwdi
.constexpr month month_weekday::month() const noexcept;Returns:
m_
.constexpr weekday_indexed month_weekday::weekday_indexed() const noexcept;Returns:
wdi_
.constexpr bool month_weekday::ok() const noexcept;Returns:
m_.ok() && wdi_.ok()
.constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept;Returns:
x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed()
.constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept;Returns:
!(x == y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_weekday& mwd);Effects: Inserts
os << mwd.month() << '/' << mwd.weekday_indexed()
.Returns:
os
.
month_weekday_last
Synopsis
class month_weekday_last { date::month m_; // exposition only date::weekday_last wdl_; // exposition only public: constexpr month_weekday_last(const date::month& m, const date::weekday_last& wdl) noexcept; constexpr date::month month() const noexcept; constexpr date::weekday_last weekday_last() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_weekday_last& mwdl);Overview
month_weekday_last
represents the lastweekday
of amonth
, of an as yet unspecifiedyear
. To do this themonth_weekday_last
stores amonth
and aweekday_last
.Specification
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 date::month& m, const date::weekday_last& wdl) noexcept;Effects: Constructs an object of type
month_weekday_last
by constructingm_
withm
, andwdl_
withwdl
.constexpr month month_weekday_last::month() const noexcept;Returns:
m_
.constexpr weekday_last month_weekday_last::weekday_last() const noexcept;Returns:
wdl_
.constexpr bool month_weekday_last::ok() const noexcept;Returns:
m_.ok() && wdl_.ok()
.constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept;Returns:
x.month() == y.month() && x.weekday_last() == y.weekday_last()
.constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept;Returns:
!(x == y)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const month_weekday_last& mwdl);Effects: Inserts
os << mwdl.month() << '/' << mwdl.weekday_last()
.Returns:
os
.
year_month
Synopsis
class year_month { date::year y_; // exposition only date::month m_; // exposition only public: year_month() = default; constexpr year_month(const date::year& y, const date::month& m) noexcept; constexpr date::year year() const noexcept; constexpr date::month month() const noexcept; constexpr year_month& operator+=(const months& dm) noexcept; constexpr year_month& operator-=(const months& dm) noexcept; constexpr year_month& operator+=(const years& dy) noexcept; constexpr year_month& operator-=(const years& dy) noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month& x, const year_month& y) noexcept; constexpr bool operator!=(const year_month& x, const year_month& y) noexcept; constexpr bool operator< (const year_month& x, const year_month& y) noexcept; constexpr bool operator> (const year_month& x, const year_month& y) noexcept; constexpr bool operator<=(const year_month& x, const year_month& y) noexcept; constexpr bool operator>=(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; constexpr months operator-(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month& ym); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year_month& ym); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month& ym, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Overview
year_month
represents a specificmonth
of a specificyear
, but with an unspecifiedday
.year_month
is a field-based time point with a resolution ofmonths
. One can observe the different components. One can assign a new value.year_month
is equality comparable and less-than comparable. One can stream out ayear_month
for debugging purposes.Specification
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 date::year& y, const date::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
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month& ym);Effects: Inserts
os << ym.year() << '/' << ym.month()
.Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year_month& ym);Effects: Inserts
ym
intoos
using the format stringfmt
as specified by theto_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%C
,%h
,%m
,%y
,%Y
,%n
,%t
or%%
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month& ym, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
ym
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. The behavior is undefined except for the following flags (or modified versions of these flags):%b
,%B
,%C
,%h
,%m
,%y
,%Y
,%n
,%t
,%z
,%Z
or%%
. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andym
will not be altered. In particular!ym.ok()
is not an indication of error.Returns:
is
.
year_month_day
Synopsis
class year_month_day { date::year y_; // exposition only date::month m_; // exposition only date::day d_; // exposition only public: year_month_day() = default; constexpr year_month_day(const date::year& y, const date::month& m, const date::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 date::year year() const noexcept; constexpr date::month month() const noexcept; constexpr date::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept; constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_day& ymd); template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year_month_day& ymd); template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month_day& ymd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Overview
year_month_day
represents a specificyear
,month
, andday
.year_month_day
is a field-based time point with a resolution ofdays
. One can observe each field.year_month_day
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic. There is also a conversion fromsys_days
.year_month_day
is equality and less-than comparable.Specification
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 date::year& y, const date::month& m, const date::day& d) noexcept;Effects: Constructs an object of type
year_month_day
by constructingy_
withy
,m_
withm
, and,d_
withd
.constexpr year_month_day::year_month_day(const year_month_day_last& ymdl) noexcept;Effects: Constructs an object of type
year_month_day
by constructingy_
withymdl.year()
,m_
withymdl.month()
, and,d_
withymdl.day()
.Note: This conversion from
year_month_day_last
toyear_month_day
is more efficient than converting ayear_month_day_last
to asys_days
, and then converting thatsys_days
to ayear_month_day
.constexpr year_month_day::year_month_day(const sys_days& dp) noexcept;Effects: Constructs an object of type
year_month_day
which corresponds to the date represented bydp
.Remarks: For any value of
year_month_day
,ymd
, for whichymd.ok()
istrue
, this equality will also betrue
:ymd == year_month_day{sys_days{ymd}}
.constexpr explicit year_month_day::year_month_day(const local_days& dp) noexcept;Effects: Constructs an object of type
year_month_day
which corresponds to the date represented bydp
.Remarks: Equivalent to constructing with
sys_days{dp.time_since_epoch()}
.constexpr year_month_day& year_month_day::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_day& year_month_day::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_day::year() const noexcept;Returns:
y_
.constexpr month year_month_day::month() const noexcept;Returns:
m_
.constexpr day year_month_day::day() const noexcept;Returns:
d_
.constexpr year_month_day::operator sys_days() const noexcept;Returns: If
ok()
, returns asys_days
holding a count ofdays
from thesys_days
epoch to*this
(a negative value if*this
represents a date prior to thesys_days
epoch). Otherwise ify_.ok() && m_.ok() == true
returns asys_days
which is offset fromsys_days{y_/m_/last}
by the number ofdays
d_
is offset fromsys_days{y_/m_/last}.day()
. Otherwise the value returned is unspecified.Remarks: A
sys_days
in the range[days{-12687428}, days{11248737}]
which is converted to ayear_month_day
, shall have the same value when converted back to asys_days
.[Example:
static_assert(year_month_day{sys_days{2017y/January/0}} == 2016y/December/31); static_assert(year_month_day{sys_days{2017y/January/31}} == 2017y/January/31); static_assert(year_month_day{sys_days{2017y/January/32}} == 2017y/February/1);—end example]
constexpr explicit year_month_day::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};constexpr bool year_month_day::ok() const noexcept;Returns: If
y_.ok()
istrue
, andm_.ok()
istrue
, andd_
is in the range[1_d, (y_/m_/last).day()]
, then returnstrue
, else returnsfalse
.constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.day() == y.day()
.constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept;Returns: If
x.year() < y.year()
, returnstrue
. Else ifx.year() > y.year()
returnsfalse
. Else ifx.month() < y.month()
, returnstrue
. Else ifx.month() > y.month()
, returnsfalse
. Else returnsx.day() < y.day()
.constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept;Returns:
!(x < y)
.constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;Returns:
(ymd.year() / ymd.month() + dm) / ymd.day()
.Remarks: If
ymd.day()
is in the range[1_d, 28_d]
, 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()
isFebruary
andymd.day()
is not in the range[1_d, 28_d]
, 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)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_day& ymd);Effects: Inserts
yyyy-mm-dd
where the number of indicated digits are prefixed with'0'
if necessary..Returns:
os
.template<class CharT, class Traits> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<class CharT, class Traits>& os, const CharT* fmt, const year_month_day& ymd);Effects: Inserts
ymd
intoos
using the format stringfmt
as specified by theto_stream
formatting flags.If
%z
or%Z
is used in thefmt
stringfailbit
will be set foros
.Returns:
os
.template <class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month_day& ymd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr);Effects: Extracts
ymd
fromis
using the format stringfmt
as specified by thefrom_stream
formatting flags. Ifabbrev
is not equal tonullptr
, the information parsed by%Z
(if present) will be placed in*abbrev
. Ifoffset
is not equal tonullptr
, the information parsed by%z
(if present) will be placed in*offset
. If an invalid date is parsed, or a time of day which is outside of the conventional bounds,failbit
will be set andymd
will not be altered. In particular!ymd.ok()
is not an indication of error.Returns:
is
.
year_month_day_last
Synopsis
class year_month_day_last { date::year y_; // exposition only date::month_day_last mdl_; // exposition only public: constexpr year_month_day_last(const date::year& y, const date::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 date::year year() const noexcept; constexpr date::month month() const noexcept; constexpr date::month_day_last month_day_last() const noexcept; constexpr date::day day() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator> (const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept; constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept; constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_day_last& ymdl);Overview
year_month_day_last
represents a specificyear
,month
, and the lastday
of themonth
.year_month_day_last
is a field-based time point with a resolution ofdays
, except that it is restricted to pointing to the last day of a year and month. One can observe each field. Theday
field is computed on demand.year_month_day_last
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_day_last
is equality and less-than comparable.Specification
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 date::year& y, const date::month_day_last& mdl) noexcept;Effects: Constructs an object of type
year_month_day_last
by constructingy_
withy
andmdl_
withmdl
.constexpr year_month_day_last& year_month_day_last::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_day_last& year_month_day_last::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_day_last::year() const noexcept;Returns:
y_
.constexpr month year_month_day_last::month() const noexcept;Returns:
mdl_.month()
.constexpr month_day_last year_month_day_last::month_day_last() const noexcept;Returns:
mdl_
.constexpr day year_month_day_last::day() const noexcept;Returns: A
day
representing the last day of theyear
,month
pair represented by*this
.constexpr year_month_day_last::operator sys_days() const noexcept;Effects: Equivalent to:
return sys_days{year()/month()/day()};
constexpr explicit year_month_day_last::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_day_last::ok() const noexcept;Returns:
y_.ok() && mdl_.ok()
.constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
x.year() == y.year() && x.month_day_last() == y.month_day_last()
.constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(x == y)
.constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns: If
x.year() < y.year()
, returnstrue
. Else ifx.year() > y.year()
returnsfalse
. Else returnsx.month_day_last() < y.month_day_last()
.constexpr bool operator> (const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
y < x
.constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(y < x)
.constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept;Returns:
!(x < y)
.constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept;Effects: Equivalent to:
return (ymdl.year() / ymdl.month() + dm) / last
.constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept;Returns:
ymdl + dm
.constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept;Returns:
ymdl + (-dm)
.constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept;Returns:
{ymdl.year()+dy, ymdl.month_day_last()}
.constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept;Returns:
ymdl + dy
.constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept;Returns:
ymdl + (-dy)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_day_last& ymdl);Effects: Inserts
os << ymdl.year() << '/' << ymdl.month_day_last()
.Returns:
os
.
year_month_weekday
Synopsis
class year_month_weekday { date::year y_; // exposition only date::month m_; // exposition only date::weekday_indexed wdi_; // exposition only public: year_month_weekday() = default; constexpr year_month_weekday(const date::year& y, const date::month& m, const date::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 date::year year() const noexcept; constexpr date::month month() const noexcept; constexpr date::weekday weekday() const noexcept; constexpr unsigned index() const noexcept; constexpr date::weekday_indexed weekday_indexed() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept; constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept; constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_weekday& ymwdi);Overview
year_month_weekday
represents a specificyear
,month
, and nthweekday
of themonth
.year_month_weekday
is a field-based time point with a resolution ofdays
. One can observe each field.year_month_weekday
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_weekday
is equality comparable.Specification
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 date::year& y, const date::month& m, const date::weekday_indexed& wdi) noexcept;Effects: Constructs an object of type
year_month_weekday
by constructingy_
withy
,m_
withm
, andwdi_
withwdi
.constexpr year_month_weekday(const sys_days& dp) noexcept;Effects: Constructs an object of type
year_month_weekday
which corresponds to the date represented bydp
.Remarks: For any value of
year_month_weekday
,ymdl
, for whichymdl.ok()
istrue
, this equality will also betrue
:ymdl == year_month_weekday{sys_days{ymdl}}
.constexpr explicit year_month_weekday(const local_days& dp) noexcept;Effects: Constructs an object of type
year_month_weekday
which corresponds to the date represented bydp
.Remarks: Equivalent to constructing with
sys_days{dp.time_since_epoch()}
.constexpr year_month_weekday& year_month_weekday::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_weekday& year_month_weekday::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_weekday::year() const noexcept;Returns:
y_
.constexpr month year_month_weekday::month() const noexcept;Returns:
m_
.constexpr weekday year_month_weekday::weekday() const noexcept;Returns:
wdi_.weekday()
.constexpr unsigned year_month_weekday::index() const noexcept;Returns:
wdi_.index()
.constexpr weekday_indexed year_month_weekday::weekday_indexed() const noexcept;Returns:
wdi_
.constexpr year_month_weekday::operator sys_days() const noexcept;Returns: If
y_.ok() && m_.ok() && wdi_.weekday().ok()
, returns asys_days
which represents the date(index() - 1)*7
days after the firstweekday()
ofyear()/month()
. Ifindex()
is0
the returnedsys_days
represents the date 7 days prior to the firstweekday()
ofyear()/month()
. Otherwise,!y_.ok() || !m_.ok() || !wdi_.weekday().ok()
and the returned value is unspecified.constexpr explicit year_month_weekday::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_weekday::ok() const noexcept;Returns: If
y_.ok()
orm_.ok()
orwdi_.ok()
returnsfalse
, returnsfalse
. Else if*this
represents a valid date, returnstrue
, else returnsfalse
.constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed()
.constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept;Returns:
!(x == y)
.constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept;Returns:
(ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed()
.constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept;Returns:
ymwd + dm
.constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept;Returns:
ymwd + (-dm)
.constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept;Returns:
{ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}
.constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept;Returns:
ymwd + dm
.constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept;Returns:
ymwd + (-dm)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_weekday& ymwd);Effects: Inserts
os << ymwdi.year() << '/' << ymwdi.month() << '/' << ymwdi.weekday_indexed()
.Returns:
os
.
year_month_weekday_last
Synopsis
class year_month_weekday_last { date::year y_; // exposition only date::month m_; // exposition only date::weekday_last wdl_; // exposition only public: constexpr year_month_weekday_last(const date::year& y, const date::month& m, const date::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 date::year year() const noexcept; constexpr date::month month() const noexcept; constexpr date::weekday weekday() const noexcept; constexpr date::weekday_last weekday_last() const noexcept; constexpr operator sys_days() const noexcept; constexpr explicit operator local_days() const noexcept; constexpr bool ok() const noexcept; }; constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept; constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept; template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_weekday_last& ymwdl);Overview
year_month_weekday_last
represents a specificyear
,month
, and lastweekday
of themonth
.year_month_weekday_last
is a field-based time point with a resolution ofdays
, except that it is restricted to pointing to the last weekday of a year and month. One can observe each field.year_month_weekday_last
supportsyears
andmonths
oriented arithmetic, but notdays
oriented arithmetic. For the latter, there is a conversion tosys_days
which efficiently supportsdays
oriented arithmetic.year_month_weekday_last
is equality comparable.Specification
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 date::year& y, const date::month& m, const date::weekday_last& wdl) noexcept;Effects: Constructs an object of type
year_month_weekday_last
by constructingy_
withy
,m_
withm
, andwdl_
withwdl
.constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& m) noexcept;Effects:
*this = *this + m;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& m) noexcept;Effects:
*this = *this - m;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& y) noexcept;Effects:
*this = *this + y;
.Returns:
*this
.constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& y) noexcept;Effects:
*this = *this - y;
.Returns:
*this
.constexpr year year_month_weekday_last::year() const noexcept;Returns:
y_
.constexpr month year_month_weekday_last::month() const noexcept;Returns:
m_
.constexpr weekday year_month_weekday_last::weekday() const noexcept;Returns:
wdl_.weekday()
.constexpr weekday_last year_month_weekday_last::weekday_last() const noexcept;Returns:
wdl_
.constexpr year_month_weekday_last::operator sys_days() const noexcept;Returns: If
ok() == true
, returns asys_days
which represents the lastweekday()
ofyear()/month()
. Otherwise the returned value is unspecified.constexpr explicit year_month_weekday_last::operator local_days() const noexcept;Effects: Equivalent to:
return local_days{sys_days{*this}.time_since_epoch()};
constexpr bool year_month_weekday_last::ok() const noexcept;Returns: If
y_.ok() && m_.ok() && wdl_.ok()
.constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;Returns:
x.year() == y.year() && x.month() == y.month() && x.weekday_last() == y.weekday_last()
.constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;Returns:
!(x == y)
.constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept;Effects: Equivalent to:
return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last()
.constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept;Returns:
ymwdl + dm
.constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept;Returns:
ymwdl + (-dm)
.constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept;Returns:
{ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}
.constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept;Returns:
ymwdl + dy
.constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept;Returns:
ymwdl + (-dy)
.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const year_month_weekday_last& ymwdl);Effects: Inserts
os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last()
.Returns:
os
.
To understand this API it is not necessary for you to memorize each of these operators. Indeed, that would be detrimental to understanding this API. Instead it is sufficient to known that this collection of operators implement constructions in 3 orders:
y/m/d
m/d/y
d/m/y
The first component in each order must be properly typed, the following components may be specified with the proper type or an
int
.Anywhere a "day" is required one can also specify one of:
last
weekday[i]
weekday[last]
Sub-field-types such as
year_month
andmonth_day
can be created by simply not applying the second division operator for any of the three orders. For example:year_month ym = 2015_y/April; month_day md1 = April/4; month_day md2 = 4_d/April;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 typeint
.auto a = 2015/4/4; // a == int(125) auto b = 2015_y/4/4; // b == year_month_day{year(2015), month(4), day(4)} auto c = 2015_y/4_d/April; // error: invalid operands to binary expression ('date::year' and 'date::day') auto d = 2015/April/4; // error: invalid operands to binary expression ('int' and 'const date::month')The last example may be clear to a human reader. But the compiler doesn't know if
2015
refers to ayear
or aday
. Instead of guessing, the compiler flags it as an error.In short, you will either write unambiguous and readable code, or you will get a compile-time 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
.
time_of_day
Overview
template <class Duration> class time_of_day;The
time_of_day
class breaks astd::chrono::duration
which represents the time elapsed since midnight, into a "broken" down time such as hours:minutes:seconds. TheDuration
template parameter dictates the precision to which the time is broken down. This can vary from a course precision of hours to a very fine precision of nanoseconds.There are 4 specializations of
time_of_day
to handle four precisions:
time_of_day<std::chrono::hours>This specialization handles hours since midnight.
time_of_day<std::chrono::minutes>This specialization handles hours:minutes since midnight.
time_of_day<std::chrono::seconds>This specialization handles hours:minutes:seconds since midnight.
time_of_day<std::chrono::duration<Rep, Period>>This specialization is restricted to
Period
s that fractions of a second to represent. Typical uses are with milliseconds, microseconds and nanoseconds. This specialization handles hours:minute:seconds.fractional_seconds since midnight.Specification
enum {am = 1, pm};Each specialization of
time_of_day
is a trivially copyable class type.
Each specialization oftime_of_day
is a standard-layout class type.
Each specialization oftime_of_day
is a literal class type.
time_of_day<std::chrono::hours> { public: using precision = std::chrono::hours; constexpr time_of_day() noexcept; constexpr explicit time_of_day(std::chrono::hours since_midnight) noexcept; constexpr std::chrono::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 time_of_day<std::chrono::hours>::time_of_day() noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding to 00:00:00 hours after 00:00:00.Postconditions:
hours()
returns0h
.mode()
returns0
.constexpr explicit time_of_day<std::chrono::hours>::time_of_day(std::chrono::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 std::chrono::hours time_of_day<std::chrono::hours>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr unsigned time_of_day<std::chrono::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<std::chrono::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<std::chrono::hours>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<std::chrono::hours>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const time_of_day<std::chrono::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 formattime_of_day<std::chrono::minutes> { public: using precision = std::chrono::minutes; constexpr time_of_day() noexcept; constexpr explicit time_of_day(std::chrono::minutes since_midnight) noexcept; constexpr std::chrono::hours hours() const noexcept; constexpr std::chrono::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 time_of_day<std::chrono::minutes>::time_of_day() noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding to 0 minutes after 00:00:00.Postconditions:
hours()
returns0h
.minutes()
returns0min
.mode()
returns0
.constexpr explicit time_of_day<std::chrono::minutes>::time_of_day(std::chrono::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 std::chrono::hours time_of_day<std::chrono::minutes>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr std::chrono::minutes time_of_day<std::chrono::minutes>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr unsigned time_of_day<std::chrono::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<std::chrono::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<std::chrono::minutes>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<std::chrono::minutes>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const time_of_day<std::chrono::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 formattime_of_day<std::chrono::seconds> { public: using precision = std::chrono::seconds; constexpr time_of_day() noexcept; constexpr explicit time_of_day(std::chrono::seconds since_midnight) noexcept; constexpr std::chrono::hours hours() const noexcept; constexpr std::chrono::minutes minutes() const noexcept; constexpr std::chrono::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 time_of_day<std::chrono::seconds>::time_of_day() noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding to 0 seconds after 00:00:00.Postconditions:
hours()
returns0h
.minutes()
returns0min
.seconds()
returns0s
.mode()
returns0
.constexpr explicit time_of_day<std::chrono::seconds>::time_of_day(std::chrono::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 std::chrono::hours time_of_day<std::chrono::seconds>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr std::chrono::minutes time_of_day<std::chrono::seconds>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr std::chrono::seconds time_of_day<std::chrono::seconds>::seconds() const noexcept;Returns: The stored second of
*this
.constexpr unsigned time_of_day<std::chrono::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<std::chrono::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<std::chrono::seconds>::make24() noexcept;Effects: If
*this
is a 12-hour time, converts to a 24-hour time. Otherwise, no effects.void time_of_day<std::chrono::seconds>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template<class CharT, class Traits> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const time_of_day<std::chrono::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 formattime_of_day<std::chrono::duration<Rep, Period>> { public: using precision = The decimal-based duration used to format constexpr time_of_day() noexcept; constexpr explicit time_of_day(std::chrono::duration<Rep, Period> since_midnight) noexcept; constexpr std::chrono::hours hours() const noexcept; constexpr std::chrono::minutes minutes() const noexcept; constexpr std::chrono::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
Period < 1s
.constexpr time_of_day<std::chrono::duration<Rep, Period>>::time_of_day() noexcept;Effects: Constructs an object of type
time_of_day
in 24-hour format corresponding to 0 fractional seconds after 00:00:00.Postconditions:
hours()
returns0h
.minutes()
returns0min
.seconds()
returns0s
.subseconds()
returns 0 fractional precision seconds.mode()
returns0
.constexpr explicit time_of_day<std::chrono::duration<Rep, Period>>::time_of_day(std::chrono::duration<Rep, Period> 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 std::chrono::hours time_of_day<std::chrono::duration<Rep, Period>>::hours() const noexcept;Returns: The stored hour of
*this
.constexpr std::chrono::minutes time_of_day<std::chrono::duration<Rep, Period>>::minutes() const noexcept;Returns: The stored minute of
*this
.constexpr std::chrono::seconds time_of_day<std::chrono::duration<Rep, Period>>::seconds() const noexcept;Returns: The stored second of
*this
.constexpr std::chrono::duration<Rep, Period> time_of_day<std::chrono::duration<Rep, Period>>::subseconds() const noexcept;Returns: The stored subsecond of
*this
.constexpr unsigned time_of_day<std::chrono::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<std::chrono::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<std::chrono::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<std::chrono::duration<Rep, Period>>::make12() noexcept;Effects: If
*this
is a 24-hour time, converts to a 12-hour time. Otherwise, no effects.template<class CharT, class Traits, class Rep, class Period> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const time_of_day<std::chrono::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
template <class Rep, class Period> constexpr time_of_day<std::chrono::duration<Rep, Period>> make_time(std::chrono::duration<Rep, Period> d) noexcept;Returns:
time_of_day<std::chrono::duration<Rep, Period>>(d)
.
template <class CharT, class Traits, class Duration> std::basic_ostream<class CharT, class Traits>& operator<<(std::basic_ostream<class CharT, class Traits>& os, const std::chrono::time_point<std::chrono::system_clock, Duration>& tp);
Remarks: This operator shall not participate in overload resolution if
std::chrono::treat_as_floating_point<typename Duration::rep>::value
is true.Effects: If
Duration{1} < days{1}
:auto const dp = floor<days>(tp); os << year_month_day(dp) << ' ' << make_time(tp-dp);Otherwise:
os << year_month_day(floor<days>(tp));Returns:
os
.
to_stream
formatting
Each flag begins with a %
. Some flags can be modified by E
or
O
. During streaming each flag is replaced according to the table below. All
characters in the format string which are not represented in the table below are inserted
unchanged into the stream.
%a
The locale's abbreviated weekday name. If the value does not contain a valid weekday
,std::ios::failbit
is set.%A
The locale's full weekday name. If the value does not contain a valid weekday
,std::ios::failbit
is set.%b
The locale's abbreviated month name. If the value does not contain a valid month
,std::ios::failbit
is set.%B
The locale's full month name. If the value does not contain a valid month
,std::ios::failbit
is set.%c
The locale's date and time representation. The modified command %Ec
produces the locale's alternate date and time representation.%C
The year divided by 100 using floored division. If the result is a single decimal digit, it is prefixed with 0
. The modified command%EC
produces the locale's alternative representation of the century.%d
The day of month as a decimal number. If the result is a single decimal digit, it is prefixed with 0
. The modified command%Od
produces the locale's alternative representation.%D
Equivalent to %m/%d/%y
.%e
The day of month as a decimal number. If the result is a single decimal digit, it is prefixed with a space. The modified command %Oe
produces the locale's alternative representation.%F
Equivalent to %Y-%m-%d
.%g
The last two decimal digits of the ISO week-based year. If the result is a single digit it is prefixed by 0
.%G
The ISO week-based year as a decimal number. If the result is less than four digits it is left-padded with 0
to four digits.%h
Equivalent to %b
.%H
The hour (24-hour clock) as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OH
produces the locale's alternative representation.%I
The hour (12-hour clock) as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OI
produces the locale's alternative representation.%j
The day of the year as a decimal number. Jan 1 is 001
. If the result is less than three digits, it is left-padded with0
to three digits.%m
The month as a decimal number. Jan is 01
. If the result is a single digit, it is prefixed with0
. The modified command%Om
produces the locale's alternative representation.%M
The minute as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OM
produces the locale's alternative representation.%n
A newline character. %p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock. %r
The locale's 12-hour clock time. %R
Equivalent to %H:%M
.%S
Seconds as a decimal number. If the number of seconds is less than 10, the result is prefixed with 0
. If the precision of the input can not be exactly represented with seconds, then the format is a decimal floating point number with a fixed format and a precision matching that of the precision of the input (or to a microseconds precision if the conversion to floating point decimal seconds can not be made within 18 fractional digits). The character for the decimal point is localized according to the locale. The modified command%OS
produces the locale's alternative representation.%t
A horizontal-tab character. %T
Equivalent to %H:%M:%S
.%u
The ISO weekday as a decimal number (1-7), where Monday is 1. The modified command %Ou
produces the locale's alternative representation.%U
The week number of the year as a decimal number. The first Sunday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. If the result is a single digit, it is prefixed with0
. The modified command%OU
produces the locale's alternative representation.%V
The ISO week-based week number as a decimal number. If the result is a single digit, it is prefixed with 0
. The modified command%OV
produces the locale's alternative representation.%w
The weekday as a decimal number (0-6), where Sunday is 0. The modified command %Ow
produces the locale's alternative representation.%W
The week number of the year as a decimal number. The first Monday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. If the result is a single digit, it is prefixed with0
. The modified command%OW
produces the locale's alternative representation.%x
The locale's date representation. The modified command %Ex
produces the locale's alternate date representation.%X
The locale's time representation. The modified command %Ex
produces the locale's alternate time representation.%y
The last two decimal digits of the year. If the result is a single digit it is prefixed by 0
.%Y
The year as a decimal number. If the result is less than four digits it is left-padded with 0
to four digits.%z
The offset from UTC in the ISO 8601 format. For example -0430
refers to 4 hours 30 minutes behind UTC. If the offset is zero,+0000
is used. The modified commands%Ez
and%Oz
insert a:
between the hours and minutes:-04:30
. If the offset information is not available,failbit
will be set.%Z
The time zone abbreviation. If the time zone abbreviation is not available, failbit
will be set.UTC
is used forsys_time
.%%
A %
character.
format
template <class CharT, class Streamable> std::basic_string<CharT> format(const std::locale& loc, const CharT* fmt, const Streamable& tp);
Remarks: This function does not participate in overload resolution unless
to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp)
is valid.Effects: Constructs a
std::basic_ostringstream<CharT> os
and imbues it withloc
. Executesos.exceptions(std::ios::failbit | std::ios::badbit)
. Callsto_stream(os, fmt, tp)
.Returns:
os.str()
.
template <class CharT, class Streamable> std::basic_string<CharT> format(const CharT* fmt, const Streamable& tp);
Remarks: This function does not participate in overload resolution unless
to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp)
is valid.Effects: Constructs a
std::basic_ostringstream<CharT> os
. Executesos.exceptions(std::ios::failbit | std::ios::badbit)
. Callsto_stream(os, fmt, tp)
.Returns:
os.str()
.
template <class CharT, class Traits, class Streamable> std::basic_string<CharT> format(const std::locale& loc, const std::basic_string<CharT, Traits>& fmt, const Streamable& tp);
Remarks: This function does not participate in overload resolution unless
to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt.c_str(), tp)
is valid.Effects: Constructs a
std::basic_ostringstream<CharT> os
and imbues it withloc
. Executesos.exceptions(std::ios::failbit | std::ios::badbit)
. Callsto_stream(os, fmt.c_str(), tp)
.Returns:
os.str()
.
template <class CharT, class Traits, class Streamable> std::basic_string<CharT> format(const std::basic_string<CharT, Traits>& fmt, const Streamable& tp);
Remarks: This function does not participate in overload resolution unless
to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt.c_str(), tp)
is valid.Effects: Constructs a
std::basic_ostringstream<CharT> os
. Executesos.exceptions(std::ios::failbit | std::ios::badbit)
. Callsto_stream(os, fmt.c_str(), tp)
.Returns:
os.str()
.
from_stream
formatting
All from_stream
overloads behave as an unformatted input function. Each
overload takes a format string containing ordinary characters and flags which have special
meaning. Each flag begins with a %
. Some flags can be modified by
E
or O
. During parsing each flag interprets characters as parts
of date and time type according to the table below. Some flags can be modified by a width
parameter which governs how many characters are parsed from the stream in interpreting the
flag. All characters in the format string which are not represented in the table below,
except for white space, are parsed unchanged from the stream. A white space character
matches zero or more white space characters in the input stream. The C++ specification
says that the parsing of month and weekday names is both locale sensitive and case
insensitive. If you find this not to be the case, file a bug with your std::lib vendor.
%a
The locale's full or abbreviated case-insensitive weekday name. %A
Equivalent to %a
.%b
The locale's full or abbreviated case-insensitive month name. %B
Equivalent to %b
.%c
The locale's date and time representation. The modified command %Ec
interprets the locale's alternate date and time representation.%C
The century as a decimal number. The modified command %NC
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands%EC
and%OC
interpret the locale's alternative representation of the century.%d
The day of the month as a decimal number. The modified command %Nd
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%EC
interprets the locale's alternative representation of the day of the month.%D
Equivalent to %m/%d/%y
.%e
Equivalent to %d
and can be modified like%d
.%F
Equivalent to %Y-%m-%d
. If modified with a width, the width is applied to only%Y
.%g
The last two decimal digits of the ISO week-based year. The modified command %Ng
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%G
The ISO week-based year as a decimal number. The modified command %NG
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 4. Leading zeroes are permitted but not required.%h
Equivalent to %b
.%H
The hour (24-hour clock) as a decimal number. The modified command %NH
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%OH
interprets the locale's alternative representation.%I
The hour (12-hour clock) as a decimal number. The modified command %NI
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%j
The day of the year as a decimal number. Jan 1 is 1
. The modified command%Nj
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 3. Leading zeroes are permitted but not required.%m
The month as a decimal number. Jan is 1
. The modified command%Nm
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%Om
interprets the locale's alternative representation.%M
The minutes as a decimal number. The modified command %NM
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified command%OM
interprets the locale's alternative representation.%n
Matches one white space character. [Note: %n
,%t
and a space, can be combined to match a wide range of white-space patterns. For example"%n "
matches one or more white space charcters, and"%n%t%t"
matches one to three white space characters. — end note]%p
The locale's equivalent of the AM/PM designations associated with a 12-hour clock. The command %I
must precede%p
in the format string.%r
The locale's 12-hour clock time. %R
Equivalent to %H:%M
.%S
The seconds as a decimal number. The modified command %NS
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2 if the input time has a precision convertible to seconds. Otherwise the default width is determined by the decimal precision of the input and the field is interpreted as a long double in a fixed format. If encountered, the locale determines the decimal point character. Leading zeroes are permitted but not required. The modified command%OS
interprets the locale's alternative representation.%t
Matches zero or one white space characters. %T
Equivalent to %H:%M:%S
.%u
The ISO weekday as a decimal number (1-7), where Monday is 1. The modified command %Nu
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 1. Leading zeroes are permitted but not required. The modified command%Ou
interprets the locale's alternative representation.%U
The week number of the year as a decimal number. The first Sunday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. The modified command%NU
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%V
The ISO week-based week number as a decimal number. The modified command %NV
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%w
The weekday as a decimal number (0-6), where Sunday is 0. The modified command %Nw
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 1. Leading zeroes are permitted but not required. The modified command%Ou
interprets the locale's alternative representation.%W
The week number of the year as a decimal number. The first Monday of the year is the first day of week 01
. Days of the same year prior to that are in week00
. The modified command%NW
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required.%x
The locale's date representation. The modified command %Ex
produces the locale's alternate date representation.%X
The locale's time representation. The modified command %Ex
produces the locale's alternate time representation.%y
The last two decimal digits of the year. If the century is not otherwise specified (e.g. with %C
), values in the range [69 - 99] are presumed to refer to the years [1969 - 1999], and values in the range [00 - 68] are presumed to refer to the years [2000 - 2068]. The modified command%Ny
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 2. Leading zeroes are permitted but not required. The modified commands%Ey
and%Oy
interpret the locale's alternative representation.%Y
The year as a decimal number. The modified command %NY
whereN
is a positive decimal integer specifies the maximum number of characters to read. If not specified, the default is 4. Leading zeroes are permitted but not required. The modified command%EY
interprets the locale's alternative representation.%z
The offset from UTC in the format [+|-]hh[mm]
. For example-0430
refers to 4 hours 30 minutes behind UTC. And04
refers to 4 hours ahead of UTC. The modified commands%Ez
and%Oz
parse a:
between the hours and minutes and leading zeroes on the hour field are optional:[+|-]h[h][:mm]
. For example-04:30
refers to 4 hours 30 minutes behind UTC. And4
refers to 4 hours ahead of UTC.%Z
The time zone abbreviation or name. A single word is parsed. This word can only contain characters from the basic source character set ([lex.charset] in the C++ standard) that are alphanumeric, or one of '_'
,'/'
,'-'
or'+'
.%%
A %
character is extracted.
parse
template <class Parsable, class CharT, class Traits, class Alloc> unspecified parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format.c_str(), tp)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format.c_str(), tp)
.
template <class Parsable, class CharT, class Traits, class Alloc> unspecified parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp, std::basic_string<CharT, Traits, Alloc>& abbrev);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format.c_str(), tp, &abbrev)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format.c_str(), tp, &abbrev)
.
template <class Parsable, class CharT, class Traits, class Alloc> unspecified parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp, std::chrono::minutes& offset);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format.c_str(), tp, nullptr, &offset)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format.c_str(), tp, nullptr, &offset)
.
template <class Parsable, class CharT, class Traits> unspecified parse(const std::basic_string<CharT, Traits>& format, Parsable& tp, std::basic_string<CharT, Traits>& abbrev, std::chrono::minutes& offset);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format.c_str(), tp, &abbrev, &offset)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format.c_str(), tp, &abbrev, &offset)
.
// const CharT* formats template <class Parsable, class CharT> unspecified parse(const CharT* format, Parsable& tp);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format, tp)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format, tp)
.
template <class Parsable, class CharT, class Traits, class Alloc> unspecified parse(const CharT* format, Parsable& tp, std::basic_string<CharT, Traits, Alloc>& abbrev);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format, tp, &abbrev)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format, tp, &abbrev)
.
template <class Parsable, class CharT> unspecified parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format, tp, nullptr, &offset)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format, tp, nullptr, &offset)
.
template <class Parsable, class CharT, class Traits, class Alloc> unspecified parse(const CharT* format, Parsable& tp, std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset);
Remarks: This function does not participate in overload resolution unless
from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format, tp, &abbrev, &offset)
is validReturns: A
basic_istream<CharT, Traits>
manipulator that on extraction from abasic_istream<CharT, Traits> is
callsfrom_stream(is, format, tp, &abbrev, &offset)
.
Some of the parsing and formatting flags require help from your std::lib's
time_get
and time_put
facets for localization help. If you are
happy with being restricted to the "C"
locale, and/or need to port this to an
older platform that doesn't support the time_get
and time_put
facets, compile with -DONLY_C_LOCALE=1
. This enables all of the streaming
and parsing flags, but makes all of them assume the "C"
locale, and removes
the dependency on the time_get
and time_put
facets.