feat: conversion from quantity_point to std::chrono::time_point added

Refers #316
This commit is contained in:
Mateusz Pusz
2021-11-23 14:37:08 +01:00
parent af928dd0c7
commit 571df5ed33
3 changed files with 59 additions and 11 deletions

View File

@@ -79,12 +79,47 @@ They are provided in a dedicated header file::
The same header file provides additional conversion helpers from ``mp-units`` to
the C++ Standard Library types:
- an explicit conversion of `quantity` to ``std::chrono::duration``::
template<QuantityOf<isq::si::dim_time> Q>
constexpr auto to_std_duration(const Q& q);
- an alias that provides a conversion from `ratio` to ``std::ratio``::
template<ratio R>
using to_std_ratio = /* ... */
- an explicit conversion of `quantity` of `isq::si::dim_time` to ``std::chrono::duration``::
template<typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_duration(const quantity<isq::si::dim_time, U, Rep>& q)
- an explicit conversion of `quantity_point` that previously originated from ``std::chrono``
to ``std::chrono::time_point``::
template<typename C, typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_time_point(const quantity_point<clock_origin<C>, U, Rep>& qp)
.. note::
Only `quantity_point` that was created from a ``std::chrono::time_point`` of a specific
``std::chrono`` clock can be converted back to ``std::chrono`` domain::
const auto qp1 = quantity_point{sys_seconds{1s}};
const auto tp1 = to_std_time_point(qp1); // OK
conat auto qp2 = quantity_point{1 * s};
const auto tp2 = to_std_time_point(qp2); // Compile-time Error
Here is an example of how interoperatibility described in this chapter can be used in practice::
using namespace units::aliases::isq::si;
using timestamp = quantity_point<clock_origin<std::chrono::system_clock>, si::second>;
const auto start_time = timestamp(std::chrono::system_clock::now()); // std::chrono -> units
const auto velocity = speed::km_per_h<>(825);
const auto distance = length::km<>(8111);
const auto flight_time = distance / velocity;
const auto exp_end_time = start_time + flight_time;
const auto tp = to_std_time_point(exp_end_time); // units -> std::chrono
const auto tp_sec = std::chrono::floor<std::chrono::seconds>(tp);
const auto tp_days = std::chrono::floor<std::chrono::days>(tp_sec);
const auto ymd = std::chrono::year_month_day(tp_days);
const auto tod = tp_sec - tp_days;
const auto hms = std::chrono::hh_mm_ss(tod);

View File

@@ -47,8 +47,7 @@ struct quantity_point_like_traits<std::chrono::time_point<C, std::chrono::durati
using origin = clock_origin<C>;
using unit = downcast_unit<typename origin::dimension, ratio(Period::num, Period::den)>;
using rep = Rep;
[[nodiscard]] static constexpr auto relative(
const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
[[nodiscard]] static constexpr auto relative(const std::chrono::time_point<C, std::chrono::duration<Rep, Period>>& qp) {
return qp.time_since_epoch();
}
};
@@ -84,10 +83,17 @@ constexpr auto to_std_ratio_impl()
template<auto R>
using to_std_ratio = decltype(detail::to_std_ratio_impl<R>());
template<QuantityOf<isq::si::dim_time> Q>
constexpr auto to_std_duration(const Q& q)
template<typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_duration(const quantity<isq::si::dim_time, U, Rep>& q)
{
return std::chrono::duration<typename Q::rep, to_std_ratio<Q::unit::ratio>>(q.number());
return std::chrono::duration<Rep, to_std_ratio<U::ratio>>(q.number());
}
template<typename C, typename U, typename Rep>
[[nodiscard]] constexpr auto to_std_time_point(const quantity_point<clock_origin<C>, U, Rep>& qp)
{
using ret_type = std::chrono::time_point<C, std::chrono::duration<Rep, to_std_ratio<U::ratio>>>;
return ret_type(to_std_duration(qp.relative()));
}
} // namespace units

View File

@@ -90,12 +90,19 @@ static_assert(10_q_m / quantity{2s} == 5_q_m_per_s);
static_assert(quantity_point{sys_seconds{1s}} + 1_q_s == time_point<std::chrono::system_clock, si::second>{2_q_s});
static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == time_point<std::chrono::system_clock, si::second>{61_q_s});
// to_duration
// to_std_duration
static_assert(to_std_duration(1_q_s) == 1s);
static_assert(to_std_duration(2_q_h) == 2h);
static_assert(to_std_duration(3_q_ns) == 3ns);
static_assert(to_std_duration(quantity{1s}) == 1s);
static_assert(to_std_duration(quantity{2h}) == 2h);
static_assert(to_std_duration(quantity{3ns}) == 3ns);
static_assert(is_same_v<decltype(to_std_duration(1_q_s))::period, std::ratio<1>>);
static_assert(is_same_v<decltype(to_std_duration(2_q_h))::period, std::ratio<3600>>);
static_assert(is_same_v<decltype(to_std_duration(3_q_ns))::period, std::nano>);
// to_std_time_point
static_assert(to_std_time_point(quantity_point{sys_seconds{1s}}) == sys_seconds{1s});
static_assert(to_std_time_point(quantity_point{sys_days{sys_days::duration{1}}}) == sys_days{sys_days::duration{1}});
} // namespace