88
99#include " config.hpp"
1010#include " constants.hpp"
11+ #include " detail/floor_math.hpp"
1112#include " types.hpp"
1213
1314#include < cmath>
@@ -24,8 +25,8 @@ namespace time_shield {
2425 // / \return T Nanosecond part of the second.
2526 template <class T = int >
2627 TIME_SHIELD_CONSTEXPR T ns_of_sec (fts_t ts) noexcept {
27- fts_t temp = 0 ;
28- return static_cast <T>(std::round ( std::modf (ts, &temp) * static_cast < fts_t >( NS_PER_SEC) ));
28+ const int64_t ns = static_cast < int64_t >( std::floor (ts * static_cast < fts_t >(NS_PER_SEC))) ;
29+ return static_cast <T>(detail::floor_mod< int64_t >(ns, NS_PER_SEC));
2930 }
3031
3132 // / \brief Get the microsecond part of the second from a floating-point timestamp.
@@ -34,8 +35,8 @@ namespace time_shield {
3435 // / \return T Microsecond part of the second.
3536 template <class T = int >
3637 TIME_SHIELD_CONSTEXPR T us_of_sec (fts_t ts) noexcept {
37- fts_t temp = 0 ;
38- return static_cast <T>(std::round ( std::modf (ts, &temp) * static_cast < fts_t >( US_PER_SEC) ));
38+ const int64_t us = static_cast < int64_t >( std::floor (ts * static_cast < fts_t >(US_PER_SEC))) ;
39+ return static_cast <T>(detail::floor_mod< int64_t >(us, US_PER_SEC));
3940 }
4041
4142 // / \brief Get the millisecond part of the second from a floating-point timestamp.
@@ -44,6 +45,36 @@ namespace time_shield {
4445 // / \return T Millisecond part of the second.
4546 template <class T = int >
4647 TIME_SHIELD_CONSTEXPR T ms_of_sec (fts_t ts) noexcept {
48+ const int64_t ms = static_cast <int64_t >(std::floor (ts * static_cast <fts_t >(MS_PER_SEC)));
49+ return static_cast <T>(detail::floor_mod<int64_t >(ms, MS_PER_SEC));
50+ }
51+
52+ // / \brief Get the nanosecond part of the second from a floating-point timestamp (truncating).
53+ // / \tparam T Type of the returned value (default is int).
54+ // / \param ts Timestamp in floating-point seconds.
55+ // / \return T Nanosecond part of the second, truncating toward zero.
56+ template <class T = int >
57+ TIME_SHIELD_CONSTEXPR T ns_of_sec_signed (fts_t ts) noexcept {
58+ fts_t temp = 0 ;
59+ return static_cast <T>(std::round (std::modf (ts, &temp) * static_cast <fts_t >(NS_PER_SEC)));
60+ }
61+
62+ // / \brief Get the microsecond part of the second from a floating-point timestamp (truncating).
63+ // / \tparam T Type of the returned value (default is int).
64+ // / \param ts Timestamp in floating-point seconds.
65+ // / \return T Microsecond part of the second, truncating toward zero.
66+ template <class T = int >
67+ TIME_SHIELD_CONSTEXPR T us_of_sec_signed (fts_t ts) noexcept {
68+ fts_t temp = 0 ;
69+ return static_cast <T>(std::round (std::modf (ts, &temp) * static_cast <fts_t >(US_PER_SEC)));
70+ }
71+
72+ // / \brief Get the millisecond part of the second from a floating-point timestamp (truncating).
73+ // / \tparam T Type of the returned value (default is int).
74+ // / \param ts Timestamp in floating-point seconds.
75+ // / \return T Millisecond part of the second, truncating toward zero.
76+ template <class T = int >
77+ TIME_SHIELD_CONSTEXPR T ms_of_sec_signed (fts_t ts) noexcept {
4778 fts_t temp = 0 ;
4879 return static_cast <T>(std::round (std::modf (ts, &temp) * static_cast <fts_t >(MS_PER_SEC)));
4980 }
@@ -53,8 +84,44 @@ namespace time_shield {
5384 // / \param ts Timestamp in milliseconds.
5485 // / \return T Millisecond part of the timestamp.
5586 template <class T = int >
87+ constexpr T ms_part (ts_ms_t ts) noexcept {
88+ return static_cast <T>(detail::floor_mod<int64_t >(static_cast <int64_t >(ts), MS_PER_SEC));
89+ }
90+
91+ // / \brief Alias for ms_part.
92+ // / \tparam T Type of the returned value (default is int).
93+ // / \param ts Timestamp in milliseconds.
94+ // / \return T Millisecond part of the timestamp.
95+ template <class T = int >
5696 constexpr T ms_of_ts (ts_ms_t ts) noexcept {
57- return static_cast <T>(ts % MS_PER_SEC);
97+ return ms_part<T>(ts);
98+ }
99+
100+ // / \brief Get the microsecond part of the timestamp.
101+ // / \tparam T Type of the returned value (default is int).
102+ // / \param ts Timestamp in microseconds.
103+ // / \return T Microsecond part of the timestamp.
104+ template <class T = int >
105+ constexpr T us_part (ts_us_t ts) noexcept {
106+ return static_cast <T>(detail::floor_mod<int64_t >(static_cast <int64_t >(ts), US_PER_SEC));
107+ }
108+
109+ // / \brief Alias for us_part.
110+ // / \tparam T Type of the returned value (default is int).
111+ // / \param ts Timestamp in microseconds.
112+ // / \return T Microsecond part of the timestamp.
113+ template <class T = int >
114+ constexpr T us_of_ts (ts_us_t ts) noexcept {
115+ return us_part<T>(ts);
116+ }
117+
118+ // / \brief Get the nanosecond part of the timestamp.
119+ // / \tparam T Type of the returned value (default is int).
120+ // / \param ts Timestamp in nanoseconds.
121+ // / \return T Nanosecond part of the timestamp.
122+ template <class T = int , class T2 = int64_t >
123+ constexpr T ns_part (T2 ts) noexcept {
124+ return static_cast <T>(detail::floor_mod<int64_t >(static_cast <int64_t >(ts), NS_PER_SEC));
58125 }
59126
60127# ifndef TIME_SHIELD_CPP17
@@ -115,7 +182,9 @@ namespace time_shield {
115182 // / \return T1 Timestamp in seconds.
116183 template <class T1 = ts_t , class T2 = ts_ms_t >
117184 constexpr T1 ms_to_sec (T2 ts_ms) noexcept {
118- return static_cast <T1>(ts_ms) / static_cast <T1>(MS_PER_SEC);
185+ return static_cast <T1>(detail::floor_div (
186+ static_cast <int64_t >(ts_ms),
187+ static_cast <int64_t >(MS_PER_SEC)));
119188 }
120189
121190 // / \brief Converts a timestamp from milliseconds to floating-point seconds.
@@ -181,7 +250,9 @@ namespace time_shield {
181250 // / \return T1 Timestamp in minutes.
182251 template <class T1 = int , class T2 = ts_ms_t >
183252 constexpr T1 ms_to_min (T2 ts) noexcept {
184- return static_cast <T1>(ts) / static_cast <T1>(MS_PER_MIN);
253+ return static_cast <T1>(detail::floor_div (
254+ static_cast <int64_t >(ts),
255+ static_cast <int64_t >(MS_PER_MIN)));
185256 }
186257
187258// ----------------------------------------------------------------------------//
@@ -238,7 +309,9 @@ namespace time_shield {
238309 // / \return T1 Timestamp in minutes.
239310 template <class T1 = int , class T2 = ts_t >
240311 constexpr T1 sec_to_min (T2 ts) noexcept {
241- return static_cast <T1>(ts) / static_cast <T1>(SEC_PER_MIN);
312+ return static_cast <T1>(detail::floor_div (
313+ static_cast <int64_t >(ts),
314+ static_cast <int64_t >(SEC_PER_MIN)));
242315 }
243316
244317 // / \brief Converts a timestamp from minutes to floating-point seconds.
@@ -314,7 +387,9 @@ namespace time_shield {
314387 // / \return T1 Timestamp in hours.
315388 template <class T1 = int , class T2 = ts_ms_t >
316389 constexpr T1 ms_to_hour (T2 ts) noexcept {
317- return static_cast <T1>(ts) / static_cast <T1>(MS_PER_HOUR);
390+ return static_cast <T1>(detail::floor_div (
391+ static_cast <int64_t >(ts),
392+ static_cast <int64_t >(MS_PER_HOUR)));
318393 }
319394
320395// ----------------------------------------------------------------------------//
@@ -372,7 +447,9 @@ namespace time_shield {
372447 // / \return T1 Timestamp in hours.
373448 template <class T1 = int , class T2 = ts_t >
374449 constexpr T1 sec_to_hour (T2 ts) noexcept {
375- return static_cast <T1>(ts) / static_cast <T1>(SEC_PER_HOUR);
450+ return static_cast <T1>(detail::floor_div (
451+ static_cast <int64_t >(ts),
452+ static_cast <int64_t >(SEC_PER_HOUR)));
376453 }
377454
378455 // / \brief Converts a timestamp from hours to floating-point seconds.
0 commit comments