Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_unit_conversions.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
4#define _TIME_SHIELD_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
5
8
9#include "config.hpp"
10#include "constants.hpp"
11#include "detail/floor_math.hpp"
12#include "types.hpp"
13
14#include <cmath>
15#include <type_traits>
16
17namespace time_shield {
18
21
26 template<class T = int>
27 TIME_SHIELD_CONSTEXPR T ns_of_sec(fts_t ts) noexcept {
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));
30 }
31
36 template<class T = int>
37 TIME_SHIELD_CONSTEXPR T us_of_sec(fts_t ts) noexcept {
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));
40 }
41
46 template<class T = int>
47 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
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
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
76 template<class T = int>
77 TIME_SHIELD_CONSTEXPR T ms_of_sec_signed(fts_t ts) noexcept {
78 fts_t temp = 0;
79 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(MS_PER_SEC)));
80 }
81
86 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
95 template<class T = int>
96 constexpr T ms_of_ts(ts_ms_t ts) noexcept {
97 return ms_part<T>(ts);
98 }
99
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
113 template<class T = int>
114 constexpr T us_of_ts(ts_us_t ts) noexcept {
115 return us_part<T>(ts);
116 }
117
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));
125 }
126
127# ifndef TIME_SHIELD_CPP17
133 template<class T>
134 constexpr ts_ms_t sec_to_ms_impl(T t, std::true_type) noexcept {
135 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_SEC)));
136 }
137
143 template<class T>
144 constexpr ts_ms_t sec_to_ms_impl(T t, std::false_type) noexcept {
145 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_SEC);
146 }
147# endif // TIME_SHIELD_CPP17
148
154 template<class T1 = ts_ms_t, class T2>
155 constexpr T1 sec_to_ms(T2 ts) noexcept {
156# ifdef TIME_SHIELD_CPP17
157 if constexpr (std::is_floating_point_v<T2>) {
158 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_SEC)));
159 } else {
160 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_SEC);
161 }
162# else
163 return static_cast<T1>(sec_to_ms_impl(ts, typename std::conditional<
164 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
165 std::true_type,
166 std::false_type
167 >::type{}));
168# endif
169 }
170
174 inline ts_ms_t fsec_to_ms(fts_t ts) noexcept {
175 return static_cast<ts_ms_t>(std::round(ts * static_cast<fts_t>(MS_PER_SEC)));
176 }
177
183 template<class T1 = ts_t, class T2 = ts_ms_t>
184 constexpr T1 ms_to_sec(T2 ts_ms) noexcept {
185 return static_cast<T1>(detail::floor_div(
186 static_cast<int64_t>(ts_ms),
187 static_cast<int64_t>(MS_PER_SEC)));
188 }
189
194 template<class T = ts_ms_t>
195 constexpr fts_t ms_to_fsec(T ts_ms) noexcept {
196 return static_cast<fts_t>(ts_ms) / static_cast<fts_t>(MS_PER_SEC);
197 }
198
199//----------------------------------------------------------------------------//
200// Minutes -> Milliseconds
201//----------------------------------------------------------------------------//
202# ifndef TIME_SHIELD_CPP17
208 template<class T>
209 constexpr ts_ms_t min_to_ms_impl(T t, std::true_type) noexcept {
210 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_MIN)));
211 }
212
218 template<class T>
219 constexpr ts_ms_t min_to_ms_impl(T t, std::false_type) noexcept {
220 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_MIN);
221 }
222# endif // TIME_SHIELD_CPP17
223
229 template<class T1 = ts_ms_t, class T2>
230 constexpr T1 min_to_ms(T2 ts) noexcept {
231# ifdef TIME_SHIELD_CPP17
232 if constexpr (std::is_floating_point_v<T2>) {
233 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_MIN)));
234 } else {
235 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_MIN);
236 }
237# else
238 return static_cast<T1>(min_to_ms_impl(ts, typename std::conditional<
239 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
240 std::true_type,
241 std::false_type
242 >::type{}));
243# endif
244 }
245
251 template<class T1 = int, class T2 = ts_ms_t>
252 constexpr T1 ms_to_min(T2 ts) noexcept {
253 return static_cast<T1>(detail::floor_div(
254 static_cast<int64_t>(ts),
255 static_cast<int64_t>(MS_PER_MIN)));
256 }
257
258//----------------------------------------------------------------------------//
259// Minutes -> Seconds
260//----------------------------------------------------------------------------//
261# ifndef TIME_SHIELD_CPP17
267 template<class T>
268 constexpr ts_t min_to_sec_impl(T t, std::true_type) noexcept {
269 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_MIN)));
270 }
271
277 template<class T>
278 constexpr ts_t min_to_sec_impl(T t, std::false_type) noexcept {
279 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_MIN);
280 }
281# endif // TIME_SHIELD_CPP17
282
288 template<class T1 = ts_t, class T2>
289 constexpr T1 min_to_sec(T2 ts) noexcept {
290# ifdef TIME_SHIELD_CPP17
291 if constexpr (std::is_floating_point_v<T2>) {
292 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_MIN)));
293 } else {
294 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_MIN);
295 }
296# else
297 return static_cast<T1>(min_to_sec_impl(ts, typename std::conditional<
298 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
299 std::true_type,
300 std::false_type
301 >::type{}));
302# endif
303 }
304
310 template<class T1 = int, class T2 = ts_t>
311 constexpr T1 sec_to_min(T2 ts) noexcept {
312 return static_cast<T1>(detail::floor_div(
313 static_cast<int64_t>(ts),
314 static_cast<int64_t>(SEC_PER_MIN)));
315 }
316
321 template<class T = int>
322 constexpr fts_t min_to_fsec(T min) noexcept {
323 return static_cast<fts_t>(min) * static_cast<fts_t>(SEC_PER_MIN);
324 }
325
330 template<class T = ts_t>
331 constexpr double sec_to_fmin(T ts) noexcept {
332 return static_cast<double>(ts) / static_cast<double>(SEC_PER_MIN);
333 }
334
335//----------------------------------------------------------------------------//
336// Hours -> Milliseconds
337//----------------------------------------------------------------------------//
338
339# ifndef TIME_SHIELD_CPP17
345 template<class T>
346 constexpr ts_ms_t hour_to_ms_impl(T t, std::true_type) noexcept {
347 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_HOUR)));
348 }
349
355 template<class T>
356 constexpr ts_ms_t hour_to_ms_impl(T t, std::false_type) noexcept {
357 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_HOUR);
358 }
359# endif // TIME_SHIELD_CPP17
360
366 template<class T1 = ts_ms_t, class T2>
367 constexpr T1 hour_to_ms(T2 ts) noexcept {
368# ifdef TIME_SHIELD_CPP17
369 if constexpr (std::is_floating_point_v<T2>) {
370 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_HOUR)));
371 } else {
372 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_HOUR);
373 }
374# else
375 return static_cast<T1>(hour_to_ms_impl(ts, typename std::conditional<
376 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
377 std::true_type,
378 std::false_type
379 >::type{}));
380# endif
381 }
382
388 template<class T1 = int, class T2 = ts_ms_t>
389 constexpr T1 ms_to_hour(T2 ts) noexcept {
390 return static_cast<T1>(detail::floor_div(
391 static_cast<int64_t>(ts),
392 static_cast<int64_t>(MS_PER_HOUR)));
393 }
394
395//----------------------------------------------------------------------------//
396// Hours -> Seconds
397//----------------------------------------------------------------------------//
398
399# ifndef TIME_SHIELD_CPP17
405 template<class T>
406 constexpr ts_t hour_to_sec_impl(T t, std::true_type) noexcept {
407 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_HOUR)));
408 }
409
415 template<class T>
416 constexpr ts_t hour_to_sec_impl(T t, std::false_type) noexcept {
417 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_HOUR);
418 }
419# endif // TIME_SHIELD_CPP17
420
426 template<class T1 = ts_t, class T2>
427 constexpr T1 hour_to_sec(T2 ts) noexcept {
428# ifdef TIME_SHIELD_CPP17
429 if constexpr (std::is_floating_point_v<T2>) {
430 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_HOUR)));
431 } else {
432 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_HOUR);
433 }
434# else
435 return static_cast<T1>(hour_to_sec_impl(ts, typename std::conditional<
436 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
437 std::true_type,
438 std::false_type
439 >::type{}));
440# endif
441 }
442
448 template<class T1 = int, class T2 = ts_t>
449 constexpr T1 sec_to_hour(T2 ts) noexcept {
450 return static_cast<T1>(detail::floor_div(
451 static_cast<int64_t>(ts),
452 static_cast<int64_t>(SEC_PER_HOUR)));
453 }
454
459 template<class T = int>
460 constexpr fts_t hour_to_fsec(T hr) noexcept {
461 return static_cast<fts_t>(hr) * static_cast<fts_t>(SEC_PER_HOUR);
462 }
463
468 template<class T = ts_t>
469 constexpr double sec_to_fhour(T ts) noexcept {
470 return static_cast<double>(ts) / static_cast<double>(SEC_PER_HOUR);
471 }
472
477 template<class T = int>
478 TIME_SHIELD_CONSTEXPR inline T hour24_to_12(T hour) noexcept {
479 if (hour == 0 || hour > 12) return 12;
480 return hour;
481 }
482
484
485}; // namespace time_shield
486
487#endif // _TIME_SHIELD_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
Configuration macros for the library.
Header file with time-related constants.
Floor division and modulus helpers.
constexpr int64_t MS_PER_MIN
Milliseconds per minute.
Definition constants.hpp:83
constexpr int64_t SEC_PER_HOUR
Seconds per hour.
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:77
constexpr int64_t SEC_PER_MIN
Seconds per minute.
constexpr int64_t NS_PER_SEC
Nanoseconds per second.
Definition constants.hpp:73
constexpr int64_t MS_PER_HOUR
Milliseconds per hour.
Definition constants.hpp:90
constexpr int64_t US_PER_SEC
Microseconds per second.
Definition constants.hpp:76
TIME_SHIELD_CONSTEXPR T ms_of_sec_signed(fts_t ts) noexcept
Get the millisecond part of the second from a floating-point timestamp (truncating).
TIME_SHIELD_CONSTEXPR T ns_of_sec_signed(fts_t ts) noexcept
Get the nanosecond part of the second from a floating-point timestamp (truncating).
constexpr ts_ms_t sec_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting seconds to milliseconds (floating-point version).
constexpr T1 min_to_sec(T2 ts) noexcept
Converts a timestamp from minutes to seconds.
TIME_SHIELD_CONSTEXPR T us_of_sec_signed(fts_t ts) noexcept
Get the microsecond part of the second from a floating-point timestamp (truncating).
constexpr T ms_part(ts_ms_t ts) noexcept
Get the millisecond part of the timestamp.
constexpr T ns_part(T2 ts) noexcept
Get the nanosecond part of the timestamp.
constexpr ts_t hour_to_sec_impl(T t, std::true_type) noexcept
Helper function for converting hours to seconds (floating-point version).
constexpr T1 hour_to_ms(T2 ts) noexcept
Converts a timestamp from hours to milliseconds.
TIME_SHIELD_CONSTEXPR ts_t ts(year_t year, int month, int day)
Alias for to_timestamp.
constexpr T ms_of_ts(ts_ms_t ts) noexcept
Alias for ms_part.
constexpr double sec_to_fhour(T ts) noexcept
Converts a timestamp from seconds to floating-point hours.
TIME_SHIELD_CONSTEXPR T hour24_to_12(T hour) noexcept
Converts a 24-hour format hour to a 12-hour format.
constexpr T1 ms_to_hour(T2 ts) noexcept
Converts a timestamp from milliseconds to hours.
TIME_SHIELD_CONSTEXPR ts_ms_t ts_ms(year_t year, int month, int day)
Alias for to_timestamp_ms.
constexpr T1 hour_to_sec(T2 ts) noexcept
Converts a timestamp from hours to seconds.
constexpr double sec_to_fmin(T ts) noexcept
Converts a timestamp from seconds to floating-point minutes.
constexpr fts_t hour_to_fsec(T hr) noexcept
Converts a timestamp from hours to floating-point seconds.
constexpr fts_t min_to_fsec(T min) noexcept
Converts a timestamp from minutes to floating-point seconds.
constexpr T1 ms_to_sec(T2 ts_ms) noexcept
Converts a timestamp from milliseconds to seconds.
constexpr ts_ms_t hour_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting hours to milliseconds (floating-point version).
constexpr ts_t min_to_sec_impl(T t, std::true_type) noexcept
Helper function for converting minutes to seconds (floating-point version).
constexpr T1 min_to_ms(T2 ts) noexcept
Converts a timestamp from minutes to milliseconds.
constexpr T1 ms_to_min(T2 ts) noexcept
Converts a timestamp from milliseconds to minutes.
constexpr T1 sec_to_min(T2 ts) noexcept
Converts a timestamp from seconds to minutes.
constexpr T1 sec_to_hour(T2 ts) noexcept
Converts a timestamp from seconds to hours.
constexpr T1 sec_to_ms(T2 ts) noexcept
Converts a timestamp from seconds to milliseconds.
constexpr T us_of_ts(ts_us_t ts) noexcept
Alias for us_part.
constexpr ts_ms_t min_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting minutes to milliseconds (floating-point version).
constexpr fts_t ms_to_fsec(T ts_ms) noexcept
Converts a timestamp from milliseconds to floating-point seconds.
constexpr T us_part(ts_us_t ts) noexcept
Get the microsecond part of the timestamp.
ts_ms_t fsec_to_ms(fts_t ts) noexcept
Converts a floating-point timestamp from seconds to milliseconds.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:49
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:50
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:52
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
Definition types.hpp:51
T ns_of_sec() noexcept
Get the nanosecond part of the current second.
T ms_of_sec() noexcept
Get the millisecond part of the current second.
T us_of_sec() noexcept
Get the microsecond part of the current second.
TIME_SHIELD_CONSTEXPR T floor_mod(T a, T b) noexcept
Floor-mod for positive modulus (returns r in [0..b)).
TIME_SHIELD_CONSTEXPR T floor_div(T a, T b) noexcept
Floor division for positive divisor.
Main namespace for the Time Shield library.
Type definitions for time-related units and formats.