From cb7e2e3cedb6e36734fece254b658dcaa2251b19 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sat, 16 Sep 2017 14:12:30 -0400 Subject: [PATCH] Document custom time zone capabilities --- tz.html | 653 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 494 insertions(+), 159 deletions(-) diff --git a/tz.html b/tz.html index e007e30..931424a 100644 --- a/tz.html +++ b/tz.html @@ -26,7 +26,7 @@

Howard E. Hinnant
-2017-07-03
+2017-09-16

Time Zone Database Parser

@@ -55,6 +55,7 @@
  • sys_info
  • local_info
  • time_zone
  • +
  • zoned_traits
  • zoned_time
  • make_zoned
  • utc_clock
  • @@ -558,6 +559,8 @@ formatting strings.

    Examples

    +

    Flight time

    +

    Interesting things can happen to the apparent time when you travel across the globe at high speeds. So departure and arrival times of airplane flights make for good @@ -674,6 +677,8 @@ flight time is 14:44 arrival Tehran time: 1979-01-01 11:14:59 IRST +

    Format conversion

    +

    A common task in dealing with dates and times is converting from one string format to another. This library is extremely flexible in handling this task. As an @@ -755,6 +760,247 @@ for extension formatting flags to indicate fractional seconds. %S and %T just work.

    +

    Custom time zone

    + +

    +Occasionally the IANA time zone database doesn't quite do everything you want. +This library allows you to use zoned_time with a time zone and/or pointer +to time zone of your own making. One common example is the need to have a time zone +that has a fixed offset from UTC, but for which that offset isn't known until run time. +Below is an example which supplies a custom time zone called OffsetZone +which can hold a UTC offset with minutes precision. +

    + +
    +#include "tz.h"
    +#include <iostream>
    +#include <type_traits>
    +
    +class OffsetZone
    +{
    +    std::chrono::minutes offset_;
    +
    +public:
    +    explicit OffsetZone(std::chrono::minutes offset)
    +        : offset_{offset}
    +        {}
    +
    +    template <class Duration>
    +        auto
    +        to_local(date::sys_time<Duration> tp) const
    +        {
    +            using namespace date;
    +            using namespace std;
    +            using namespace std::chrono;
    +            using LT = local_time<common_type_t<Duration, minutes>>;
    +            return LT{(tp + offset_).time_since_epoch()};
    +        }
    +
    +    template <class Duration>
    +        auto
    +        to_sys(date::local_time<Duration> tp) const
    +        {
    +            using namespace date;
    +            using namespace std;
    +            using namespace std::chrono;
    +            using ST = sys_time<common_type_t<Duration, minutes>>;
    +            return ST{(tp - offset_).time_since_epoch()};
    +        }
    +};
    +
    +int
    +main()
    +{
    +    using namespace date;
    +    using namespace std::chrono;
    +    OffsetZone p3_45{3h + 45min};
    +    zoned_time<milliseconds, OffsetZone*> zt{&p3_45, floor<milliseconds>(system_clock::now())};
    +    std::cout << zt.get_sys_time() << '\n';
    +    std::cout << zt.get_local_time() << '\n';
    +}
    +
    + +

    +This just output for me: +

    + +
    +2017-09-16 17:34:47.560
    +2017-09-16 21:19:47.560
    +
    + +

    +The second template parameter to zoned_time is a pointer to a time zone. +This example simply creates a OffsetZone with a UTC offset of 3:45, and +constructs a OffsetZone which points to that custom time zone and +supplies the current time to the desired precision (whatever that may be). +

    + +

    +You don't have to use a built-in pointer to your time zone. You could just as easily use +unique_ptr, shared_ptr, or whatever smart pointer is right for +your application. And in C++17, you won't need to supply the template parameters for +zoned_time (though you still can if you want to). That is, the construction +of zt above could be simplified down to just this: +

    + +
    +zoned_time zt{&p3_45, floor<milliseconds>(system_clock::now())};
    +
    + +

    +One can even have OffsetZone serve as its own smart pointer by +giving it a member operator->() that returns itself: +

    + +
    +const OffsetZone* operator->() const {return this;}
    +
    + +

    +This allows you to embed the OffsetZone directly into the +zoned_time instead of pointing to an externally held OffsetZone: +

    + +
    +zoned_time<milliseconds, OffsetZone> zt{OffsetZone{3h + 45min}, floor<milliseconds>(system_clock::now())};
    +
    + +

    +As it stands, zoned<Duration, OffsetZone> can't be streamed with +operator<< or formatted with format. But that can be +fixed too: Just give OffsetZone a member get_info which +takes a sys_time and returns a +sys_info: +

    + +
    +template <class Duration>
    +    date::sys_info
    +    get_info(date::sys_time<Duration>) const
    +    {
    +        using namespace date;
    +        using namespace std::chrono;
    +        return {sys_seconds::min(), sys_seconds::max(), offset_,
    +                minutes{0}, offset_ >= minutes{0}
    +                                ? "+" + date::format("%H%M", offset_)
    +                                : "-" + date::format("%H%M", -offset_)};
    +    }
    +
    + +

    +Above I've chosen to make the abbreviation for OffsetZone equivalent to +%z, but I could have installed any std::string I wanted to. +This allows me to say: +

    + +
    +std::cout << zt << '\n';
    +
    + +

    +which just output for me: +

    + +
    +2017-09-16 21:36:10.913 +0345
    +
    + +

    +If I want to make zoned_time<Duration, OffsetZone> default constructible, +then I need to specialize zoned_traits<OffsetZone> with +default_zone(): +

    + +
    +namespace date
    +{
    +
    +template <>
    +struct zoned_traits<OffsetZone>
    +{
    +    static
    +    OffsetZone
    +    default_zone()
    +    {
    +        using namespace std::chrono;
    +        return OffsetZone{minutes{0}};
    +    }
    +};
    +
    +}  // namespace date
    +
    + +

    +Now this: +

    + +
    +zoned_time<milliseconds, OffsetZone> zt;
    +std::cout << zt << '\n';
    +
    + +

    +outputs: +

    + +
    +1970-01-01 00:00:00.000 +0000
    +
    + +

    +And if I wanted to construct a zoned_time<Duration, OffsetZone> from +a string, I need to add +static OffsetZone locate_zone(string name) to my zoned_traits +specialization. +

    + +
    +namespace date
    +{
    +
    +template <>
    +struct zoned_traits<OffsetZone>
    +{
    +    static
    +    OffsetZone
    +    default_zone()
    +    {
    +        using namespace std::chrono;
    +        return OffsetZone{minutes{0}};
    +    }
    +
    +    static
    +    OffsetZone
    +    locate_zone(const std::string& name)
    +    {
    +        using namespace std::chrono;
    +        if (name == "UTC")
    +            return OffsetZone{minutes{0}};
    +        throw std::runtime_error{"OffsetZone can't handle anything but " + name};
    +    }
    +};
    +
    +}  // namespace date
    +
    + +

    +Now this: +

    + +
    +zoned_time<seconds, OffsetZone> zt{"UTC", floor<seconds>(system_clock::now())};
    +std::cout << zt << '\n';
    +
    + +

    +outputs: +

    + +
    +2017-09-16 18:09:22 +0000
    +
    +

    Reference

    @@ -1543,84 +1789,125 @@ useful for debugging this library. +

    zoned_traits

    + +
    +

    +zoned_traits provides a means for customizing the behavior of +zoned_time<Duration, TimeZonePtr> for the +zoned_time default constructor, and constructors taking +string_view. A specialization for const time_zone* +is provided by the implementation. +

    + +
    +template <class T> struct zoned_traits {};
    +
    +template <>
    +struct zoned_traits<const time_zone*>
    +{
    +    static const time_zone* default_zone();
    +    static const time_zone* locate_zone(string_view name);
    +};
    +
    + +
    +static const time_zone* zoned_traits<const time_zone*>::default_zone();
    +
    +
    +

    +Returns: date::locate_zone("UTC"). +

    +
    + +
    +static const time_zone* zoned_traits<const time_zone*>::locate_zone(string_view name);
    +
    +
    +

    +Returns: date::locate_zone(name). +

    +
    + +
    +

    zoned_time

    zoned_time represents a logical paring of time_zone and a -time_point with precision Duration. If seconds -is not implicitly convertible to Duration, the instantiation is ill-formed. -[Note: There exist time_zones with UTC offsets that require a -precision of seconds. — end note:] +time_point with precision Duration.

    -template <class Duration>
    +template <class Duration, class TimeZonePtr = const time_zone*>
     class zoned_time
     {
    -    const time_zone*   zone_;  // exposition only
    -    sys_time<Duration> tp_;    // exposition only
    +public:
    +    using duration = common_type_t<Duration, seconds>;
    +
    +private:
    +    TimeZonePtr        zone_;  // exposition only
    +    sys_time<duration> tp_;    // exposition only
     
     public:
    +    zoned_time();
         zoned_time(const zoned_time&) = default;
         zoned_time& operator=(const zoned_time&) = default;
     
    -             zoned_time();
    -             zoned_time(sys_time<Duration> st);
    -    explicit zoned_time(const time_zone* z);
    -    explicit zoned_time(const std::string& name);
    +             zoned_time(const sys_time<Duration>& st);
    +    explicit zoned_time(TimeZonePtr z);
    +    explicit zoned_time(string_view name);
     
    -    template <class Duration2,
    -              class = std::enable_if_t
    -                      <
    -                          std::is_convertible<sys_time<Duration2>,
    -                                              sys_time<Duration>>{}
    -                      >>
    +    template <class Duration2>
             zoned_time(const zoned_time<Duration2>& zt) noexcept;
     
    -    zoned_time(const time_zone* z,      local_time<Duration> tp);
    -    zoned_time(const std::string& name, local_time<Duration> tp);
    -    zoned_time(const time_zone* z,      local_time<Duration> tp, choose c);
    -    zoned_time(const std::string& name, local_time<Duration> tp, choose c);
    +    zoned_time(TimeZonePtr z,    const sys_time<Duration>& st);
    +    zoned_time(string_view name, const sys_time<Duration>& st);
     
    -    zoned_time(const time_zone* z,      const zoned_time<Duration>& zt);
    -    zoned_time(const std::string& name, const zoned_time<Duration>& zt);
    -    zoned_time(const time_zone* z,      const zoned_time<Duration>& zt, choose);
    -    zoned_time(const std::string& name, const zoned_time<Duration>& zt, choose);
    +    zoned_time(TimeZonePtr z,    const local_time<Duration>& tp);
    +    zoned_time(string_view name, const local_time<Duration>& tp);
    +    zoned_time(TimeZonePtr z,    const local_time<Duration>& tp, choose c);
    +    zoned_time(string_view name, const local_time<Duration>& tp, choose c);
     
    -    zoned_time(const time_zone* z,      const sys_time<Duration>& st);
    -    zoned_time(const std::string& name, const sys_time<Duration>& st);
    +    zoned_time(TimeZonePtr z,    const zoned_time<Duration>& zt);
    +    zoned_time(string_view name, const zoned_time<Duration>& zt);
    +    zoned_time(TimeZonePtr z,    const zoned_time<Duration>& zt, choose);
    +    zoned_time(string_view name, const zoned_time<Duration>& zt, choose);
     
    -    zoned_time& operator=(sys_time<Duration> st);
    -    zoned_time& operator=(local_time<Duration> ut);
    +    zoned_time& operator=(const sys_time<Duration>& st);
    +    zoned_time& operator=(const local_time<Duration>& ut);
     
    -             operator sys_time<Duration>() const;
    -    explicit operator local_time<Duration>() const;
    +             operator sys_time<duration>()   const;
    +    explicit operator local_time<duration>() const;
     
    -    const time_zone*     get_time_zone() const;
    -    local_time<Duration> get_local_time() const;
    -    sys_time<Duration>   get_sys_time() const;
    -    sys_info             get_info() const;
    +    TimeZonePtr          get_time_zone()  const;
    +    local_time<duration> get_local_time() const;
    +    sys_time<duration>   get_sys_time()   const;
    +    sys_info             get_info()       const;
     };
     
     using zoned_seconds = zoned_time<std::chrono::seconds>;
     
    -template <class Duration1, class Duration2>
    +template <class Duration1, class Duration2, class TimeZonePtr>
     bool
    -operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
    +operator==(const zoned_time<Duration1, TimeZonePtr>& x,
    +           const zoned_time<Duration2, TimeZonePtr>& y);
     
    -template <class Duration1, class Duration2>
    +template <class Duration1, class Duration2, class TimeZonePtr>
     bool
    -operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
    +operator!=(const zoned_time<Duration1, TimeZonePtr>& x,
    +           const zoned_time<Duration2, TimeZonePtr>& y);
     
    -template <class CharT, class Traits, class Duration>
    -std::basic_ostream<class CharT, class Traits>&
    -operator<<(std::basic_ostream<class CharT, class Traits>& os, const zoned_time<Duration>& t)
    +template <class charT, class traits, class Duration, class TimeZonePtr>
    +    basic_ostream<charT, traits>&
    +    operator<<(basic_ostream<charT, traits>& os,
    +               const zoned_time<Duration, TimeZonePtr>& t);
     
    -template <class CharT, class Traits, class Duration>
    -std::basic_ostream<CharT, Traits>&
    -to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
    -          const zoned_time<Duration>& tp);
    +template <class charT, class traits, class Duration, class TimeZonePtr>
    +    basic_ostream<charT, traits>&
    +    to_stream(basic_ostream<charT, traits>& os, const charT* fmt,
    +              const zoned_time<Duration, TimeZonePtr>& tp);
     

    @@ -1630,8 +1917,23 @@ and is not ambiguous.

    -zoned_time<Duration>::zoned_time(const zoned_time&) = default;
    -zoned_time<Duration>& zoned_time<Duration>::operator=(const zoned_time&) = default;
    +zoned_time<Duration, TimeZonePtr>::zoned_time();
    +
    +
    +

    +Remarks: This constructor does not participate in overload resolution unless +the expression zoned_traits<TimeZonePtr>::default_zone() is well formed. +

    +

    +Effects: Constructs a zoned_time by initializing +zone_ with zoned_traits<TimeZonePtr>::default_zone() and +default constructing tp_. +

    +
    + +
    +zoned_time<Duration, TimeZonePtr>::zoned_time(const zoned_time&) = default;
    +zoned_time<Duration, TimeZonePtr>& zoned_time<Duration>::operator=(const zoned_time&) = default;
     

    @@ -1644,151 +1946,214 @@ members.

    -zoned_time<Duration>::zoned_time();
    +zoned_time<Duration, TimeZonePtr>::zoned_time(const sys_time<Duration>& st);
     

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()->name() == "UTC", and -zt.get_sys_time() == sys_seconds{}. +Remarks: This constructor does not participate in overload resolution unless +the expression zoned_traits<TimeZonePtr>::default_zone() is well formed. +

    +

    +Effects: Constructs a zoned_time by initializing +zone_ with zoned_traits<TimeZonePtr>::default_zone() and +tp_ with st.

    -zoned_time<Duration>::zoned_time(sys_time<Duration> st);
    -
    -
    -

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()->name() == "UTC", and -zt.get_sys_time() == st. -

    -
    - -
    -explicit zoned_time<Duration>::zoned_time(const time_zone* z);
    +explicit zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z);
     

    Requires: z refers to a valid time_zone.

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and -zt.get_sys_time() == sys_seconds{}. +Effects: Constructs a zoned_time initializing zone_ +with std::move(z).

    -explicit zoned_time<Duration>::zoned_time(const std::string& name);
    +explicit zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name);
     

    -Effects: Equivalent to construction with locate_zone(name). +Remarks: This constructor does not participate in overload resolution unless +the expression zoned_traits<TimeZonePtr>::locate_zone(string_view{}) +is well formed and zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(string_view{}).

    -Throws: Any exception propagating out of locate_zone(name). +Effects: Constructs a zoned_time by initializing +zone_ with zoned_traits<TimeZonePtr>::locate_zone(name) +and default constructing tp_.

    -template <class Duration2,
    -          class = std::enable_if_t
    -                  <
    -                      std::is_convertible<sys_time<Duration2>,
    -                                          sys_time<Duration>>{}
    -                  >>
    -    zoned_time<Duration>::zoned_time(const zoned_time<Duration2>& y) noexcept;
    +template <class Duration2, TimeZonePtr>
    +    zoned_time<Duration>::zoned_time(const zoned_time<Duration2, TimeZonePtr>& y) noexcept;
     

    +Remarks: Does not participate in overload resolution unless +sys_time<Duration2> is implicitly convertible to +sys_time<Duration>. +

    +

    Effects: Constructs a zoned_time x such that x == y.

    -zoned_time<Duration>::zoned_time(const time_zone* z, local_time<Duration> tp);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const sys_time<Duration>& st);
     

    Requires: z refers to a valid time_zone.

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and zt.get_local_time() == tp. -

    -

    -Throws: Any exception that z->to_sys(tp) would throw. +Effects: Constructs a zoned_time by initializing zone_ +with std::move(z) and tp_ with st.

    -zoned_time<Duration>::zoned_time(const std::string& name, local_time<Duration> tp);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const sys_time<Duration>& st);
     

    -Effects: Equivalent to construction with {locate_zone(name), tp}. +Remarks: This constructor does not participate in overload resolution unless +zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(name) and st. +

    +

    +Effects: Equivalent to construction with {zoned_traits<TimeZonePtr>::locate_zone(name), st}.

    -zoned_time<Duration>::zoned_time(const time_zone* z, local_time<Duration> tp, choose c);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& tp);
     

    Requires: z refers to a valid time_zone.

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and -zt.get_sys_time() == z->to_sys(tp, c). +Remarks: This constructor does not participate in overload resolution unless +declval<TimeZonePtr&>()->to_sys(local_time<Duration>{}) +is convertible to sys_time<duration>. +

    +

    +Effects: Constructs a zoned_time by initializing zone_ +with std::move(z) and tp_ with zone_->to_sys(t).

    -zoned_time<Duration>::zoned_time(const std::string& name, local_time<Duration> tp, choose c);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const local_time<Duration>& tp);
     

    -Effects: Equivalent to construction with {locate_zone(name), tp, c}. +Remarks: This constructor does not participate in overload resolution unless +zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(name) and tp. +

    +

    +Effects: Equivalent to construction with {zoned_traits<TimeZonePtr>::locate_zone(name), tp}.

    -zoned_time<Duration>::zoned_time(const time_zone* z, const zoned_time<Duration>& y);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const local_time<Duration>& tp, choose c);
     

    Requires: z refers to a valid time_zone.

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and -zt.get_sys_time() == y.get_sys_time(). +Remarks: This constructor does not participate in overload resolution unless +decltype(declval<TimeZonePtr&>()->to_sys(local_time<Duration>{}, choose::earliest)) +is convertible to sys_time<duration>. +

    +

    +Effects: Constructs a zoned_time by initializing zone_ +with std::move(z) and tp_ with zone_->to_sys(t, c).

    -zoned_time<Duration>::zoned_time(const std::string& name, const zoned_time<Duration>& y);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const local_time<Duration>& tp, choose c);
     

    -Effects: Equivalent to construction with {locate_zone(name), y}. +Remarks: This constructor does not participate in overload resolution unless +zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(name), +local_time<Duration> and choose. +

    +

    +Effects: Equivalent to construction with +{zoned_traits<TimeZonePtr>::locate_zone(name), tp, c}.

    -zoned_time<Duration>::zoned_time(const time_zone* z, const zoned_time<Duration>& y, choose);
    +zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const zoned_time<Duration>& y);
     

    Requires: z refers to a valid time_zone.

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and -zt.get_sys_time() == y.get_sys_time(). +Effects: Constructs a zoned_time by initializing zone_ +with std::move(z) and tp_ with z.tp_. +

    +
    + +
    +zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const zoned_time<Duration>& y);
    +
    +
    +

    +Remarks: This constructor does not participate in overload resolution unless +zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(name) +and zoned_time. +

    +

    +Effects: Equivalent to construction with +{zoned_traits<TimeZonePtr>::locate_zone(name), y}. +

    +
    + +
    +zoned_time<Duration, TimeZonePtr>::zoned_time(TimeZonePtr z, const zoned_time<Duration>& y, choose);
    +
    +
    +

    +Requires: z refers to a valid time_zone. +

    +

    +Effects: Equivalent to construction with {z, y}. +

    +Note: The choose parameter is allowed here, but has no impact. +

    +
    + +
    +zoned_time<Duration, TimeZonePtr>::zoned_time(string_view name, const zoned_time<Duration>& y, choose c);
    +
    +
    +

    +Remarks: This constructor does not participate in overload resolution unless +zoned_time is constructible from the return type of +zoned_traits<TimeZonePtr>::locate_zone(name), zoned_time, +and choose. +

    +

    +Effects: Equivalent to construction with {locate_zone(name), y, c}.

    Note: The choose parameter is allowed here, but has no impact. @@ -1796,41 +2161,7 @@ zoned_time<Duration>::zoned_time(const time_zone* z, const zoned_time<D

    -zoned_time<Duration>::zoned_time(const std::string& name, const zoned_time<Duration>& y, choose);
    -
    -
    -

    -Effects: Equivalent to construction with {locate_zone(name), y}. -

    -

    -Note: The choose parameter is allowed here, but has no impact. -

    -
    - -
    -zoned_time<Duration>::zoned_time(const time_zone* z, const sys_time<Duration>& st);
    -
    -
    -

    -Requires: z refers to a valid time_zone. -

    -

    -Effects: Constructs a zoned_time zt such that -zt.get_time_zone()-> == z, and zt.get_sys_time() == st. -

    -
    - -
    -zoned_time<Duration>::zoned_time(const std::string& name, const sys_time<Duration>& st);
    -
    -
    -

    -Effects: Equivalent to construction with {locate_zone(name), st}. -

    -
    - -
    -zoned_time<Duration>& zoned_time<Duration>::operator=(sys_time<Duration> st);
    +zoned_time<Duration, TimeZonePtr>& zoned_time<Duration, TimeZonePtr>::operator=(const sys_time<Duration>& st);
     

    @@ -1843,7 +2174,7 @@ no effect on the return value of get_time_zone().

    -zoned_time<Duration>& zoned_time<Duration>::operator=(local_time<Duration> lt);
    +zoned_time<Duration, TimeZonePtr>& zoned_time<Duration, TimeZonePtr>::operator=(const local_time<Duration>& lt);
     

    @@ -1856,7 +2187,7 @@ no effect on the return value of get_time_zone().

    -zoned_time<Duration>::operator sys_time<Duration>() const;
    +zoned_time<Duration, TimeZonePtr>::operator sys_time<duration>() const;
     

    @@ -1865,7 +2196,7 @@ zoned_time<Duration>::operator sys_time<Duration>() const;

    -explicit zoned_time<Duration>::operator local_time<Duration>() const;
    +explicit zoned_time<Duration, TimeZonePtr>::operator local_time<duration>() const;
     

    @@ -1874,7 +2205,7 @@ explicit zoned_time<Duration>::operator local_time<Duration>() const

    -const time_zone* zoned_time<Duration>::get_time_zone() const;
    +TimeZonePtr zoned_time<Duration, TimeZonePtr>::get_time_zone() const;
     

    @@ -1883,7 +2214,7 @@ const time_zone* zoned_time<Duration>::get_time_zone() const;

    -local_time<Duration> zoned_time<Duration>::get_local_time() const;
    +local_time<typename zoned_time<Duration, TimeZonePtr>::duration> zoned_time<Duration, TimeZonePtr>::get_local_time() const;
     

    @@ -1892,7 +2223,7 @@ local_time<Duration> zoned_time<Duration>::get_local_time() const;

    -sys_time<Duration> zoned_time<Duration>::get_sys_time() const;
    +sys_time<typename zoned_time<Duration, TimeZonePtr>::duration> zoned_time<Duration, TimeZonePtr>::get_sys_time() const;
     

    @@ -1901,7 +2232,7 @@ sys_time<Duration> zoned_time<Duration>::get_sys_time() const;

    -sys_info zoned_time<Duration>::get_info() const;
    +sys_info zoned_time<Duration, TimeZonePtr>::get_info() const;
     

    @@ -1910,9 +2241,10 @@ sys_info zoned_time<Duration>::get_info() const;

    -template <class Duration1, class Duration2>
    +template <class Duration1, class Duration2, class TimeZonePtr>
     bool
    -operator==(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
    +operator==(const zoned_time<Duration1, TimeZonePtr>& x,
    +           const zoned_time<Duration2, TimeZonePtr>& y);
     

    @@ -1921,9 +2253,10 @@ operator==(const zoned_time<Duration1>& x, const zoned_time<Duratio

    -template <class Duration1, class Duration2>
    +template <class Duration1, class Duration2, class TimeZonePtr>
     bool
    -operator!=(const zoned_time<Duration1>& x, const zoned_time<Duration2>& y);
    +operator!=(const zoned_time<Duration1, TimeZonePtr>& x,
    +           const zoned_time<Duration2, TimeZonePtr>& y);
     

    @@ -1932,13 +2265,15 @@ operator!=(const zoned_time<Duration1>& x, const zoned_time<Duratio

    -template <class CharT, class Traits, class Duration>
    -std::basic_ostream<class CharT, class Traits>&
    -operator<<(std::basic_ostream<class CharT, class Traits>& os, const zoned_time<Duration>& t)
    +template <class charT, class traits, class Duration, class TimeZonePtr>
    +basic_ostream<charT, traits>&
    +operator<<(basic_ostream<charT, traits>& os,
    +           const zoned_time<Duration, TimeZonePtr>& t)
     

    -Effects: Calls to_stream(os, "%F %T %Z", t). +Effects: Streams t to os using the format "%F %T %Z" +and the value returned from t.get_local_time().

    Returns: os. @@ -1946,17 +2281,17 @@ operator<<(std::basic_ostream<class CharT, class Traits>& os, co

    -template <class CharT, class Traits, class Duration>
    -std::basic_ostream<CharT, Traits>&
    -to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
    -          const zoned_time<Duration>& tp);
    +template <class charT, class traits, class Duration, class TimeZonePtr>
    +basic_ostream<charT, traits>&
    +to_stream(basic_ostream<charT, traits>& os, const charT* fmt,
    +          const zoned_time<Duration, TimeZonePtr>& tp);
     

    -Effects: Constructs a copy of the sys_info object by calling -tp.get_info() (stored in a local named info for example). -Then calls to_stream(os, fmt, tp.get_local_time(), &info.abbrev, &info.offset). +Effects: First obtains a sys_info via tp.get_info() +which for exposition purposes will be referred to as info. Then calls +to_stream(os, fmt, tp.get_local_time(), &info.abbrev, &info.offset).

    Returns: os.