diff --git a/docs/use_cases/interoperability.rst b/docs/use_cases/interoperability.rst index ca967d30..694d5346 100644 --- a/docs/use_cases/interoperability.rst +++ b/docs/use_cases/interoperability.rst @@ -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 Q> - constexpr auto to_std_duration(const Q& q); - - an alias that provides a conversion from `ratio` to ``std::ratio``:: template using to_std_ratio = /* ... */ + +- an explicit conversion of `quantity` of `isq::si::dim_time` to ``std::chrono::duration``:: + + template + [[nodiscard]] constexpr auto to_std_duration(const quantity& q) + +- an explicit conversion of `quantity_point` that previously originated from ``std::chrono`` + to ``std::chrono::time_point``:: + + template + [[nodiscard]] constexpr auto to_std_time_point(const quantity_point, 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, 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(tp); + const auto tp_days = std::chrono::floor(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); diff --git a/src/core/include/units/chrono.h b/src/core/include/units/chrono.h index 8e040de2..df29e486 100644 --- a/src/core/include/units/chrono.h +++ b/src/core/include/units/chrono.h @@ -47,8 +47,7 @@ struct quantity_point_like_traits; using unit = downcast_unit; using rep = Rep; - [[nodiscard]] static constexpr auto relative( - const std::chrono::time_point>& qp) { + [[nodiscard]] static constexpr auto relative(const std::chrono::time_point>& qp) { return qp.time_since_epoch(); } }; @@ -84,10 +83,17 @@ constexpr auto to_std_ratio_impl() template using to_std_ratio = decltype(detail::to_std_ratio_impl()); -template Q> -constexpr auto to_std_duration(const Q& q) +template +[[nodiscard]] constexpr auto to_std_duration(const quantity& q) { - return std::chrono::duration>(q.number()); + return std::chrono::duration>(q.number()); +} + +template +[[nodiscard]] constexpr auto to_std_time_point(const quantity_point, U, Rep>& qp) +{ + using ret_type = std::chrono::time_point>>; + return ret_type(to_std_duration(qp.relative())); } } // namespace units diff --git a/test/unit_test/static/chrono_test.cpp b/test/unit_test/static/chrono_test.cpp index d5592de2..547bebe6 100644 --- a/test/unit_test/static/chrono_test.cpp +++ b/test/unit_test/static/chrono_test.cpp @@ -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{2_q_s}); static_assert(quantity_point{sys_seconds{1s}} + 1_q_min == time_point{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>); static_assert(is_same_v>); static_assert(is_same_v); +// 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