7namespace Stroika::Foundation::Time {
12 template <
typename DstTimePo
intT,
typename SrcTimePo
intT,
typename DstClockT =
typename DstTimePo
intT::clock,
typename SrcClockT =
typename SrcTimePo
intT::clock>
13 DstTimePointT clock_cast_0th (
const SrcTimePointT tp)
15 const auto src_now = SrcClockT::now ();
16 const auto dst_now = DstClockT::now ();
17 return dst_now + chrono::duration_cast<typename DstClockT::duration> (tp - src_now);
20 template <
typename DurationT,
typename ReprT =
typename DurationT::rep>
21 constexpr DurationT max_duration () noexcept
23 return DurationT{std::numeric_limits<ReprT>::max ()};
25 template <
typename DurationT>
26 constexpr DurationT abs_duration (
const DurationT d)
noexcept
28 return DurationT{(d.count () < 0) ? -d.count () : d.count ()};
31 template <
typename DstTimePointT,
typename SrcTimePointT,
typename DstDurationT =
typename DstTimePointT::duration,
typename SrcDurationT =
typename SrcTimePointT::duration,
32 typename DstClockT =
typename DstTimePointT::clock,
typename SrcClockT =
typename SrcTimePointT::clock>
33 DstTimePointT clock_cast_2nd (
const SrcTimePointT tp,
34 const SrcDurationT tolerance = std::chrono::duration_cast<SrcDurationT> (std::chrono::nanoseconds{100}),
39 auto src_now = SrcTimePointT{};
40 auto dst_now = DstTimePointT{};
41 auto epsilon = detail::max_duration<SrcDurationT> ();
43 const auto src_before = SrcClockT::now ();
44 const auto dst_between = DstClockT::now ();
45 const auto src_after = SrcClockT::now ();
46 const auto src_diff = src_after - src_before;
47 const auto delta = detail::abs_duration (src_diff);
48 if (delta < epsilon) {
49 src_now = src_before + src_diff / 2;
50 dst_now = dst_between;
51 epsilon = std::chrono::duration_cast<SrcDurationT> (delta);
53 if (++itercnt >= limit)
55 }
while (epsilon > tolerance);
56 return dst_now + chrono::duration_cast<typename DstClockT::duration> (tp - src_now);
58#if __cpp_lib_chrono >= 201907L
61 template <
typename DESTINATION_CLOCK_T,
typename SOURCE_CLOCK_T,
typename DURATION_T>
62 constexpr bool kCanUseStdClockCnv_ =
63 same_as<DESTINATION_CLOCK_T,SOURCE_CLOCK_T>
65 ( same_as<DESTINATION_CLOCK_T, chrono::system_clock> or same_as<DESTINATION_CLOCK_T, chrono::utc_clock> or same_as<DESTINATION_CLOCK_T, chrono::gps_clock> or same_as<DESTINATION_CLOCK_T, chrono::file_clock> or same_as<DESTINATION_CLOCK_T, chrono::tai_clock>)
66 and (same_as<SOURCE_CLOCK_T, chrono::system_clock> or same_as<SOURCE_CLOCK_T, chrono::utc_clock> or same_as<SOURCE_CLOCK_T, chrono::gps_clock> or same_as<SOURCE_CLOCK_T, chrono::file_clock> or same_as<SOURCE_CLOCK_T, chrono::tai_clock>)
71 template <
typename DESTINATION_CLOCK_T,
typename SOURCE_CLOCK_T,
typename DURATION_T>
72 constexpr bool kCanUseStdClockCnv_ =
false;
81 template <
typename DESTINATION_CLOCK_T,
typename SOURCE_CLOCK_T,
typename DURATION_T>
82 inline auto clock_cast (chrono::time_point<SOURCE_CLOCK_T, DURATION_T> tp) ->
typename DESTINATION_CLOCK_T::time_point
84#if __cpp_lib_chrono >= 201907L
85 if constexpr (Private_::kCanUseStdClockCnv_<DESTINATION_CLOCK_T, SOURCE_CLOCK_T, DURATION_T>) {
86 return chrono::clock_cast<DESTINATION_CLOCK_T> (tp);
89 return Private_::clock_cast_2nd<typename DESTINATION_CLOCK_T::time_point> (tp);
91 template <
typename DESTINATION_CLOCK_T,
template <
typename>
typename RANGE,
typename SOURCE_CLOCK_T,
typename DURATION_T>
92 RANGE<typename DESTINATION_CLOCK_T::time_point> clock_cast (RANGE<chrono::time_point<SOURCE_CLOCK_T, DURATION_T>> tpRange)
94 using RESULT_TIMERANGE =
typename DESTINATION_CLOCK_T::time_point;
95 using RESULT_RANGE_TYPE = RANGE<RESULT_TIMERANGE>;
96 if (tpRange.empty ()) {
97 return RESULT_RANGE_TYPE{};
108 if constexpr (Private_::kCanUseStdClockCnv_<DESTINATION_CLOCK_T, SOURCE_CLOCK_T, DURATION_T>) {
109 return RESULT_RANGE_TYPE{clock_cast<DESTINATION_CLOCK_T> (tpRange.GetLowerBound ()),
110 Time::clock_cast<DESTINATION_CLOCK_T> (tpRange.GetUpperBound ())};
113 typename DESTINATION_CLOCK_T::time_point lb = clock_cast<DESTINATION_CLOCK_T> (tpRange.GetLowerBound ());
114 auto diff = lb.time_since_epoch () - tpRange.GetLowerBound ().time_since_epoch ();
115 return RESULT_RANGE_TYPE{lb, RESULT_TIMERANGE{tpRange.GetUpperBound ().time_since_epoch () + diff}};
124 template <
typename BASE_CLOCK_T,
typename DURATION_T>
125 [[nodiscard]]
inline auto AppStartZeroedClock<BASE_CLOCK_T, DURATION_T>::now () noexcept -> time_point
127 return time_point{Implementation_::now ().time_since_epoch ()} - kTimeAppStartedOffset_;