From 58b08e0c74ac128aa21e122e1e6e26599f20071e Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Tue, 7 Jun 2016 20:04:10 -0400 Subject: [PATCH] Add tai_clock and gps_clock. --- tz.html | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 290 insertions(+), 1 deletion(-) diff --git a/tz.html b/tz.html index 6514a2b..2e8028c 100644 --- a/tz.html +++ b/tz.html @@ -26,7 +26,7 @@

Howard E. Hinnant
-2016-06-06
+2016-06-07
Creative
 Commons License
This work is licensed @@ -65,6 +65,8 @@ Commons Attribution 4.0 International License.
  • format
  • parse
  • utc_clock
  • +
  • tai_clock
  • +
  • gps_clock
  • leap
  • link
  • @@ -2472,6 +2474,293 @@ seconds specifier when the value represents an inserted leap second. +

    tai_clock

    +
    +
    +class tai_clock
    +{
    +public:
    +    using duration                  = std::chrono::system_clock::duration;
    +    using rep                       = duration::rep;
    +    using period                    = duration::period;
    +    using time_point                = std::chrono::time_point<tai_clock>;
    +    static constexpr bool is_steady = true;
    +
    +    static time_point now() noexcept;
    +
    +    template <class Duration>
    +        static
    +        tai_time<std::common_type_t<Duration, std::chrono::seconds>>
    +        utc_to_tai(utc_time<Duration> t);
    +
    +    template <class Duration>
    +        static
    +        utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +        tai_to_utc(tai_time<Duration> u);
    +};
    +
    +template <class Duration>
    +    using tai_time = std::chrono::time_point<tai_clock, Duration>;
    +
    +using tai_seconds = tai_time<std::chrono::seconds>;
    +
    + +

    +tai_time counts physical seconds continuously like utc_itme, +but when printed out, always has 60 seconds per minute. It's epoch +is 1958-01-01 and is offset ahead of utc_time by 10s in 1970-01-01. +With each leap second, the offset from utc_time grows by another +second. +

    + +
    +static tai_clock::time_point tai_clock::now() noexcept;
    +
    +
    +

    +Returns: to_tai_time(utc_clock::now()). +

    +
    + +
    +template <class Duration>
    +static
    +tai_time<std::common_type_t<Duration, std::chrono::seconds>>
    +tai_clock::utc_to_tai(utc_time<Duration> t);
    +
    +
    +

    +Returns: A tai_time which represents time as measured by +TAI at the same instant as the time t in UTC. +

    +
    + +
    +template <class Duration>
    +static
    +utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +tai_clock::tai_to_utc(tai_time<Duration> t);
    +
    +
    +

    +Returns: A utc_time u, such that +tai_clock::utc_to_tai(u) == t. +

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

    +Returns: tai_clock::tai_to_utc(t). +

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

    +Returns: tai_clock::utc_to_tai(u). +

    +
    + +
    +template <class CharT, class Traits, class Duration>
    +std::basic_ostream<class CharT, class Traits>&
    +operator<<(std::basic_ostream<class CharT, class Traits>& os, const tai_time<Duration>& t)
    +
    +
    +

    +Effects: Streams t to os using the format "%F %T". +

    +

    +Returns: os. +

    +
    + +
    + +

    gps_clock

    +
    +
    +class gps_clock
    +{
    +public:
    +    using duration                  = std::chrono::system_clock::duration;
    +    using rep                       = duration::rep;
    +    using period                    = duration::period;
    +    using time_point                = std::chrono::time_point<gps_clock>;
    +    static constexpr bool is_steady = true;
    +
    +    static time_point now() noexcept;
    +
    +    template <class Duration>
    +        static
    +        gps_time<std::common_type_t<Duration, std::chrono::seconds>>
    +        utc_to_gps(utc_time<Duration> t);
    +
    +    template <class Duration>
    +        static
    +        utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +        gps_to_utc(gps_time<Duration> u);
    +};
    +
    +template <class Duration>
    +    using gps_time = std::chrono::time_point<gps_clock, Duration>;
    +
    +using gps_seconds = gps_time<std::chrono::seconds>;
    +
    + +

    +gps_time counts physical seconds continuously like utc_itme, +but when printed out, always has 60 seconds per minute. It's epoch +is 1980-01-06 and was equivalent to UTC at that time. If falls ahead of UTC +with each inserted leap second. It is always exactly 19s behind TAI. +

    + +
    +static gps_clock::time_point gps_clock::now() noexcept;
    +
    +
    +

    +Returns: to_gps_time(utc_clock::now()). +

    +
    + +
    +template <class Duration>
    +static
    +gps_time<std::common_type_t<Duration, std::chrono::seconds>>
    +gps_clock::utc_to_gps(utc_time<Duration> t);
    +
    +
    +

    +Returns: A gps_time which represents time as measured by +GPS at the same instant as the time t in UTC. +

    +
    + +
    +template <class Duration>
    +static
    +utc_time<std::common_type_t<Duration, std::chrono::seconds>>
    +gps_clock::gps_to_utc(gps_time<Duration> t);
    +
    +
    +

    +Returns: A utc_time u, such that +gps_clock::utc_to_gps(u) == t. +

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

    +Returns: gps_clock::gps_to_utc(t). +

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

    +Returns: gps_clock::utc_to_gps(u). +

    +
    + +
    +template <class CharT, class Traits, class Duration>
    +std::basic_ostream<class CharT, class Traits>&
    +operator<<(std::basic_ostream<class CharT, class Traits>& os, const gps_time<Duration>& t)
    +
    +
    +

    +Effects: Streams t to os using the format "%F %T". +

    +

    +Returns: os. +

    +
    + +

    +[Example: +

    + +

    +The following code prints out equivalent time stamps to millisecond precision for +times near the 2015-06-30 leap second insertion. Note that the mapping to +sys_time during the leap second collapses down to the last instant +prior to the leap second. But the maping between UTC, TAI and GPS is all one-to-one. +

    + +
    +#include "tz.h"
    +#include <iostream>
    +
    +int
    +main()
    +{
    +    using namespace date;
    +    using namespace std::chrono;
    +    auto start = to_utc_time(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);
    +        std::cout << sys << " SYS  ==  " 
    +                  << utc << " UTC  ==  "
    +                  << tai << " TAI  ==  "
    +                  << gps << " GPS\n";
    +    }
    +}
    +
    +

    +Output: +

    +
    +2015-06-30 23:59:59.500 SYS  ==  2015-06-30 23:59:59.500 UTC  ==  2015-07-01 00:00:34.500 TAI  ==  2015-07-01 00:00:15.500 GPS
    +2015-06-30 23:59:59.600 SYS  ==  2015-06-30 23:59:59.600 UTC  ==  2015-07-01 00:00:34.600 TAI  ==  2015-07-01 00:00:15.600 GPS
    +2015-06-30 23:59:59.700 SYS  ==  2015-06-30 23:59:59.700 UTC  ==  2015-07-01 00:00:34.700 TAI  ==  2015-07-01 00:00:15.700 GPS
    +2015-06-30 23:59:59.800 SYS  ==  2015-06-30 23:59:59.800 UTC  ==  2015-07-01 00:00:34.800 TAI  ==  2015-07-01 00:00:15.800 GPS
    +2015-06-30 23:59:59.900 SYS  ==  2015-06-30 23:59:59.900 UTC  ==  2015-07-01 00:00:34.900 TAI  ==  2015-07-01 00:00:15.900 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.000 UTC  ==  2015-07-01 00:00:35.000 TAI  ==  2015-07-01 00:00:16.000 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.100 UTC  ==  2015-07-01 00:00:35.100 TAI  ==  2015-07-01 00:00:16.100 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.200 UTC  ==  2015-07-01 00:00:35.200 TAI  ==  2015-07-01 00:00:16.200 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.300 UTC  ==  2015-07-01 00:00:35.300 TAI  ==  2015-07-01 00:00:16.300 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.400 UTC  ==  2015-07-01 00:00:35.400 TAI  ==  2015-07-01 00:00:16.400 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.500 UTC  ==  2015-07-01 00:00:35.500 TAI  ==  2015-07-01 00:00:16.500 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.600 UTC  ==  2015-07-01 00:00:35.600 TAI  ==  2015-07-01 00:00:16.600 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.700 UTC  ==  2015-07-01 00:00:35.700 TAI  ==  2015-07-01 00:00:16.700 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.800 UTC  ==  2015-07-01 00:00:35.800 TAI  ==  2015-07-01 00:00:16.800 GPS
    +2015-06-30 23:59:59.999 SYS  ==  2015-06-30 23:59:60.900 UTC  ==  2015-07-01 00:00:35.900 TAI  ==  2015-07-01 00:00:16.900 GPS
    +2015-07-01 00:00:00.000 SYS  ==  2015-07-01 00:00:00.000 UTC  ==  2015-07-01 00:00:36.000 TAI  ==  2015-07-01 00:00:17.000 GPS
    +2015-07-01 00:00:00.100 SYS  ==  2015-07-01 00:00:00.100 UTC  ==  2015-07-01 00:00:36.100 TAI  ==  2015-07-01 00:00:17.100 GPS
    +2015-07-01 00:00:00.200 SYS  ==  2015-07-01 00:00:00.200 UTC  ==  2015-07-01 00:00:36.200 TAI  ==  2015-07-01 00:00:17.200 GPS
    +2015-07-01 00:00:00.300 SYS  ==  2015-07-01 00:00:00.300 UTC  ==  2015-07-01 00:00:36.300 TAI  ==  2015-07-01 00:00:17.300 GPS
    +2015-07-01 00:00:00.400 SYS  ==  2015-07-01 00:00:00.400 UTC  ==  2015-07-01 00:00:36.400 TAI  ==  2015-07-01 00:00:17.400 GPS
    +
    +
    + +

    +— end example] +

    + +

    leap