From 632d1158124220fbaa13653bc2bcfd72f5861814 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sun, 26 Nov 2017 13:51:38 -0500 Subject: [PATCH] Add clock_cast documentation --- tz.html | 497 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 381 insertions(+), 116 deletions(-) diff --git a/tz.html b/tz.html index bae3af4..d2e2c35 100644 --- a/tz.html +++ b/tz.html @@ -26,7 +26,7 @@

Howard E. Hinnant
-2017-10-28
+2017-11-26

Time Zone Database Parser

@@ -61,6 +61,7 @@
  • utc_clock
  • tai_clock
  • gps_clock
  • +
  • clock_cast
  • leap
  • link
  • @@ -648,13 +649,13 @@ was in the air. This can be taken into account with the following code: int main() { - using namespace std::chrono_literals; + using namespace std::chrono; using namespace date; auto departure = make_zoned("America/New_York", local_days{dec/31/1978} + 12h + 1min); - auto departure_utc = to_utc_time(departure.get_sys_time()); + auto departure_utc = clock_cast<utc_clock>(departure.get_sys_time()); auto flight_length = 14h + 44min; - auto arrival = make_zoned("Asia/Tehran", to_sys_time(departure_utc + flight_length)); + auto arrival = make_zoned("Asia/Tehran", clock_cast<system_clock>(departure_utc + flight_length)); std::cout << "departure NYC time: " << departure << '\n'; std::cout << "flight time is " << make_time(flight_length) << '\n'; @@ -2672,13 +2673,23 @@ make_zoned(const std::string& name, const sys_time<Duration>& st) class utc_clock { public: - using duration = std::chrono::system_clock::duration; - using rep = duration::rep; - using period = duration::period; + using rep = a signed arithmetic type; + using period = ratio<unspecified, unspecified>; + using duration = std::chrono::duration<rep, period>; using time_point = std::chrono::time_point<utc_clock>; - static constexpr bool is_steady = false; + static constexpr bool is_steady = unspecified; static time_point now() noexcept; + + template <class Duration> + static + sys_time<std::common_type_t<Duration, std::chrono::seconds>> + to_sys(const utc_time<Duration>&); + + template <class Duration> + static + utc_time<std::common_type_t<Duration, std::chrono::seconds>> + from_sys(const sys_time<Duration>&); }; template <class Duration> @@ -2708,19 +2719,21 @@ static utc_clock::time_point utc_clock::now() noexcept;

    -Returns: to_utc_time(system_clock::now()). +Returns: from_sys(system_clock::now()), or a more accurate +value of utc_time.

    -template <class Duration>
    +template <typename Duration>
    +static 
     sys_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_sys_time(utc_time<Duration> u)
    +utc_clock::to_sys(const utc_time<Duration>& u);
     

    Returns: A sys_time t, such that -to_utc_time(t) == u if such a mapping exists. Otherwise u +from_sys(t) == u if such a mapping exists. Otherwise u represents a time_point during a leap second insertion and the last representable value of sys_time prior to the insertion of the leap second is returned. @@ -2728,9 +2741,10 @@ second is returned.

    -template <class Duration>
    +template <typename Duration>
    +static
     utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_utc_time(sys_time<Duration> t)
    +utc_clock::from_sys(const sys_time<Duration>& t);
     

    @@ -2742,34 +2756,6 @@ second insertion), then the conversion counts that leap second as inserted.

    -
    -template <class Duration>
    -utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_utc_time(tai_time<Duration> t) noexcept
    -
    -
    -

    -Returns: utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 378691210s -

    -

    -Note: 378691210s == sys_days{1970y/jan/1} - sys_days{1958y/jan/1} + 10s -

    -
    - -
    -template <class Duration>
    -utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_utc_time(gps_time<Duration> t) noexcept
    -
    -
    -

    -Returns: utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 315964809s -

    -

    -Note: 315964809s == sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1} + 9s -

    -
    -
     template <class CharT, class Traits, class Duration>
     std::basic_ostream<class CharT, class Traits>&
    @@ -2838,13 +2824,23 @@ If abbrev is not equal to nullptr, the information par
     class tai_clock
     {
     public:
    -    using duration                  = std::chrono::system_clock::duration;
    -    using rep                       = duration::rep;
    -    using period                    = duration::period;
    +    using rep                       = a signed arithmetic type;
    +    using period                    = ratio<unspecified, unspecified>;
    +    using duration                  = std::chrono::duration<rep, period>;
         using time_point                = std::chrono::time_point<tai_clock>;
    -    static constexpr bool is_steady = false;
    +    static constexpr bool is_steady = unspecified;
     
         static time_point now() noexcept;
    +
    +    template <class Duration>
    +    static 
    +    utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +    to_utc(const std::chrono::time_point<tai_clock, Duration>&) noexcept;
    +
    +    template <class Duration>
    +    static
    +    tai_time<std::common_type<Duration, std::chrono::seconds>>
    +    from_utc(const utc_time<Duration>&) noexcept;
     };
     
     template <class Duration>
    @@ -2872,40 +2868,20 @@ static tai_clock::time_point tai_clock::now() noexcept;
     

    -Returns: to_tai_time(system_clock::now()). +Returns: from_utc(utc_clock::now()), or a more accurate +value of tai_time.

     template <class Duration>
    -sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_sys_time(tai_time<Duration> t)
    +static 
    +utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +to_utc(const std::chrono::time_point<tai_clock, Duration>& t) noexcept;
     

    -Equivalent to: return to_sys_time(to_utc_time(t)). -

    -
    - -
    -template <class Duration>
    -tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_tai_time(sys_time<Duration> t)
    -
    -
    -

    -Equivalent to: return to_tai_time(to_utc_time(t)). -

    -
    - -
    -template <class Duration>
    -tai_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_tai_time(utc_time<Duration> u) noexcept
    -
    -
    -

    -Returns: tai_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 378691210s +Returns: utc_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 378691210s

    Note: 378691210s == sys_days{1970y/jan/1} - sys_days{1958y/jan/1} + 10s @@ -2914,15 +2890,16 @@ to_tai_time(utc_time<Duration> u) noexcept

     template <class Duration>
    -tai_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_tai_time(gps_time<Duration> t) noexcept
    +static
    +tai_time<std::common_type<Duration, std::chrono::seconds>>
    +tai_clock::from_utc(const utc_time<Duration>& t) noexcept;
     

    -Returns: tai_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 694656019s +Returns: tai_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 378691210s

    -Note: 694656019s == sys_days{1980y/jan/sun[1]} - sys_days{1958y/jan/1} + 19s +Note: 378691210s == sys_days{1970y/jan/1} - sys_days{1958y/jan/1} + 10s

    @@ -2992,13 +2969,23 @@ If abbrev is not equal to nullptr, the information par class gps_clock { public: - using duration = std::chrono::system_clock::duration; - using rep = duration::rep; - using period = duration::period; + using rep = a signed arithmetic type; + using period = ratio<unspecified, unspecified>; + using duration = std::chrono::duration<rep, period>; using time_point = std::chrono::time_point<gps_clock>; - static constexpr bool is_steady = false; + static constexpr bool is_steady = unspecified; static time_point now() noexcept; + + template <class Duration> + static + utc_time<std::common_type_t<Duration, std::chrono::seconds>> + to_utc(const gps_time<Duration>&) noexcept; + + template <class Duration> + static + gps_time<std::common_type_t<Duration, std::chrono::seconds>> + from_utc(const utc_time<Duration>&) noexcept; }; template <class Duration> @@ -3025,40 +3012,20 @@ static gps_clock::time_point gps_clock::now() noexcept;

    -Returns: to_gps_time(system_clock::now()). +Returns: from_utc(utc_clock::now()), or a more accurate +value of gps_time.

     template <class Duration>
    -sys_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_sys_time(gps_time<Duration> t)
    +static 
    +utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +gps_clock::to_utc(const gps_time<Duration>& t) noexcept;
     

    -Equivalent to: return to_sys_time(to_utc_time(t)). -

    -
    - -
    -template <class Duration>
    -gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_gps_time(sys_time<Duration> t)
    -
    -
    -

    -Equivalent to: return to_gps_time(to_utc_time(t)). -

    -
    - -
    -template <class Duration>
    -gps_time<std::common_type_t<Duration, std::chrono::seconds>>
    -to_gps_time(utc_time<Duration> u) noexcept
    -
    -
    -

    -Returns: gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 315964809s +Returns: gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} + 315964809s

    Note: 315964809s == sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1} + 9s @@ -3067,15 +3034,16 @@ to_gps_time(utc_time<Duration> u) noexcept

     template <class Duration>
    -gps_time<typename std::common_type<Duration, std::chrono::seconds>::type>
    -to_gps_time(tai_time<Duration> t) noexcept
    +static
    +gps_time<std::common_type_t<Duration, std::chrono::seconds>>
    +gps_clock::from_utc(const utc_time<Duration>& t) noexcept;
     

    -Returns: gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 694656019s +Returns: gps_time<common_type_t<Duration, seconds>>{t.time_since_epoch()} - 315964809s

    -Note: 694656019s == sys_days{1980y/jan/sun[1]} - sys_days{1958y/jan/1} + 19s +Note: 315964809s == sys_days{1980y/jan/sun[1]} - sys_days{1970y/jan/1} + 9s

    @@ -3156,14 +3124,14 @@ int main() { using namespace date; - using namespace std::chrono_literals; - auto start = to_utc_time(sys_days{2015_y/jul/1} - 500ms); + using namespace std::chrono; + auto start = clock_cast<utc_clock>(sys_days{2015_y/jul/1} - 500ms); auto end = start + 2s; for (auto utc = start; utc < end; utc += 100ms) { - auto sys = to_sys_time(utc); - auto tai = to_tai_time(utc); - auto gps = to_gps_time(utc); + auto sys = clock_cast<system_clock>(utc); + auto tai = clock_cast<tai_clock>(utc); + auto gps = clock_cast<gps_clock>(utc); std::cout << format("%F %T SYS == ", sys) << format("%F %T %Z == ", utc) << format("%F %T %Z == ", tai) @@ -3203,6 +3171,303 @@ Output:

    + +

    clock_cast

    +
    +
    +template <class DestClock, class SourceClock>
    +struct clock_time_conversion
    +{};
    +
    +

    +clock_time_conversion serves as trait which can be used to specify how to +convert time_point<SourceClock, Duration> to +time_point<DestClock, Duration> via a specialization: +clock_time_conversion<DestClock, SourceClock>. A specialization of +clock_time_conversion<DestClock, SourceClock> shall provide a +const-qualified operator() that takes a parameter of type +time_point<SourceClock, Duration> and returns a +time_point<DestClock, some duration> representing an equivalent +point in time. A program may specialize clock_time_conversion if at least +one of the template parameters is user-defined clock type. +

    + +

    +Several specializations are provided by the implementation: +

    +
    +// Identity
    +
    +template <typename Clock>
    +struct clock_time_conversion<Clock, Clock>
    +{
    +    template <class Duration>
    +    std::chrono::time_point<Clock, Duration>
    +    operator()(const std::chrono::time_point<Clock, Duration>& t) const;
    +};
    +
    +template <class Duration>
    +std::chrono::time_point<Clock, Duration>
    +operator()(const std::chrono::time_point<Clock, Duration>& t) const;
    +
    + +
    +

    +Returns: t. +

    +
    + +
    +template <>
    +struct clock_time_conversion<std::chrono::system_clock, std::chrono::system_clock>
    +{
    +    template <class Duration>
    +    sys_time<Duration>
    +    operator()(const sys_time<Duration>& t) const;
    +};
    +
    +template <class Duration>
    +sys_time<Duration>
    +operator()(const sys_time<Duration>& t) const;
    +
    + +
    +

    +Returns: t. +

    +
    + +
    +template <>
    +struct clock_time_conversion<utc_clock, utc_clock>
    +{
    +    template <class Duration>
    +    utc_time<Duration>
    +    operator()(const utc_time<Duration>& t) const;
    +};
    +
    +template <class Duration>
    +utc_time<Duration>
    +operator()(const utc_time<Duration>& t) const;
    +
    + +
    +

    +Returns: t. +

    +
    + +
    +// system_clock <-> utc_clock
    +
    + +
    +template <>
    +struct clock_time_conversion<utc_clock, std::chrono::system_clock>
    +{
    +    template <class Duration>
    +    utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +    operator()(const sys_time<Duration>& t) const;
    +};
    +
    +template <class Duration>
    +utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +operator()(const sys_time<Duration>& t) const;
    +
    + +
    +

    +Returns: utc_clock::from_sys(t). +

    +
    + +
    +template <>
    +struct clock_time_conversion<std::chrono::system_clock, utc_clock>
    +{
    +    template <class Duration>
    +    sys_time<std::common_type_t<Duration, std::chrono::seconds>>
    +    operator()(const utc_time<Duration>& t) const;
    +};
    +
    +template <class Duration>
    +sys_time<std::common_type_t<Duration, std::chrono::seconds>>
    +operator()(const utc_time<Duration>& t) const;
    +
    + +
    +

    +Returns: utc_clock::to_sys(t). +

    +
    + +
    +// Clock <-> system_clock
    +
    + +
    +template <class SourceClock>
    +struct clock_time_conversion<std::chrono::system_clock, SourceClock>
    +{
    +    template <class Duration>
    +    auto
    +    operator()(const std::chrono::time_point<SourceClock, Duration>& t) const
    +        -> decltype(SourceClock::to_sys(t));
    +};
    +
    +template <class Duration>
    +auto
    +operator()(const std::chrono::time_point<SourceClock, Duration>& t) const
    +    -> decltype(SourceClock::to_sys(t));
    +
    + +
    +

    +Remarks: This function does not participate in overload resolution unless +SourceClock::to_sys(t) is well formed. If +SourceClock::to_sys(t) does not return +sys_time<some duration> the program is ill-formed. +

    +

    +Returns: SourceClock::to_sys(t). +

    +
    + +
    +template <class DestClock>
    +struct clock_time_conversion<DestClock, std::chrono::system_clock>
    +{
    +    template <class Duration>
    +    auto
    +    operator()(const sys_time<Duration>& t) const
    +        -> decltype(DestClock::from_sys(t));
    +};
    +
    +template <class Duration>
    +auto
    +operator()(const sys_time<Duration>& t) const
    +    -> decltype(DestClock::from_sys(t));
    +
    + +
    +

    +Remarks: This function does not participate in overload resolution unless +DestClock::from_sys(t) is well formed. If +DestClock::from_sys(t) does not return +time_point<DestClock, some duration> the program is ill-formed. +

    +

    +Returns: DestClock::from_sys(t). +

    +
    + +
    +// Clock <-> utc_clock
    +
    + +
    +template <class SourceClock>
    +struct clock_time_conversion<utc_clock, SourceClock>
    +{
    +    template <class Duration>
    +    auto
    +    operator()(const std::chrono::time_point<SourceClock, Duration>& t) const
    +        -> decltype(SourceClock::to_utc(t));
    +};
    +
    +template <class Duration>
    +auto
    +operator()(const std::chrono::time_point<SourceClock, Duration>& t) const
    +    -> decltype(SourceClock::to_utc(t));
    +
    + +
    +

    +Remarks: This function does not participate in overload resolution unless +SourceClock::to_utc(t) is well formed. If +SourceClock::to_utc(t) does not return +utc_time<some duration> the program is ill-formed. +

    +

    +Returns: SourceClock::to_utc(t). +

    +
    + +
    +template <class DestClock>
    +struct clock_time_conversion<DestClock, utc_clock>
    +{
    +    template <class Duration>
    +    auto
    +    operator()(const utc_time<Duration>& t) const
    +        -> decltype(DestClock::from_utc(t));
    +};
    +
    +template <class Duration>
    +auto
    +operator()(const utc_time<Duration>& t) const
    +    -> decltype(DestClock::from_utc(t));
    +
    + +
    +

    +Remarks: This function does not participate in overload resolution unless +DestClock::from_utc(t) is well formed. If +DestClock::from_utc(t) does not return +time_point<DestClock, some duration> the program is ill-formed. +. +

    +

    +Returns: DestClock::from_utc(t). +

    +
    + +
    +// clock_cast
    +
    + +
    +template <class DestClock, class SourceClock, class Duration>
    +std::chrono::time_point<DestClock, some duration>
    +clock_cast(const std::chrono::time_point<SourceClock, Duration>& t);
    +
    + +
    +

    +Remarks: This function does not participate in overload resolution unless +at least one of the following expressions are well formed: +

    +
      +
    1. clock_time_conversion<DestClock, SourceClock>{}(t)
    2. +
    3. Exactly one of: +
        +
      • clock_time_conversion<DestClock, system_clock>{}( + clock_time_conversion<system_clock, SourceClock>{}(t)) +
      • +
      • clock_time_conversion<DestClock, utc_clock>{}( + clock_time_conversion<utc_clock, SourceClock>{}(t))
      • +
    4. +
    5. Exactly one of: +
        +
      • clock_time_conversion<DestClock, utc_clock>{}( + clock_time_conversion<utc_clock, system_clock>{}( + clock_time_conversion<system_clock, SourceClock>{}(t)))
      • +
      • clock_time_conversion<DestClock, system_clock>{}( + clock_time_conversion<system_clock, utc_clock>{}( + clock_time_conversion<utc_clock, SourceClock>{}(t)))
      • +
    6. +
    +

    +Returns: The first expression in the above list that is well-formed. If item 1 is +not well-formed and both expressions in item 2 are well-formed, the +clock_cast is ambiguous (ill-formed). If items 1 and 2 are not well-formed +and both expressions in item 3 are well-formed, the clock_cast is ambiguous +(ill-formed). +

    +
    + +
    +

    leap

    @@ -3556,7 +3821,7 @@ influencing the date.h library.
     

    And I would also especially like to thank contributors to this library: gmcode, -Ivan Pizhenko, tomy2105 and Ville Voutilainen. +Ivan Pizhenko, Tomasz Kamiński, tomy2105 and Ville Voutilainen.