<html>
<head><title>P0034 &ndash; Civil Time</title></head>
<body>
<table border=0>
<tr>
  <td><b>Doc No:</b></td>
  <td>P0034</td>
</tr>
<tr>
  <td><b>Date:</b></td>
  <td>2015-09-25</td>
</tr>
<tr>
  <td><b>Reply to:</b>&nbsp;</td>
  <td>Bill Seymour &lt;stdbill<tt>.</tt>h<sup>@</sup>pobox<tt>.</tt>com&gt;</td>
</tr>
</table>
<p>
<center>
<h2>Civil Time for the Standard Library</h2>
<h3>Bill Seymour<br>2015-09-25</h3>
</center>

<p><hr>
<h3>Abstract:</h3>

This paper asks, what&rsquo;s your interest in adding to the standard library
classes that support civil time beyond what <tt>&lt;ctime&gt;</tt> provides?

<p>The <a href="http://www.boost.org/doc/libs/1_59_0/doc/html/date_time.html">Boost.Date_Time</a>
library would certainly do the trick; but it&rsquo;s really huge; and this writer
isn&rsquo;t aware of any interest in accepting it into the standard library.

<p>This paper suggests a simpler design that just does the basics.
In particular, it assumes that we won&rsquo;t need to deal with any
pre-Gregorian-calendar dates, or even any <nobr><tt>time_t</tt>-overflow</nobr>
dates; and although we might want sub-second
<i>resolution</i> (for example, to handle SQL <tt>TIMESTAMP</tt>s),
we won&rsquo;t really need the kind of <i>accuracy</i> that requires
handling leap seconds any better than <tt>time_t</tt> does.

<p>If something like Boost.Date_Time does make its way into the
standard library, this proposal will be withdrawn.

<p><b>Issue:</b>&nbsp;&nbsp;Although this paper shows <tt>operator</tt>&nbsp;<tt>""</tt>
literals for several types because they might be convenient for users,
we might not want them anyway since they wouldn&rsquo;t be <tt>constexpr</tt>
(unless we require the compiler to have in it a parser for all the various
<a href="https://en.wikipedia.org/wiki/ISO_8601">ISO&nbsp;8601</a> formats
plus the additional forms that this paper requires).

<p><hr>
<h3>Overview:</h3>

<p><b><tt>class duration;</tt></b>
<blockquote>
This is a signed amount of time with microsecond resolution.  It supports all the usual
integer arithmetic.  Other <tt>duration</tt>s can be added to it or subtracted from it;
it can be multiplied and divided by <nobr><tt>long</tt>&nbsp;<tt>long</tt>s;</nobr>
and the quotient of two <tt>duration</tt>s is a <nobr><tt>long</tt>&nbsp;<tt>long</tt>.</nobr>
</blockquote>

<p><b><tt>class time_of_day;</tt></b>
<blockquote>
This is an unsigned amount of time after midnight.
It&rsquo;s like a <tt>duration</tt>, but restricted to the half-open interval,
<nobr>[midnight, midnight +1 day).</nobr>
Users may select whether it saturates or modwraps.
It does not understand leap seconds,
and cannot since it&rsquo;s not associated with any particular day.
A pure-number multiplier or divisor, and the quotient of two
<tt>time_of_day</tt>s, is an <tt>unsigned</tt>&nbsp;<tt>long</tt>,
not a <tt>long</tt>&nbsp;<tt>long</tt>.
</blockquote>

<p>Objects of the <tt>duration</tt> and <tt>time_of_day</tt> types
can freely interact arithmetically.

<p><b><tt>class month_count;</tt></b>
<blockquote>
This is a signed number of months.  Objects of this type cannot interact
arithmetically with <tt>duration</tt>s or <tt>time_of_day</tt>s; but
<tt>month_count</tt>s can be added and subtracted; they can be multiplied
and divided by <tt>int</tt>s; and the quotient of two <tt>month_count</tt>s
is an <tt>int</tt>.
</blockquote>

<p><b><tt>class datetime;</tt></b>
<blockquote>
This is a point in time in a particular time zone.  <tt>duration</tt>s, <tt>time_of_day</tt>s, and
<tt>month_count</tt>s can be added to it and subtracted from it; but this
class provides no multiplicative arithmetic.  The difference
between two <tt>datetime</tt>s is a <tt>duration</tt>. <tt>datetime</tt>s
can be explicitly converted to and from <tt>time_t</tt> and
<nobr><tt>struct</tt>&nbsp;<tt>tm</tt>.</nobr>
</blockquote>

<p><b><tt>class timezone;</tt></b>
<blockquote>
This class has member functions that return <tt>duration</tt>s that are
offsets from UTC, <tt>bool</tt>s that indicate whether daylight saving
time is in effect, and <tt>string</tt>s that contain the customary
abbreviations for the time zone name (e.g., <tt>"CST"</tt>).  The return
values can reflect the local wall clock time or a particular <tt>datetime</tt>.

<p>As specified in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO&nbsp;8601</a>,
Eastern-hemisphere time zones have positive offsets.

<p>A <tt>timezone</tt> can be constructed from a POSIX string like
<tt>"CST6CDT"</tt>, an ISO&nbsp;8601 time zone specifier, or optionally
(if the implementation supports the Olson zoneinfo database),
a name like <tt>"America/Chicago"</tt>.
There&rsquo;s also a default constructor that constructs the local time zone;
but the local time zone also exists as a constant at namespace scope,
so the user never needs to explicitly construct it.
</blockquote>

<p>There are also some obvious <tt>constexpr</tt> values (e.g., <tt>secs_per_day</tt>)
at namespace scope.  They&rsquo;re intended to help with avoiding magic numbers.

<p>I/O is comming Real Soon Now, probably involving extensions
to the existing <tt>time_get</tt> and <tt>time_put</tt> facets.

<p>The library provides no <nobr><tt>clock()</tt>-related</nobr>
interface:&nbsp;&nbsp;the <tt>&lt;chrono&gt;</tt>
library is a better choice for that.

<p><hr>
<h3>Synopsis:</h3>

<table><tr><td bgcolor=lightgrey>
For brevity herein, constructors that take string arguments
and the <tt>operator</tt>&nbsp;<tt>""</tt> literals are shown
only in <tt>const</tt>&nbsp;<tt>char*</tt> form.  You may assume
that all the standard character and string types are required as well.
</td></tr></table>

<pre>
namespace std {
namespace experimental {
namespace civiltime {

class duration;
class time_of_day;
class month_count;
class datetime;
class timezone;

//
// Most of the types in the library will have microsecond resolution
// so that they can map to third-party types that do (e.g., various
// SQL types that hold dates and times).
//
typedef long long microsecs;

//
// Some interesting constants:
//

constexpr int months_per_year = 12;

constexpr long hours_per_day = 24L;
constexpr long mins_per_hour = 60L;
constexpr long secs_per_min  = 60L;

constexpr long mins_per_day  = hours_per_day * mins_per_hour;
constexpr long secs_per_day  = mins_per_day  * secs_per_min;
constexpr long secs_per_hour = mins_per_hour * secs_per_min;

constexpr long usecs_per_sec = 1000000L;

//
// Note that the only requirements on the time_t type are that it be
// an arithmetic type and that it &ldquo;holds a time&rdquo;, whatever that means.
//
extern const long usecs_per_time_t_tick;

//
// A duration is a signed amount of time with microsecond resolution.
// It can be constructed from, and broken down into, days, hours,
// minutes, seconds, and microseconds, but not into years or months.
//
class duration
{
public:
    static constexpr duration one_day;
    static constexpr duration one_hour;
    static constexpr duration one_minute;
    static constexpr duration one_second;
    static constexpr duration zero;

    explicit constexpr duration(microsecs = 0LL) noexcept;

    duration(int hours,
             int minutes,
             int seconds = 0,
             long microseconds = 0L) noexcept;

    duration(int days,
             int hours,
             int minutes,
             int seconds,
             long microseconds) noexcept;

    //
    // Construct from an optional sign ('+', '-', U+2212) followed by:
    //   - an ISO 8601 duration without years or months
    //   - an ISO 8601 time interval
    //   - a string like "hh:mm:ss"
    //   - a string like "dd;hh:mm:ss" (the day separator is a semicolon,
    //     not a colon)
    //
    // In all forms, the seconds may contain a decimal point
    // and up to six decimal digits; and less significant fields
    // (along with their leading separators) are optional, except
    // that the semicolon is always required in the fourth form,
    // even to specify just a number of days.
    //
    explicit duration(const char*);

    //
    // We&rsquo;d like to construct a duration from a time_t; but we can&rsquo;t
    // write such a constructor because a time_t might be just a
    // typedef for a long long; and if it is, the unit is probably
    // seconds, not microseconds.  Here&rsquo;s a convenience function
    // that lets us write, e.g., duration(from_tt(<i>my_time_t</i>));
    //
    static microsecs from_tt(std::time_t) noexcept;

    //
    // The above isn&rsquo;t a problem for a struct tm; but we&rsquo;ll provide
    // the same mechanism since that seems to support the principle
    // of least astonishment (because tm is another &lt;ctime&gt; type
    // and so could reasonably be handled in some parallel way).
    //
    // The following function has the side effect of calling std::mktime(),
    // which is why the argument is a pointer to <i>non-const</i> tm.
    //
    static microsecs from_tm(std::tm*);
    // and for the user&rsquo;s convenience:
    static microsecs from_tm(std::tm&amp; tmref) { return from_tm(&amp;tmref); }

    //
    // The author imagines that the internal represention could be
    // just a long long or other fundamental type, so there&rsquo;s no need
    // for move semantics or swap.  Implementors could certainly add
    // them; but they shouldn&rsquo;t be required.
    //

    duration(const duration&amp;) = default;
    duration&amp; operator=(const duration&amp;) = default;

    ~duration() = default;

    //
    // Observers:
    //

    microsecs total_microsecs() const noexcept;

    struct breakdown
    {
        int days, hours, minutes, seconds;
        long microseconds;
    };
    explicit operator breakdown() const noexcept;

    //
    // Unary + and - return copies:
    //
    duration operator+() const noexcept;
    duration operator-() const noexcept;

    //
    // The prefix and postfix increment and decrement operators
    // add and subtract whole seconds, not microseconds:
    //
    duration&amp; operator++() noexcept;
    duration&amp; operator--() noexcept;
    duration  operator++(int) noexcept;
    duration  operator--(int) noexcept;

    //
    // Other durations and time_of_days can be added and subtracted:
    //
    duration&amp; operator+=(const duration&amp;) noexcept;
    duration&amp; operator-=(const duration&amp;) noexcept;
    duration&amp; operator+=(const time_of_day&amp;) noexcept;
    duration&amp; operator-=(const time_of_day&amp;) noexcept;

    //
    // durations can be multiplied and divided by pure numbers:
    //
    duration&amp; operator*=(long long) noexcept;
    duration&amp; operator/=(long long) noexcept;

    //
    // The usual integer remainder operations:
    //
    duration&amp; operator%=(long long) noexcept;
    duration&amp; operator%=(const duration&amp;) noexcept;
    duration&amp; operator%=(const time_of_day&amp;) noexcept;

    //
    // Comparisons:
    //

    bool operator==(const duration&amp;) const noexcept;
    bool operator!=(const duration&amp;) const noexcept;
    bool operator&lt; (const duration&amp;) const noexcept;
    bool operator&gt; (const duration&amp;) const noexcept;
    bool operator&lt;=(const duration&amp;) const noexcept;
    bool operator&gt;=(const duration&amp;) const noexcept;

    bool operator==(const time_of_day&amp;) const noexcept;
    bool operator!=(const time_of_day&amp;) const noexcept;
    bool operator&lt; (const time_of_day&amp;) const noexcept;
    bool operator&gt; (const time_of_day&amp;) const noexcept;
    bool operator&lt;=(const time_of_day&amp;) const noexcept;
    bool operator&gt;=(const time_of_day&amp;) const noexcept;
};

duration operator+(const duration&amp;, const duration&amp;) noexcept;
duration operator-(const duration&amp;, const duration&amp;) noexcept;

duration operator+(const duration&amp;, const time_of_day&amp;) noexcept;
duration operator-(const duration&amp;, const time_of_day&amp;) noexcept;

duration operator*(const duration&amp;, long long) noexcept;
duration operator*(long long, const duration&amp;) noexcept;
duration operator/(const duration&amp;, long long) noexcept;

long long operator/(const duration&amp;, const duration&amp;) noexcept;
long long operator/(const duration&amp;, const time_of_day&amp;) noexcept;

duration operator%(const duration&amp;, long long) noexcept;
duration operator%(const duration&amp;, const duration&amp;) noexcept;
duration operator%(const duration&amp;, const time_of_day&amp;) noexcept;

//
// We&rsquo;ll also provide std::div()-like operations:
//
std::pair&lt;duration, duration&gt; div(const duration&amp;, long long) noexcept;
std::pair&lt;long long,duration&gt; div(const duration&amp;, const duration&amp;) noexcept;
std::pair&lt;long long,duration&gt; div(const duration&amp;, const time_of_day&amp;) noexcept;

//
// duration literals...same requirements as
// construction from strings; NB: not constexpr:
//
duration operator "" dur(const char*, size_t);

//
// A time_of_day is an unsigned amount of time after midnight.
// It does not understand leap seconds since it&rsquo;s not associated
// with any particular day.  Values will always be in the half-open
// interval, [midnight, midnight +1 day).  Users may select whether
// arithmetic saturates or modwraps.  The default is to modwrap.
//
class time_of_day
{
public:
    explicit constexpr time_of_day(bool saturate = false); // midnight

    explicit time_of_day(unsigned long tot_seconds, bool saturate = false);

    time_of_day(unsigned int  hour,
                unsigned int  minute,
                unsigned int  second = 0U,
                unsigned long microsecond = 0UL,
                bool saturate = false);

    //
    // Construct from strings as for duration, but only:
    //   - an ISO 8601 duration without years, months or days
    //   - a string like "hh:mm:ss"
    // with the optional decimal point for non-zero microseconds.
    // A leading sign is not allowed.
    //
    explicit time_of_day(const char*);

    time_of_day(const time_of_day&amp;) = default;
    time_of_day&amp; operator=(const time_of_day&amp;) = default;

    ~time_of_day() = default;

    //
    // Get/set saturate/modwrap behavior:
    //
    bool get_saturate() const noexcept;
    void set_saturate(bool = true) noexcept;

    //
    // A time_of_day can be cast to a duration.
    // You get a copy, not a reference to *this,
    // since duration values aren't constrained.
    //
    explicit operator duration() const noexcept;

    microsecs total_microsecs() const noexcept;

    struct breakdown
    {
        unsigned int hour, minute, second;
        unsigned long microsecond;
    };
    explicit operator breakdown() const noexcept;

    //
    // Since *this is conceptually unsigned, unary + and -
    // don&rsquo;t seem particularly useful; but they&rsquo;re there
    // anyway just for the sake of least astonishment.
    //
    time_of_day operator+() noexcept; // gets a copy
    time_of_day operator-() noexcept; // saturates or modwraps

    time_of_day&amp; operator++() noexcept;
    time_of_day&amp; operator--() noexcept;

    time_of_day  operator++(int) noexcept;
    time_of_day  operator--(int) noexcept;

    time_of_day&amp; operator+=(const time_of_day&amp;) noexcept;
    time_of_day&amp; operator-=(const time_of_day&amp;) noexcept;

    time_of_day&amp; operator+=(const duration&amp;) noexcept;
    time_of_day&amp; operator-=(const duration&amp;) noexcept;

    time_of_day&amp; operator*=(unsigned long) noexcept;
    time_of_day&amp; operator/=(unsigned long) noexcept;

    time_of_day&amp; operator%=(unsigned long) noexcept;
    time_of_day&amp; operator%=(const time_of_day&amp;) noexcept;
    time_of_day&amp; operator%=(const duration&amp;) noexcept;

    bool operator==(const time_of_day&amp;) const noexcept;
    bool operator!=(const time_of_day&amp;) const noexcept;
    bool operator&lt; (const time_of_day&amp;) const noexcept;
    bool operator&gt; (const time_of_day&amp;) const noexcept;
    bool operator&lt;=(const time_of_day&amp;) const noexcept;
    bool operator&gt;=(const time_of_day&amp;) const noexcept;

    bool operator==(const duration&amp;) const noexcept;
    bool operator!=(const duration&amp;) const noexcept;
    bool operator&lt; (const duration&amp;) const noexcept;
    bool operator&gt; (const duration&amp;) const noexcept;
    bool operator&lt;=(const duration&amp;) const noexcept;
    bool operator&gt;=(const duration&amp;) const noexcept;
};

time_of_day operator+(const time_of_day&amp;, const time_of_day&amp;) noexcept;
time_of_day operator-(const time_of_day&amp;, const time_of_day&amp;) noexcept;

time_of_day operator+(const time_of_day&amp;, const duration&amp;) noexcept;
time_of_day operator-(const time_of_day&amp;, const duration&amp;) noexcept;

time_of_day operator*(const time_of_day&amp;, unsigned long) noexcept;
time_of_day operator*(unsigned long, const time_of_day&amp;) noexcept;
time_of_day operator/(const time_of_day&amp;, unsigned long) noexcept;

unsigned long operator/(const time_of_day&amp;, const time_of_day&amp;) noexcept;
/*signed*/ long operator/(const time_of_day&amp;, const duration&amp;) noexcept;

time_of_day operator%(const time_of_day&amp;, unsigned long) noexcept;
time_of_day operator%(const time_of_day&amp;, const time_of_day&amp;) noexcept;
time_of_day operator%(const time_of_day&amp;, const duration&amp;) noexcept;

//
// The div()-like functions need to allow the user to specify
// the saturate/modwrap behavior ...
//
std::pair&lt;time_of_day, time_of_day&gt;
  div(const time_of_day&amp;, unsigned long, bool) noexcept;
std::pair&lt;long, time_of_day&gt;
  div(const time_of_day&amp;, const time_of_day&amp;, bool) noexcept;
std::pair&lt;long, time_of_day&gt;
  div(const time_of_day&amp;, const duration&amp;, bool) noexcept;
//
// or just default to the first argument&rsquo;s behavior:
//
std::pair&lt;time_of_day, time_of_day&gt;
  div(const time_of_day&amp;, unsigned long) noexcept;
std::pair&lt;long, time_of_day&gt;
  div(const time_of_day&amp;, const time_of_day&amp;) noexcept;
std::pair&lt;long, time_of_day&gt;
  div(const time_of_day&amp;, const duration&amp;) noexcept;

//
// time_of_day literals:
//
time_of_day operator "" tod(const char*, size_t);

//
// A month_count is a signed amount of time with month resolution.
// A month_count cannot interact arithmetically with either duration
// or time_of_day.
//
class month_count
{
public:
    static constexpr month_count one_year;
    static constexpr month_count one_month;
    static constexpr month_count zero;

    explicit constexpr month_count(int tot_months = 0) noexcept;
    constexpr month_count(int years, int months) noexcept;

    //
    // Construct from:
    //   - an ISO 8601 duration with only 'Y' and 'M' suffixes
    //   - a string containing years, a hyphen, and months
    //   - a string containing total months
    // with an optional leading sign
    //
    explicit month_count(const char*);

    month_count(const month_count&amp;) = default;
    month_count&amp; operator=(const month_count&amp;) = default;

    ~month_count() = default;

    int years() const noexcept;
    int months() const noexcept;
    int total_months() const noexcept;

    typedef std::pair&lt;int,int&gt; breakdown;
    explicit operator breakdown() const noexcept;

    month_count operator+() noexcept;
    month_count operator-() noexcept;

    month_count&amp; operator++() noexcept;
    month_count&amp; operator--() noexcept;

    month_count  operator++(int) noexcept
    month_count  operator--(int) noexcept

    month_count&amp; operator+=(month_count) noexcept;
    month_count&amp; operator-=(month_count) noexcept;

    month_count&amp; operator*=(int) noexcept;
    month_count&amp; operator/=(int) noexcept;
    month_count&amp; operator%=(int) noexcept;
    month_count&amp; operator%=(month_count) noexcept;

    bool operator==(month_count) const noexcept;
    bool operator!=(month_count) const noexcept;
    bool operator&lt; (month_count) const noexcept;
    bool operator&gt; (month_count) const noexcept;
    bool operator&lt;=(month_count) const noexcept;
    bool operator&gt;=(month_count) const noexcept;
};

month_count operator+(const month_count&amp;, month_count) noexcept;
month_count operator-(const month_count&amp;, month_count) noexcept;

month_count operator*(const month_count&amp;, int) noexcept;
month_count operator*(int, const month_count&amp;) noexcept;
month_count operator/(const month_count&amp;, int) noexcept;

int operator/(month_count, month_count) noexcept;

month_count operator%(const month_count&amp;, int) noexcept;
month_count operator%(const month_count&amp;, month_count) noexcept;

std::pair&lt;month_count, month_count&gt; div(month_count, int) noexcept;
std::pair&lt;int, month_count&gt; div(month_count, month_count) noexcept;

month_count operator "" mc(const char*, size_t);

//
// A datetime is a point in time in some time zone.
//
class datetime
{
public:
    datetime(); // the current wall clock time in the local time zone

    explicit datetime(const timezone&amp;); // current wall clock time

    explicit datetime(const duration&amp;); // in the local time zone
    explicit datetime(std::time_t);
    explicit datetime(std::tm*);
    explicit datetime(std::tm&amp;);

    datetime(const duration&amp;, const timezone&amp;)
    datetime(std::time_t, const timezone&amp;);
    datetime(std::tm*, const timezone&amp;);
    datetime(std::tm&amp;, const timezone&amp;);

    //
    // Construct from an ISO 8601 date/time representation
    // (the 'T' separator may not be replaced by a space):
    //
    explicit datetime(const char*);

    //
    // A timezone will require move semantics and swap,
    // so a datetime will, too.
    //
    explicit datetime(timezone&amp;&amp;);
    datetime(const duration&amp;, timezone&amp;&amp;);
    datetime(std::time_t, timezone&amp;&amp;);
    datetime(std::tm*, timezone&amp;&amp;);
    datetime(std::tm&amp;, timezone&amp;&amp;);

    datetime(const datetime&amp;) = default;
    datetime&amp; operator=(const datetime&amp;) = default;

    datetime(datetime&amp;&amp;) = default;
    datetime&amp; operator=(datetime&amp;&amp;) = default;

    ~datetime() = default;

    void swap(datetime&amp;) noexcept;

    const timezone&amp; get_timezone() const noexcept;

    explicit operator std::time_t() const noexcept;

    struct breakdown
    {
        int year;  // /not/ -1900 like std:tm
        int mon;   // 1-based (not like std::tm)
        int mday;  // 1-based (like std::tm)

        int wday;  // 0 == Sunday
        int yday;  // 0-based

        int hour;  // 0 to 23
        int min;   // 0 to 59
        int sec;   // 0 to 60 (allow leap sec.)
        long usec; // 0 to 999,999

        int isdst; // same as std::tm

        duration utc_offset;

        explicit operator std::tm() const noexcept;
    };
    breakdown localtime() const;
    breakdown gmtime() const;

    //
    // We&rsquo;ll provide mktime() functionality, first adjusting
    // unreasonable values just like std::mktime() does:
    //
    datetime mktime(const breakdown&amp;) noexcept; // *this&rsquo; time zone
    static datetime mktime(const breakdown&amp;, const timezone&amp;) noexcept;
    static datetime mktime(const breakdown&amp;, timezone&amp;&amp;) noexcept;

    //
    // The wall-clock time that would correspond to *this
    // in the specified time zone:
    //
    datetime this_time_in(const timezone&amp;) const;
    datetime this_time_in(timezone&amp;&amp;) const;

    //
    // Assign a different time zone, optionally
    // adjusting *this&rsquo; internal value to match.
    //
    void set_timezone(const timezone&amp;, bool adjust_val = false);
    void set_timezone(timezone&amp;&amp;, bool adjust_val = false);

    datetime&amp; operator+=(const duration&amp;) noexcept;
    datetime&amp; operator-=(const duration&amp;) noexcept;

    datetime&amp; operator+=(const time_of_day&amp;) noexcept;
    datetime&amp; operator-=(const time_of_day&amp;) noexcept;

    datetime&amp; operator+=(month_count);
    datetime&amp; operator-=(month_count);

    bool operator==(const datetime&amp;) const noexcept;
    bool operator!=(const datetime&amp;) const noexcept;
    bool operator&lt; (const datetime&amp;) const noexcept;
    bool operator&gt; (const datetime&amp;) const noexcept;
    bool operator&lt;=(const datetime&amp;) const noexcept;
    bool operator&gt;=(const datetime&amp;) const noexcept;
};

void swap(datetime&amp;, datetime&amp;) noexcept;

datetime operator+(const datetime&amp;, const duration&amp;) noexcept;
datetime operator+(const duration&amp;, const datetime&amp;) noexcept;
datetime operator-(const datetime&amp;, const duration&amp;) noexcept;

datetime operator+(const datetime&amp;, const time_of_day&amp;) noexcept;
datetime operator+(const time_of_day&amp;, const datetime&amp;) noexcept;
datetime operator-(const datetime&amp;, const time_of_day&amp;) noexcept;

datetime operator+(const datetime&amp;, month_count);
datetime operator+(month_count, const datetime&amp;);
datetime operator-(const datetime&amp;, month_count);

datetime operator "" dt(const char*, size_t);

//
// A time zone is an offset from UTC.
//
class timezone
{
public:
    timezone(); // the local time zone

    //
    // Construct the named time zone.  POSIX strings like "CST6CDT"
    // are always supported.  If you're running on a box that has
    // the Olson zoneinfo database, names like "America/Chicago"
    // may be specified as well.  An ISO 8601 time zone specifier
    // may also be used, but if you construct a timezone from such
    // a string, the timezone won&rsquo;t have any daylight-saving-time
    // rules associated with it.
    //
    explicit timezone(const char*);

    timezone(const timezone&amp;) = default;
    timezone&amp; operator=(const timezone&amp;) = default;

    timezone(timezone&amp;&amp;) = default;
    timezone&amp; operator=(timezone&amp;&amp;) = default;

    ~timezone() = default;

    void swap(timezone&amp;) noexcept;

    const std::string&amp; name() const noexcept;

    duration utc_offset() const; // at local wall clock time
    bool is_dst() const;         //           "
    std::string abbrv() const;   //           "

    duration utc_offset(const datetime&amp;) const; // at specified time
    bool is_dst(const datetime&amp;) const;         //        "
    std::string abbrv(const datetume&amp;) const;   //        "
};

void swap(timezone&amp;, timezone&amp;) noexcept;

} // namespace civiltime
} // namespace experimental
} // namespace std
</pre>
<p><hr>
All suggestions and corrections will be welcome; all flames will be amusing.<br>
Mail to stdbill<tt>.</tt>h<sup>@</sup>pobox<tt>.</tt>com.
</body>
</html>
