c ++ 11时钟/ time_points之间的隐式转换

问题描述 投票:2回答:1

是否可以在两个C ++ 11时钟的time_points之间进行隐式/显式转换?

动机:chrono::durations提供了从纪元存储时间间隔的方法,概念上不等于自己有时代的自定义时钟的time_point。在时钟之间进行隐式转换可以减少使用Howard Hinnant的date library <date/date.h>,它提供了操作和打印系统时钟的time_points的方法。

例:

#include <date/date.h>
using namespace date;
namespace ch = std::chrono;
// 
#define EPOCH_OFFSET 100
template<class Duration> using PosixTimePoint = 
                   ch::time_point<ch::system_clock, Duration>;
typedef PosixTimePoint<ch::duration<long,std::micro>> PosixTimePointType;

struct SomeClock{
    typedef ch::duration<long,std::micro>   duration;
    typedef ch::time_point<SomeClock>  time_point;

    ...
    static time_point now() noexcept {
        using namespace std::chrono;
        return time_point (
            duration_cast<duration>( 
                system_clock::now().time_since_epoch()) + date::years(EPOCH_OFFSET) );
    }
    static PosixTimePoint<duration> to_posix( const time_point& tp  ){...}

}
auto tp = SomeClock::now(); //<time_point<SomeClock,ch::duration<long,std::micro>>;

目标:转换tp使std::stream转换date.h工作并打印出当前时间,在我的情况下是:2017-12-24 17:02:56.000000

// std::cout << tp; compile error
std::cout << SomeClock::to_posix( tp ); // OK

显式演员:这可以降低可读性,支持语言的转换功能并便于访问date.h例程。

long time_value = static_cast<long>( tp );
auto st = static_cast<PosixTimePointType>( tp ); 
std::cout << static_cast<PosixTimePointType>( tp );
date c++11 time chrono
1个回答
1
投票

我建议模仿在date::utc_clock中找到的date::tai_clocktz.h的实现。例如,utc_clock实现了两个函数来转换为sys_time和从template<typename Duration> static std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, std::chrono::seconds>::type> to_sys(const std::chrono::time_point<utc_clock, Duration>&); template<typename Duration> static std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type> from_sys(const std::chrono::time_point<std::chrono::system_clock, Duration>&); 转换:

std::chrono::system_clock

因此,您可以将system_clock视为“中心”。实现这些转换的任何时钟都可以转换为任何其他时钟,通过弹出date::clock_cast来实现这些转换。为了促进这种反弹,引入了utc_time

此外,如果对您的类型更有效,tai_clock可以用作中心。例如template<typename Duration> static std::chrono::time_point<utc_clock, typename std::common_type<Duration, std::chrono::seconds>::type> to_utc(const std::chrono::time_point<tai_clock, Duration>&) NOEXCEPT; template<typename Duration> static std::chrono::time_point<tai_clock, typename std::common_type<Duration, std::chrono::seconds>::type> from_utc(const std::chrono::time_point<utc_clock, Duration>&) NOEXCEPT; 实现:

clock_cast

utc_time非常聪明,可以处理这种“双集线器”系统,因此可以将转换为/从sys_time转换的时钟转换为使用to_stream作为其集线器的另一个时钟。

如果你还为你的时钟实现format,那么你可以直接使用clock::time_point格式化你的clock_castto_stream可能对你的from_stream函数的实现很有用。

clock::time_point也可以用来将你的date::parse挂到https://howardhinnant.github.io/date/tz.html

搜索clock_cast的“to_sys”,例如使用它。对于您的用例,from_sys / clock_cast API似乎是最有用的。只需这两个函数就可以在SomeClock和tz.h中的任何其他时钟(以及满足这些要求的任何其他自定义时钟)之间使用#include "date/tz.h" #include <iostream> #include <sstream> struct SomeClock { using duration = std::chrono::microseconds; using rep = duration::rep; using period = duration::period; using time_point = std::chrono::time_point<SomeClock>; static constexpr bool is_steady = false; static time_point now() noexcept { return from_sys(date::floor<duration>(std::chrono::system_clock::now())); } static constexpr auto offset = date::sys_days{} - date::sys_days{date::year{1870}/1/1}; template<typename Duration> static date::sys_time<Duration> to_sys(const std::chrono::time_point<SomeClock, Duration>& t) { return date::sys_time<Duration>{(t - offset).time_since_epoch()}; } template<typename Duration> static std::chrono::time_point<SomeClock, Duration> from_sys(const date::sys_time<Duration>& t) { return std::chrono::time_point<SomeClock, Duration>{(t + offset).time_since_epoch()}; } }; template <class Duration> using SomeTime = std::chrono::time_point<SomeClock, Duration>; constexpr date::days SomeClock::offset; template <class CharT, class Traits, class Duration> std::basic_ostream<CharT, Traits>& to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const SomeTime<Duration>& t) { return date::to_stream(os, fmt, date::clock_cast<std::chrono::system_clock>(t)); } template <class CharT, class Traits, class Duration> std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const SomeTime<Duration>& t) { const CharT fmt[] = {'%', 'F', ' ', '%', 'T', CharT{}}; return to_stream(os, fmt, t); } template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>> std::basic_istream<CharT, Traits>& from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, SomeTime<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace date; sys_time<Duration> st; date::from_stream(is, fmt, st, abbrev, offset); if (!is.fail()) tp = clock_cast<SomeClock>(st); return is; } int main() { std::cout << SomeClock::now() << '\n'; std::cout << date::format("%a, %b %d, %Y\n", SomeClock::now()); std::istringstream in{"2017-12-24 19:52:30"}; SomeClock::time_point t; in >> date::parse("%F %T", t); std::cout << t << '\n'; }


完整的演示

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.