Howard E. Hinnant
2016-05-28

date

Contents

Introduction

This paper fully documents a date and time library for use with C++11 and C++14.

Implementation

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.

Overview

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.

Major Concepts

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:

  1. serial-based
  2. field-based

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.

Major Types

This library is composed of many types. But here are the most important ones:

  1. sys_days: A count of days since system_clock's epoch. This is a serial-based time point with a resolution of one day.
  2. 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.
  3. 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.

Examples

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.

Example: Constructing dates

year_month_day

constexpr dates can be constructed from literals in any one of 3 orders:

constexpr auto x1 = 2015_y/mar/22;
constexpr auto x2 = mar/22/2015;
constexpr auto x3 = 22_d/mar/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/feb/last;
constexpr auto x2 = feb/last/2015;
constexpr auto x3 = last/feb/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/mar/sun[4];
constexpr auto x2 = mar/sun[4]/2015;
constexpr auto x3 = sun[4]/mar/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/mar/sun[last];
constexpr auto x2 = mar/sun[last]/2015;
constexpr auto x3 = sun[last]/mar/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:

2015/Mar/Sun[last]
2015-03-29
Escape hatch from the conventional syntax

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/mar/sun[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]

Example: Today

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.

Example: Contrast with C

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{jul/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/jul/4} == wed, "");
}

(Date ordering was switched simply to assure the gentle reader that we're not hung up on m/d/y ordering.)

Errors

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/fri[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.

Efficiency

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.

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 jan/1/2000 to jan/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(jan/1/2000) - sys_days(jan/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(jan/1/2000) - sys_days(jan/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).

What about a date-time type?

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{sun[2]/mar/y} + 2h - EST; // EDT begins at this UTC time
    const auto end   = sys_days{sun[1]/nov/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

Extensibility

The hub of this library is sys_days. This is a serial-based time point which simply counts the days since (or before) jan/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_ - mon);
    }

    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{thu[1]/jan/y} - (thu-mon);
    }

    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:

  1. Weeks begin with Monday and end on Sunday.
  2. The year begins on the Monday prior to the first Thursday in January.
  3. A date is specified by the week number [1 - 53], day of the week [Mon - Sun], and year number.
  4. The year number is the same as the civil year number for the Thursday that follows the start of the week-based year.

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{thu[1]/jan/y} - (thu-mon);

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 (thu-mon). 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 "(thu-mon)" 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 jan/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_ - mon);

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.

Range of Validity

As with all numerical representations with a fixed storage size, durations, time_points, and year_month_days 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()}/jan/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 durations, 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:

  1. If you need to check range, do the check using duration<double> to ensure your comparison is not itself vulnerable to overflow.

  2. 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.

Reference

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.

durations 
 days
 weeks
 months
 years
  
time_points 
 sys_time
 sys_days
 sys_seconds
 local_time
 local_days
 local_seconds
  
types 
 last_spec
  
 day
 month
 year
  
 weekday
 weekday_indexed
 weekday_last
  
 month_day
 month_day_last
 month_weekday
 month_weekday_last
  
 year_month
  
 year_month_day
 year_month_day_last
 year_month_weekday
 year_month_weekday_last
  
 time_of_day
  
conventional syntax
operators
 
 constexpr year_month operator/(const year& y, const month& m) noexcept;
 constexpr year_month operator/(const year& y, int m) noexcept;
  
 constexpr month_day operator/(const month& m, const day& d) noexcept;
 constexpr month_day operator/(const month& m, int d) noexcept;
 constexpr month_day operator/(int m, const day& d) noexcept;
 constexpr month_day operator/(const day& d, const month& m) noexcept;
 constexpr month_day operator/(const day& d, int m) noexcept;
  
 constexpr month_day_last operator/(const month& m, last_spec) noexcept;
 constexpr month_day_last operator/(int m, last_spec) noexcept;
 constexpr month_day_last operator/(last_spec, const month& m) noexcept;
 constexpr month_day_last operator/(last_spec, int m) noexcept;
  
 constexpr month_weekday operator/(const month& m, const weekday_indexed& wdi) noexcept;
 constexpr month_weekday operator/(int m, const weekday_indexed& wdi) noexcept;
 constexpr month_weekday operator/(const weekday_indexed& wdi, const month& m) noexcept;
 constexpr month_weekday operator/(const weekday_indexed& wdi, int m) noexcept;
  
 constexpr month_weekday_last operator/(const month& m, const weekday_last& wdl) noexcept;
 constexpr month_weekday_last operator/(int m, const weekday_last& wdl) noexcept;
 constexpr month_weekday_last operator/(const weekday_last& wdl, const month& m) noexcept;
 constexpr month_weekday_last operator/(const weekday_last& wdl, int m) noexcept;
  
 constexpr year_month_day operator/(const year_month& ym, const day& d) noexcept;
 constexpr year_month_day operator/(const year_month& ym, int d) noexcept;
 constexpr year_month_day operator/(const year& y, const month_day& md) noexcept;
 constexpr year_month_day operator/(int y, const month_day& md) noexcept;
 constexpr year_month_day operator/(const month_day& md, const year& y) noexcept;
 constexpr year_month_day operator/(const month_day& md, int y) noexcept;
  
 constexpr year_month_day_last operator/(const year_month& ym, last_spec) noexcept;
 constexpr year_month_day_last operator/(const year& y, const month_day_last& mdl) noexcept;
 constexpr year_month_day_last operator/(int y, const month_day_last& mdl) noexcept;
 constexpr year_month_day_last operator/(const month_day_last& mdl, const year& y) noexcept;
 constexpr year_month_day_last operator/(const month_day_last& mdl, int y) noexcept;
  
 constexpr year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) noexcept;
 constexpr year_month_weekday operator/(const year& y, const month_weekday& mwd) noexcept;
 constexpr year_month_weekday operator/(int y, const month_weekday& mwd) noexcept;
 constexpr year_month_weekday operator/(const month_weekday& mwd, const year& y) noexcept;
 constexpr year_month_weekday operator/(const month_weekday& mwd, int y) noexcept;
  
 constexpr year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) noexcept;
 constexpr year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) noexcept;
 constexpr year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) noexcept;
 constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) noexcept;
 constexpr year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) noexcept;
  
time_of_day
factory functions
 
 
template <class Rep, class Period>
constexpr
time_of_day<std::chrono::duration<Rep, Period>>
make_time(std::chrono::duration<Rep, Period> d) noexcept;
 
constexpr
time_of_day<std::chrono::hours>
make_time(std::chrono::hours h, unsigned md) noexcept;
 
constexpr
time_of_day<std::chrono::minutes>
make_time(std::chrono::hours h, std::chrono::minutes m, unsigned md) noexcept;
 
constexpr
time_of_day<std::chrono::seconds>
make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
          unsigned md) noexcept;
 
template <class Rep, class Period,
          class = std::enable_if_t<std::ratio_less<Period, std::ratio<1>>::value>>
constexpr
time_of_day<std::chrono::duration<Rep, Period>>
make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
          std::chrono::duration<Rep, Period> sub_s, unsigned md) noexcept
  
convenience
streaming operators
 
 
template <class CharT, class Traits, class Duration>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const sys_time<Duration>& tp);
 
template <class CharT, class Traits, class Duration>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, const local_time<Duration>& tp);

Everything here is contained in the namespace date. The literal operators, and the constexpr field literals (e.g. sun, jan, etc.) are in namespace date_literals and imported into namespace date.

days

days is a std::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 two sys_dayss.

using days = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;

weeks

weeks is a std::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 to days but not vice-versa.

using weeks = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<7>, days::period>>;

years

years is a std::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 two year field-based time points. years is not implicitly convertible to days or weeks nor vice-versa. However years will implicitly convert to months.

using years = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;

months

months is a std::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 two month field-based time points. months is not implicitly convertible to days or weeks nor vice-versa. months will not implicitly convert to years.

using months = std::chrono::duration
    <int, std::ratio_divide<years::period, std::ratio<12>>>;

sys_time

sys_time is a convenience template alias for creating a system_clock::time_point but of arbitrary precision. This family of types represents "system time", which closely models UTC. See utc_time in tz.h for a variation of sys_time that accurately takes leap seconds into account when subtracting time_points.

template <class Duration>
    using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;

sys_days

sys_days is a std::chrono::time_point using std::chrono::system_clock and days. This makes sys_days interoperable with std::chrono::system_clock::time_point. It is simply a count of days since the epoch of std::chrono::system_clock which in every implementation is Jan. 1, 1970. sys_days is a serial-based time point with a resolution of days.

using sys_days = sys_time<days>;

sys_seconds

sys_seconds is a std::chrono::time_point using std::chrono::system_clock and std::chrono::seconds. This makes sys_seconds interoperable with std::chrono::system_clock::time_point. It is simply a count of non-leap seconds since the epoch of std::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 of seconds. sys_seconds is also widely known as Unix Time.

using sys_seconds = sys_time<std::chrono::seconds>;

local_time

local_time is a convenience template alias for creating a time_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/jan/1} + 0s. For those in a time zone with a zero offset from UTC, it will be celebrated at the concrete time of sys_days{2017_y/jan/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 write local_time<days>. The upcoming 2017 New Years will be commonly celebrated at local_days{2017_y/jan/1} + 0s.

using local_days = local_time<days>;

local_seconds

local_seconds is a convient way to write local_time<seconds>.

using local_seconds = local_time<std::chrono::seconds>;

last_spec

last_spec is a struct that is CopyConstructible. There exists a constexpr instance of last_spec named last. 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:
    explicit constexpr day(unsigned d) noexcept;

    day& operator++() noexcept;
    day operator++(int) noexcept;
    day& operator--() noexcept;
    day operator--(int) noexcept;

    day& operator+=(const days& d) noexcept;
    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);

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 any unsigned value, which will be subsequently truncated to fit into day's internal storage. day is equality and less-than comparable, and participates in basic arithmetic with days representing the quantity between any two day's. One can form a day literal with _d. And one can stream out a day for debugging purposes. day has explicit conversions to and from unsigned.

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 constructing d_ with d.

day& day::operator++() noexcept;

Effects: ++d_.

Returns: *this.

day day::operator++(int) noexcept;

Effects: ++(*this).

Returns: A copy of *this as it existed on entry to this member function.

day& day::operator--() noexcept;

Effects: --d_.

Returns: *this.

day day::operator--(int) noexcept;

Effects: --(*this).

Returns: A copy of *this as it existed on entry to this member function.

day& day::operator+=(const days& d) noexcept;

Effects: *this = *this + d.

Returns: *this.

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 into os. Single digit values are prefixed with '0'.

Returns: os.

month

Synopsis

class month
{
    unsigned char m_;  // exposition only
public:
    explicit constexpr month(unsigned m) noexcept;

    month& operator++() noexcept;
    month operator++(int) noexcept;
    month& operator--() noexcept;
    month operator--(int) noexcept;

    month& operator+=(const months& m) noexcept;
    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);

inline namespace literals {
constexpr month jan{1};
constexpr month feb{2};
constexpr month mar{3};
constexpr month apr{4};
constexpr month may{5};
constexpr month jun{6};
constexpr month jul{7};
constexpr month aug{8};
constexpr month sep{9};
constexpr month oct{10};
constexpr month nov{11};
constexpr month dec{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 any unsigned value, which will be subsequently truncated to fit into month's internal storage. month is equality and less-than comparable, and participates in basic arithmetic with months representing the quantity between any two month's. One can stream out a month for debugging purposes. month has explicit conversions to and from unsigned. There are 12 month 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 constructing m_ with m.

month& month::operator++() noexcept;

Effects: If m_ != 12, ++m_. Otherwise sets m_ to 1.

Returns: *this.

month month::operator++(int) noexcept;

Effects: ++(*this).

Returns: A copy of *this as it existed on entry to this member function.

month& month::operator--() noexcept;

Effects: If m_ != 1, --m_. Otherwise sets m_ to 12.

Returns: *this.

month month::operator--(int) noexcept;

Effects: --(*this).

Returns: A copy of *this as it existed on entry to this member function.

month& month::operator+=(const months& m) noexcept;

Effects: *this = *this + m.

Returns: *this.

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 which ok() == true and is found as if by incrementing (or decrementing if y < months{0}) x, y times. If month.ok() == false prior to this operation, behaves as if *this is first brought into the range [1, 12] by modular arithmetic. [Note: For example month{0} becomes month{12}, and month{13} becomes month{1}. — end note]

Complexity: O(1) with respect to the value of y. That is, repeated increments or decrements is not a valid implementation.

Example: feb + months{11} == jan.

constexpr month  operator+(const months& x, const month&  y) noexcept;

Returns: y + x.

constexpr month  operator-(const month&  x, const months& y) noexcept;

Returns: x + -y.

constexpr months operator-(const month&  x, const month&  y) noexcept;

Requires: x.ok() == true and y.ok() == true.

Returns: A value of months in the range of months{0} to months{11} inclusive.

Remarks: The returned value m shall satisfy the equality: y + m == x.

Example: jan - feb == 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 by asctime. Otherwise outputs unsigned{m} << " is not a valid month".

Returns: os.

year

Synopsis

class year
{
    short y_;  // exposition only
public:
    explicit constexpr year(int y) noexcept;

    year& operator++() noexcept;
    year operator++(int) noexcept;
    year& operator--() noexcept;
    year operator--(int) noexcept;

    year& operator+=(const years& y) noexcept;
    year& operator-=(const years& y) noexcept;

    constexpr bool is_leap() const noexcept;

    constexpr explicit operator int() const noexcept;
    constexpr bool ok() const noexcept;

    static constexpr year min() noexcept;
    static constexpr year max() noexcept;
};

constexpr bool operator==(const year& x, const year& y) noexcept;
constexpr bool operator!=(const year& x, const year& y) noexcept;
constexpr bool operator< (const year& x, const year& y) noexcept;
constexpr bool operator> (const year& x, const year& y) noexcept;
constexpr bool operator<=(const year& x, const year& y) noexcept;
constexpr bool operator>=(const year& x, const year& y) noexcept;

constexpr year  operator+(const year&  x, const years& y) noexcept;
constexpr year  operator+(const years& x, const year&  y) noexcept;
constexpr year  operator-(const year&  x, const years& y) noexcept;
constexpr years operator-(const year&  x, const year&  y) noexcept;

template<class CharT, class Traits>
std::basic_ostream<class CharT, class Traits>&
operator<<(std::basic_ostream<class CharT, class Traits>& os, const year& y);

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 any int value, which will be subsequently truncated to fit into year's internal storage. year is equality and less-than comparable, and participates in basic arithmetic with years representing the quantity between any two year's. One can form a year literal with _y. And one can stream out a year for debugging purposes. year has explicit conversions to and from int.

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 constructing y_ with y.

year& year::operator++() noexcept;

Effects: ++y_.

Returns: *this.

year year::operator++(int) noexcept;

Effects: ++(*this).

Returns: A copy of *this as it existed on entry to this member function.

year& year::operator--() noexcept;

Effects: --y_.

Returns: *this.

year year::operator--(int) noexcept;

Effects: --(*this).

Returns: A copy of *this as it existed on entry to this member function.

year& year::operator+=(const years& y) noexcept;

Effects: *this = *this + y.

Returns: *this.

year& year::operator-=(const years& y) noexcept;

Effects: *this = *this - y.

Returns: *this.

constexpr bool year::is_leap() const noexcept;

Returns: true if *this represents a leap year, else returns false.

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{std::numeric_limits<short>::min()}.

static constexpr year year::max() noexcept;

Returns: year{std::numeric_limits<short>::max()}.

constexpr bool operator==(const year& x, const year& y) noexcept;

Returns: int{x} == int{y}.

constexpr bool operator!=(const year& x, const year& y) noexcept;

Returns: !(x == y).

constexpr bool operator< (const year& x, const year& y) noexcept;

Returns: int{x} < int{y}.

constexpr bool operator> (const year& x, const year& y) noexcept;

Returns: y < x.

constexpr bool operator<=(const year& x, const year& y) noexcept;

Returns: !(y < x).

constexpr bool operator>=(const year& x, const year& y) noexcept;

Returns: !(x < y).

constexpr year  operator+(const year&  x, const years& y) noexcept;

Returns: year{int{x} + y.count()}.

constexpr year  operator+(const years& x, const year&  y) noexcept;

Returns: y + x.

constexpr year  operator-(const year&  x, const years& y) noexcept;

Returns: x + -y.

constexpr years operator-(const year&  x, const year&  y) noexcept;

Returns: years{int{x} - int{y}}.

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 into os. 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.

weekday

Synopsis

class weekday
{
    unsigned char wd_;  // exposition only
public:
    explicit constexpr weekday(unsigned wd) noexcept;
    constexpr weekday(const sys_days& dp) noexcept;
    constexpr explicit weekday(const local_days& dp) noexcept;

    weekday& operator++() noexcept;
    weekday operator++(int) noexcept;
    weekday& operator--() noexcept;
    weekday operator--(int) noexcept;

    weekday& operator+=(const days& d) noexcept;
    weekday& operator-=(const days& d) noexcept;

    constexpr explicit operator unsigned() const noexcept;
    constexpr bool ok() const noexcept;
    constexpr weekday_indexed operator[](unsigned index) const noexcept;
    constexpr weekday_last operator[](last_spec) const noexcept;
};

constexpr bool operator==(const weekday& x, const weekday& y) noexcept;
constexpr bool operator!=(const weekday& x, const weekday& y) noexcept;

constexpr weekday operator+(const weekday& x, const days&    y) noexcept;
constexpr weekday operator+(const days&    x, const weekday& y) noexcept;
constexpr weekday operator-(const weekday& x, const days&    y) noexcept;
constexpr days    operator-(const weekday& x, const weekday& y) noexcept;

template<class CharT, class Traits>
std::basic_ostream<class CharT, class Traits>&
operator<<(std::basic_ostream<class CharT, class Traits>& os, const weekday& wd);

inline namespace literals {
constexpr weekday sun{0};
constexpr weekday mon{1};
constexpr weekday tue{2};
constexpr weekday wed{3};
constexpr weekday thu{4};
constexpr weekday fri{5};
constexpr weekday sat{6};
}

Overview

weekday represents a day of the week in the Gregorian calendar. It should only be representing values in the range 0 to 6, corresponding to Sunday thru Saturday. However it may hold values outside this range. It can be constructed with any unsigned value, which will be subsequently truncated to fit into weekday's internal storage. weekday is equality comparable. weekday is not less-than comparable because there is no universal consensus on which day is the first day of the week. This design chooses the encoding of 0 to 6 to represent Sunday thru Saturday only because this is consistent with existing C and C++ practice. However weekday's comparison and arithmetic operations treat the days of the week as a circular range, with no beginning and no end. One can stream out a weekday for debugging purposes. weekday has explicit conversions to and from unsigned. There are 7 weekday constants, one for each day of the week.

A weekday can be implicitly constructed from a sys_days. This is the computation that discovers the day of the week of an arbitrary date.

A weekday can be indexed with either unsigned or last. This produces new types which represent the first, second, third, fourth, fifth or last weekdays of a month.

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 by constructing wd_ with wd.

constexpr weekday(const sys_days& dp) noexcept;

Effects: Constructs an object of type weekday by computing what day of the week corresponds to the sys_days dp, and representing that day of the week in wd_.

Example: If dp represents 1970-01-01, the constructed weekday shall represent Thursday by storing 4 in wd_.

constexpr explicit weekday(const local_days& dp) noexcept;

Effects: Constructs an object of type weekday by computing what day of the week corresponds to the local_days dp, and representing that day of the week in wd_.

The value after construction shall be identical to that constructed from sys_days{dp.time_since_epoch()}.

weekday& weekday::operator++() noexcept;

Effects: If wd_ != 6, ++wd_. Otherwise sets wd_ to 0.

Returns: *this.

weekday weekday::operator++(int) noexcept;

Effects: ++(*this).

Returns: A copy of *this as it existed on entry to this member function.

weekday& weekday::operator--() noexcept;

Effects: If wd_ != 0, --wd_. Otherwise sets wd_ to 6.

Returns: *this.

weekday weekday::operator--(int) noexcept;

Effects: --(*this).

Returns: A copy of *this as it existed on entry to this member function.

weekday& weekday::operator+=(const days& d) noexcept;

Effects: *this = *this + d.

Returns: *this.

weekday& weekday::operator-=(const days& d) noexcept;

Effects: *this = *this - d.

Returns: *this.

constexpr explicit weekday::operator unsigned() const noexcept;

Returns: wd_.

constexpr bool weekday::ok() const noexcept;

Returns: wd_ <= 6.

constexpr weekday_indexed weekday::operator[](unsigned index) const noexcept;

Returns: {*this, index}.

constexpr weekday_last weekday::operator[](last_spec) const noexcept;

Returns: weekday_last{*this}.

constexpr bool operator==(const weekday& x, const weekday& y) noexcept;

Returns: unsigned{x} == unsigned{y}.

constexpr bool operator!=(const weekday& x, const weekday& y) noexcept;

Returns: !(x == y).

constexpr weekday  operator+(const weekday&  x, const days& y) noexcept;

Returns: A weekday for which ok() == true and is found as if by incrementing (or decrementing if y < days{0}) x, y times. If weekday.ok() == false prior to this operation, behaves as if *this is first brought into the range [0, 6] by modular arithmetic. [Note: For example weekday{7} becomes weekday{0}. — end note]

Complexity: O(1) with respect to the value of y. That is, repeated increments or decrements is not a valid implementation.

Example: mon + days{6} == sun.

constexpr weekday  operator+(const days& x, const weekday&  y) noexcept;

Returns: y + x.

constexpr weekday  operator-(const weekday&  x, const days& y) noexcept;

Returns: x + -y.

constexpr days operator-(const weekday&  x, const weekday&  y) noexcept;

Requires: x.ok() == true and y.ok() == true.

Returns: A value of days in the range of days{0} to days{6} inclusive.

Remarks: The returned value d shall satisfy the equality: y + d == x.

Example: sun - mon == 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 by asctime. Otherwise outputs unsigned{wd} << " is not a valid weekday".

Returns: os.

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 a weekday and a small index in the range 1 to 5. This class is used to represent the first, second, third, fourth or fifth weekday of a month. It is most easily constructed by indexing a weekday.

[Example:

constexpr auto wdi = sun[2];  // wdi is the second Sunday of an as yet unspecified month
static_assert(wdi.weekday() == sun);
static_assert(wdi.index() == 2);

end example:]

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 constructing wd_ with wd and index_ with index.

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 last weekday of a month. It is most easily constructed by indexing a weekday with last.

[Example:

constexpr auto wdl = sun[last];  // wdl is the last Sunday of an as yet unspecified month
static_assert(wdl.weekday() == sun);

end example:]

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 constructing wd_ with wd.

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:
    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);

Overview

month_day represents a specific day of a specific month, but with an unspecified year. One can observe the different components. One can assign a new value. month_day is equality comparable and less-than comparable. One can stream out a month_day 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 constructing m_ with m, and d_ with d.

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 if m_.ok() is true, and if 1_d <= d_, and if d_ <= the number of days in month m_. For m_ == feb the number of days is considered to be 29. Otherwise returns false.

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() returns true. Else if x.month() > y.month() returns false. Else returns x.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.

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 last day of a month. It is most easily constructed using the expression m/last or last/m, where m is an expression with type month.

[Example:

constexpr auto mdl = feb/last;  // mdl is the last day of February of an as yet unspecified year
static_assert(mdl.month() == feb);

end example:]

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 constructing m_ with m.

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 nth weekday of a month, of an as yet unspecified year. To do this the month_weekday stores a month and a weekday_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 constructing m_ with m, and wdi_ with wdi.

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 last weekday of a month, of an as yet unspecified year. To do this the month_weekday_last stores a month and a weekday_last.

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 constructing m_ with m, and wdl_ with wdl.

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:
    constexpr year_month(const date::year& y, const date::month& m) noexcept;

    constexpr date::year year() const noexcept;
    constexpr date::month month() const noexcept;

    year_month& operator+=(const months& dm) noexcept;
    year_month& operator-=(const months& dm) noexcept;
    year_month& operator+=(const years& dy) noexcept;
    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);

Overview

year_month represents a specific month of a specific year, but with an unspecified day. year_month is a field-based time point with a resolution of months. One can observe the different components. One can assign a new value. year_month is equality comparable and less-than comparable. One can stream out a year_month 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 constructing y_ with y, and m_ with m.

constexpr year year_month::year() const noexcept;

Returns: y_.

constexpr month year_month::month() const noexcept;

Returns: m_.

year_month& operator+=(const months& dm) noexcept;

Effects: *this = *this + dm.

Returns: *this.

year_month& operator-=(const months& dm) noexcept;

Effects: *this = *this - dm.

Returns: *this.

year_month& operator+=(const years& dy) noexcept;

Effects: *this = *this + dy.

Returns: *this.

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() returns true. Else if x.year() > y.year() returns false. Else returns x.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 value z such that z - 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 to y to get x.

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.

year_month_day

Synopsis

class year_month_day
{
    date::year  y_;  // exposition only
    date::month m_;  // exposition only
    date::day   d_;  // exposition only

public:
    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;

    year_month_day& operator+=(const months& m) noexcept;
    year_month_day& operator-=(const months& m) noexcept;
    year_month_day& operator+=(const years& y) noexcept;
    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);

Overview

year_month_day represents a specific year, month, and day. year_month_day is a field-based time point with a resolution of days. One can observe each field. year_month_day supports years and months oriented arithmetic, but not days oriented arithmetic. For the latter, there is a conversion to sys_days which efficiently supports days oriented arithmetic. There is also a conversion from sys_days. year_month_day is equality and less-than comparable.

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 constructing y_ with y, m_ with m, and, d_ with d.

constexpr year_month_day::year_month_day(const year_month_day_last& ymdl) noexcept;

Effects: Constructs an object of type year_month_day by constructing y_ with ymdl.year(), m_ with ymdl.month(), and, d_ with ymdl.day().

Note: This conversion from year_month_day_last to year_month_day is more efficient than converting a year_month_day_last to a sys_days, and then converting that sys_days to a year_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 by dp.

Remarks: For any value of year_month_day, ymd, for which ymd.ok() is true, this equality will also be true: 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 by dp.

Remarks: Equivalent to constructing with sys_days{dp.time_since_epoch()}.

year_month_day& year_month_day::operator+=(const months& m) noexcept;

Effects: *this = *this + m;.

Returns: *this.

year_month_day& year_month_day::operator-=(const months& m) noexcept;

Effects: *this = *this - m;.

Returns: *this.

year_month_day& year_month_day::operator+=(const years& y) noexcept;

Effects: *this = *this + y;.

Returns: *this.

year_month_day& year_month_day::operator-=(const years& y) noexcept;

Effects: *this = *this - y;.

Returns: *this.

constexpr year year_month_day::year() const noexcept;

Returns: y_.

constexpr month year_month_day::month() const noexcept;

Returns: m_.

constexpr day year_month_day::day() const noexcept;

Returns: d_.

constexpr year_month_day::operator sys_days() const noexcept;

Requires: ok() == true.

Returns: A sys_days which represents the date represented by *this.

Remarks: A sys_days which is converted to a year_month_day, shall have the same value when converted back to a sys_days. The round trip conversion sequence shall be loss-less.

constexpr explicit year_month_day::operator local_days() const noexcept;

Requires: ok() == true.

Returns: A local_days which represents the date represented by *this.

Remarks: Shall return a value equivalent to local_days{static_cast<sys_days>(*this).time_since_epoch()}.

constexpr bool year_month_day::ok() const noexcept;

Returns: If y_.ok() is true, and m_.ok() is true, and d_ is in the range [1_d, (y_/m_/last).day()], then returns true, else returns false.

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(), returns true. Else if x.year() > y.year() returns false. Else if x.month() < y.month(), returns true. Else if x.month() > y.month(), returns false. Else returns x.day() < y.day().

constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept;

Returns: y < x.

constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept;

Returns: !(y < x).

constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept;

Returns: !(x < y).

constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;

Requires: ymd.month().ok() is true.

Returns: (ymd.year() / ymd.month() + dm) / ymd.day().

Remarks: If ymd.day() is in the range [1_d, 28_d], the resultant year_month_day is guaranteed to return true from ok().

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() is feb and ymd.day() is not in the range [1_d, 28_d], the resultant year_month_day is not guaranteed to return true from ok().

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.

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;

    year_month_day_last& operator+=(const months& m) noexcept;
    year_month_day_last& operator-=(const months& m) noexcept;
    year_month_day_last& operator+=(const years& y) noexcept;
    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 specific year, month, and the last day of the month. year_month_day_last is a field-based time point with a resolution of days, except that it is restricted to pointing to the last day of a year and month. One can observe each field. The day field is computed on demand. year_month_day_last supports years and months oriented arithmetic, but not days oriented arithmetic. For the latter, there is a conversion to sys_days which efficiently supports days oriented arithmetic. year_month_day_last is equality and less-than comparable.

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 constructing y_ with y and mdl_ with mdl.

year_month_day_last& year_month_day_last::operator+=(const months& m) noexcept;

Effects: *this = *this + m;.

Returns: *this.

year_month_day_last& year_month_day_last::operator-=(const months& m) noexcept;

Effects: *this = *this - m;.

Returns: *this.

year_month_day_last& year_month_day_last::operator+=(const years& y) noexcept;

Effects: *this = *this + y;.

Returns: *this.

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 the year, month pair represented by *this.

constexpr year_month_day_last::operator sys_days() const noexcept;

Requires: ok() == true.

Returns: A sys_days which represents the date represented by *this.

constexpr explicit year_month_day_last::operator local_days() const noexcept;

Requires: ok() == true.

Returns: A local_days which represents the date represented by *this.

Remarks: Shall return a value equivalent to local_days{static_cast<sys_days>(*this).time_since_epoch()}.

constexpr bool year_month_day_last::ok() const noexcept;

Returns: y_.ok() && mdl_.ok().

constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept;

Returns: x.year() == y.year() && x.month_day_last() == y.month_day_last().

constexpr bool operator!=(const year_month_day_last& x, const year_month_day_last& y) noexcept;

Returns: !(x == y).

constexpr bool operator< (const year_month_day_last& x, const year_month_day_last& y) noexcept;

Returns: If x.year() < y.year(), returns true. Else if x.year() > y.year() returns false. Else returns 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: y < x.

constexpr bool operator<=(const year_month_day_last& x, const year_month_day_last& y) noexcept;

Returns: !(y < x).

constexpr bool operator>=(const year_month_day_last& x, const year_month_day_last& y) noexcept;

Returns: !(x < y).

constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept;

Requires: ymdl.ok() is true.

Returns: (ymdl.year() / ymdl.month() + dm) / last.

Postconditions: The resultant year_month_day_last will return true from ok().

Complexity: O(1) with respect to the value of dm.

constexpr year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) noexcept;

Returns: ymdl + dm.

constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) noexcept;

Returns: ymdl + (-dm).

constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) noexcept;

Returns: {ymdl.year()+dy, ymdl.month_day_last()}.

constexpr year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) noexcept;

Returns: ymdl + dy.

constexpr year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) noexcept;

Returns: ymdl + (-dy).

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:
    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;

    year_month_weekday& operator+=(const months& m) noexcept;
    year_month_weekday& operator-=(const months& m) noexcept;
    year_month_weekday& operator+=(const years& y) noexcept;
    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 specific year, month, and nth weekday of the month. year_month_weekday is a field-based time point with a resolution of days. One can observe each field. year_month_weekday supports years and months oriented arithmetic, but not days oriented arithmetic. For the latter, there is a conversion to sys_days which efficiently supports days oriented arithmetic. year_month_weekday is equality comparable.

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 constructing y_ with y, m_ with m, and wdi_ with wdi.

constexpr year_month_weekday(const sys_days& dp) noexcept;

Effects: Constructs an object of type year_month_weekday which corresponds to the date represented by dp.

Remarks: For any value of year_month_weekday, ymdl, for which ymdl.ok() is true, this equality will also be true: 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 by dp.

Remarks: Equivalent to constructing with sys_days{dp.time_since_epoch()}.

year_month_weekday& year_month_weekday::operator+=(const months& m) noexcept;

Effects: *this = *this + m;.

Returns: *this.

year_month_weekday& year_month_weekday::operator-=(const months& m) noexcept;

Effects: *this = *this - m;.

Returns: *this.

year_month_weekday& year_month_weekday::operator+=(const years& y) noexcept;

Effects: *this = *this + y;.

Returns: *this.

year_month_weekday& year_month_weekday::operator-=(const years& y) noexcept;

Effects: *this = *this - y;.

Returns: *this.

constexpr year year_month_weekday::year() const noexcept;

Returns: y_.

constexpr month year_month_weekday::month() const noexcept;

Returns: m_.

constexpr weekday year_month_weekday::weekday() const noexcept;

Returns: wdi_.weekday().

constexpr unsigned year_month_weekday::index() const noexcept;

Returns: wdi_.index().

constexpr weekday_indexed year_month_weekday::weekday_indexed() const noexcept;

Returns: wdi_.

constexpr year_month_weekday::operator sys_days() const noexcept;

Requires: ok() == true.

Returns: A sys_days which represents the date represented by *this.

constexpr explicit year_month_weekday::operator local_days() const noexcept;

Requires: ok() == true.

Returns: A local_days which represents the date represented by *this.

Remarks: Shall return a value equivalent to local_days{static_cast<sys_days>(*this).time_since_epoch()}.

constexpr bool year_month_weekday::ok() const noexcept;

Returns: If y_.ok() or m_.ok() or wdi_.ok() returns false, returns false. Else if *this represents a valid date, returns true, else returns false.

constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept;

Returns: x.year() == y.year() && x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed().

constexpr bool operator!=(const year_month_weekday& x, const year_month_weekday& y) noexcept;

Returns: !(x == y).

constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept;

Requires: ymwd.ok() is true.

Returns: (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed().

Postconditions: The resultant year_month_weekday will return true from ok().

Complexity: O(1) with respect to the value of dm.

constexpr year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) noexcept;

Returns: ymwd + dm.

constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) noexcept;

Returns: ymwd + (-dm).

constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) noexcept;

Returns: {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}.

constexpr year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) noexcept;

Returns: ymwd + dm.

constexpr year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) noexcept;

Returns: ymwd + (-dm).

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;

    year_month_weekday_last& operator+=(const months& m) noexcept;
    year_month_weekday_last& operator-=(const months& m) noexcept;
    year_month_weekday_last& operator+=(const years& y) noexcept;
    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 specific year, month, and last weekday of the month. year_month_weekday_last is a field-based time point with a resolution of days, except that it is restricted to pointing to the last weekday of a year and month. One can observe each field. year_month_weekday_last supports years and months oriented arithmetic, but not days oriented arithmetic. For the latter, there is a conversion to sys_days which efficiently supports days oriented arithmetic. year_month_weekday_last is equality comparable.

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 constructing y_ with y, m_ with m, and wdl_ with wdl.

year_month_weekday_last& year_month_weekday_last::operator+=(const months& m) noexcept;

Effects: *this = *this + m;.

Returns: *this.

year_month_weekday_last& year_month_weekday_last::operator-=(const months& m) noexcept;

Effects: *this = *this - m;.

Returns: *this.

year_month_weekday_last& year_month_weekday_last::operator+=(const years& y) noexcept;

Effects: *this = *this + y;.

Returns: *this.

year_month_weekday_last& year_month_weekday_last::operator-=(const years& y) noexcept;

Effects: *this = *this - y;.

Returns: *this.

constexpr year year_month_weekday_last::year() const noexcept;

Returns: y_.

constexpr month year_month_weekday_last::month() const noexcept;

Returns: m_.

constexpr weekday year_month_weekday_last::weekday() const noexcept;

Returns: wdl_.weekday().

constexpr weekday_last year_month_weekday_last::weekday_last() const noexcept;

Returns: wdl_.

constexpr year_month_weekday_last::operator sys_days() const noexcept;

Requires: ok() == true.

Returns: A sys_days which represents the date represented by *this.

constexpr explicit year_month_weekday_last::operator local_days() const noexcept;

Requires: ok() == true.

Returns: A local_days which represents the date represented by *this.

Remarks: Shall return a value equivalent to local_days{static_cast<sys_days>(*this).time_since_epoch()}.

constexpr bool year_month_weekday_last::ok() const noexcept;

Returns: If y_.ok() && m_.ok() && wdl_.ok().

constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;

Returns: x.year() == y.year() && x.month() == y.month() && x.weekday_last() == y.weekday_last().

constexpr bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept;

Returns: !(x == y).

constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept;

Requires: ymwdl.ok() is true.

Returns: (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last().

Postconditions: The resultant year_month_weekday_last will return true from ok().

Complexity: O(1) with respect to the value of dm.

constexpr year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept;

Returns: ymwdl + dm.

constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) noexcept;

Returns: ymwdl + (-dm).

constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept;

Returns: {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}.

constexpr year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept;

Returns: ymwdl + dy.

constexpr year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) noexcept;

Returns: ymwdl + (-dy).

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.

date composition operators

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:

  1. y/m/d
  2. m/d/y
  3. 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:

Sub-field-types such as year_month and month_day can be created by simply not applying the second division operator for any of the three orders. For example:

year_month ym = 2015_y/apr;
month_day md1 = apr/4;
month_day md2 = 4_d/apr;

Everything not intended as above is caught as a compile-time error, with the notable exception of an expression that consists of nothing but int, which of course has type int.

auto a = 2015/4/4;       // a == int(125)
auto b = 2015_y/4/4;     // b == year_month_day{year(2015), month(4), day(4)}
auto c = 2015_y/4_d/apr; // error: invalid operands to binary expression ('date::year' and 'date::day')
auto d = 2015/apr/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 a year or a day. 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 a std::chrono::duration which represents the time elapsed since midnight, into a "broken" down time such as hours:minutes:seconds. The Duration template parameter dictates the precision to which the time is broken down. This can vary from a course precision of hours to a very fine precision of nanoseconds.

There are 4 specializations of time_of_day to handle four precisions:

  1. time_of_day<std::chrono::hours>
    

    This specialization handles hours since midnight.

  2. time_of_day<std::chrono::minutes>
    

    This specialization handles hours:minutes since midnight.

  3. time_of_day<std::chrono::seconds>
    

    This specialization handles hours:minutes:seconds since midnight.

  4. time_of_day<std::chrono::duration<Rep, Period>>
    

    This specialization is restricted to Periods that are shorter than 1 second. 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 of time_of_day is a standard-layout class type.
Each specialization of time_of_day is a literal class type.

time_of_day<std::chrono::hours>
{
public:
    using precision = std::chrono::hours;

    constexpr explicit time_of_day(std::chrono::hours since_midnight) noexcept;
    constexpr time_of_day(std::chrono::hours h, unsigned md) 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 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 to since_midnight hours after 00:00:00.

Postconditions: hours() returns the integral number of hours since_midnight is after 00:00:00. mode() returns 0.

constexpr time_of_day<std::chrono::hours>::time_of_day(std::chrono::hours h, unsigned md) noexcept;

Preconditions: md == am or md == pm.

Effects: Constructs an object of type time_of_day in 12-hour format corresponding to h hours after 00:00:00.

Postconditions: hours() returns h, and mode() returns md.

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 returns am or pm 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 to os according to the strftime format: "%H00". "%H" will emit a leading 0 for hours less than 10. Else t is a 12-hour time, outputs to os according to the strftime format: "%I%p" according to the C locale, except that no leading zero is output for hours less than 10.

Returns: os.

Example:

0100  // 1 in the morning in 24-hour format
1800  // 6 in the evening in 24-hour format
1am   // 1 in the morning in 12-hour format
6pm   // 6 in the evening in 12-hour format
time_of_day<std::chrono::minutes>
{
public:
    using precision = std::chrono::minutes;

    constexpr explicit time_of_day(std::chrono::minutes since_midnight) noexcept;
    constexpr time_of_day(std::chrono::hours h, std::chrono::minutes m,
                          unsigned md) 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 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 to since_midnight minutes after 00:00:00.

Postconditions: hours() returns the integral number of hours since_midnight is after 00:00:00. minutes() returns the integral number of minutes since_midnight is after (00:00:00 + hours()). mode() returns 0.

constexpr time_of_day<std::chrono::minutes>::time_of_day(std::chrono::hours h, std::chrono::minutes m,
                                                               unsigned md) noexcept;

Preconditions: md == am or md == pm.

Effects: Constructs an object of type time_of_day in 12-hour format corresponding to h hours and m minutes after 00:00:00.

Postconditions: hours() returns h, minutes() returns m, and mode() returns md.

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 returns am or pm 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 to os according to the strftime format: "%H:%M". "%H" will emit a leading 0 for hours less than 10. Else t is a 12-hour time, outputs to os according to the strftime format: "%I:%M%p" according to the C locale, except that no leading zero is output for hours less than 10.

Returns: os.

Example:

01:08   // 1:08 in the morning in 24-hour format
18:15   // 6:15 in the evening in 24-hour format
1:08am  // 1:08 in the morning in 12-hour format
6:15pm  // 6:15 in the evening in 12-hour format
time_of_day<std::chrono::seconds>
{
public:
    using precision = std::chrono::seconds;

    constexpr explicit time_of_day(std::chrono::seconds since_midnight) noexcept;
    constexpr time_of_day(std::chrono::hours h, std::chrono::minutes m,
                          std::chrono::seconds s, unsigned md) 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 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 to since_midnight seconds after 00:00:00.

Postconditions: hours() returns the integral number of hours since_midnight is after 00:00:00. minutes() returns the integral number of minutes since_midnight is after (00:00:00 + hours()). seconds() returns the integral number of seconds since_midnight is after (00:00:00 + hours() + minutes()). mode() returns 0.

constexpr time_of_day<std::chrono::seconds>::time_of_day(std::chrono::hours h, std::chrono::minutes m,
                                                               std::chrono::seconds s, unsigned md) noexcept;

Preconditions: md == am or md == pm.

Effects: Constructs an object of type time_of_day in 12-hour format corresponding to h hours, m minutes, and s seconds after 00:00:00.

Postconditions: hours() returns h. minutes() returns m. seconds() returns s. mode() returns md.

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 returns am or pm 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 to os according to the strftime format: "%H:%M%S". "%H" will emit a leading 0 for hours less than 10. Else t is a 12-hour time, outputs to os according to the strftime format: "%I:%M%S%p" according to the C locale, except that no leading zero is output for hours less than 10.

Returns: os.

Example:

01:08:03   // 1:08:03 in the morning in 24-hour format
18:15:45   // 6:15:45 in the evening in 24-hour format
1:08:03am  // 1:08:03 in the morning in 12-hour format
6:15:45pm  // 6:15:45 in the evening in 12-hour format
time_of_day<std::chrono::duration<Rep, Period>>
{
public:
    using precision = std::chrono::duration<Rep, Period>;

    constexpr explicit time_of_day(precision since_midnight) noexcept;
    constexpr time_of_day(std::chrono::hours h, std::chrono::minutes m,
                          std::chrono::seconds s, precision sub_s, unsigned md) 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 explicit time_of_day<std::chrono::duration<Rep, Period>>::time_of_day(precision since_midnight) noexcept;

Effects: Constructs an object of type time_of_day in 24-hour format corresponding to since_midnight precision fractional seconds after 00:00:00.

Postconditions: hours() returns the integral number of hours since_midnight is after 00:00:00. minutes() returns the integral number of minutes since_midnight is after (00:00:00 + hours()). seconds() returns the integral number of seconds since_midnight is after (00:00:00 + hours() + minutes()). subseconds() returns the integral number of fractional precision seconds since_midnight is after (00:00:00 + hours() + minutes() + seconds). mode() returns 0.

constexpr time_of_day<std::chrono::duration<Rep, Period>>::time_of_day(std::chrono::hours h, std::chrono::minutes m,
                                                                       std::chrono::seconds s, precision sub_s,
                                                                       unsigned md) noexcept;

Preconditions: md == am or md == pm.

Effects: Constructs an object of type time_of_day in 12-hour format corresponding to h hours, m minutes, and s + sub_s seconds after 00:00:00.

Postconditions: hours() returns h. minutes() returns m. seconds() returns s. subseconds() returns sub_s. mode() returns md.

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 returns am or pm 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 to os according to the strftime format: "%H:%M%S.%s". "%H" will emit a leading 0 for hours less than 10. "%s" is not a strftime code and represents the fractional seconds. Else t is a 12-hour time, outputs to os according to the strftime 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).

constexpr
time_of_day<std::chrono::hours>
make_time(std::chrono::hours h, unsigned md) noexcept;

Returns: time_of_day<std::chrono::hours>(h, md).

constexpr
time_of_day<std::chrono::minutes>
make_time(std::chrono::hours h, std::chrono::minutes m, unsigned md) noexcept;

Returns: time_of_day<std::chrono::minutes>(h, m, md).

constexpr
time_of_day<std::chrono::seconds>
make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
          unsigned md) noexcept;

Returns: time_of_day<std::chrono::seconds>(h, m, s, md).

template <class Rep, class Period,
          class = std::enable_if_t<std::ratio_less<Period, std::ratio<1>>::value>>
constexpr
time_of_day<std::chrono::duration<Rep, Period>>
make_time(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s,
          std::chrono::duration<Rep, Period> sub_s, unsigned md) noexcept

Returns: time_of_day<std::chrono::duration<Rep, Period>>(h, m, s, sub_s, md).

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.