Time Shield Library 2.0.0
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_HEADER_CONVERSIONS_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
4#define TIME_SHIELD_HEADER_CONVERSIONS_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
5
8
10#include "detail/floor_math.hpp"
11
12#include <cmath>
13#include <type_traits>
14
15namespace time_shield {
16
19
24 template<class T = int>
25 TIME_SHIELD_CONSTEXPR T ns_of_sec(fts_t ts) noexcept {
26 const int64_t ns = static_cast<int64_t>(std::floor(ts * static_cast<fts_t>(NS_PER_SEC)));
27 return static_cast<T>(detail::floor_mod<int64_t>(ns, NS_PER_SEC));
28 }
29
34 template<class T = int>
35 TIME_SHIELD_CONSTEXPR T us_of_sec(fts_t ts) noexcept {
36 const int64_t us = static_cast<int64_t>(std::floor(ts * static_cast<fts_t>(US_PER_SEC)));
37 return static_cast<T>(detail::floor_mod<int64_t>(us, US_PER_SEC));
38 }
39
44 template<class T = int>
45 TIME_SHIELD_CONSTEXPR T ms_of_sec(fts_t ts) noexcept {
46 const int64_t ms = static_cast<int64_t>(std::floor(ts * static_cast<fts_t>(MS_PER_SEC)));
47 return static_cast<T>(detail::floor_mod<int64_t>(ms, MS_PER_SEC));
48 }
49
54 template<class T = int>
55 TIME_SHIELD_CONSTEXPR T ns_of_sec_signed(fts_t ts) noexcept {
56 fts_t temp = 0;
57 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(NS_PER_SEC)));
58 }
59
64 template<class T = int>
65 TIME_SHIELD_CONSTEXPR T us_of_sec_signed(fts_t ts) noexcept {
66 fts_t temp = 0;
67 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(US_PER_SEC)));
68 }
69
74 template<class T = int>
75 TIME_SHIELD_CONSTEXPR T ms_of_sec_signed(fts_t ts) noexcept {
76 fts_t temp = 0;
77 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(MS_PER_SEC)));
78 }
79
84 template<class T = int>
85 TIME_SHIELD_CONSTEXPR T ms_part(ts_ms_t ts) noexcept {
86 return static_cast<T>(detail::floor_mod<int64_t>(static_cast<int64_t>(ts), MS_PER_SEC));
87 }
88
93 template<class T = int>
94 TIME_SHIELD_CONSTEXPR T ms_of_ts(ts_ms_t ts) noexcept {
95 return ms_part<T>(ts);
96 }
97
102 template<class T = int>
103 TIME_SHIELD_CONSTEXPR T us_part(ts_us_t ts) noexcept {
104 return static_cast<T>(detail::floor_mod<int64_t>(static_cast<int64_t>(ts), US_PER_SEC));
105 }
106
111 template<class T = int>
112 TIME_SHIELD_CONSTEXPR T us_of_ts(ts_us_t ts) noexcept {
113 return us_part<T>(ts);
114 }
115
120 template<class T = int, class T2 = int64_t>
121 TIME_SHIELD_CONSTEXPR T ns_part(T2 ts) noexcept {
122 return static_cast<T>(detail::floor_mod<int64_t>(static_cast<int64_t>(ts), NS_PER_SEC));
123 }
124
125# ifndef TIME_SHIELD_CPP17
130 template<class T>
131 TIME_SHIELD_CONSTEXPR ts_ms_t sec_to_ms_impl(T t, std::true_type) noexcept {
132 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_SEC)));
133 }
134
139 template<class T>
140 TIME_SHIELD_CONSTEXPR ts_ms_t sec_to_ms_impl(T t, std::false_type) noexcept {
141 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_SEC);
142 }
143# endif // TIME_SHIELD_CPP17
144
150 template<class T1 = ts_ms_t, class T2>
151 TIME_SHIELD_CONSTEXPR T1 sec_to_ms(T2 ts) noexcept {
152# ifdef TIME_SHIELD_CPP17
153 if constexpr (std::is_floating_point_v<T2>) {
154 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_SEC)));
155 } else {
156 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_SEC);
157 }
158# else
159 return static_cast<T1>(sec_to_ms_impl(ts, typename std::conditional<
160 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
161 std::true_type,
162 std::false_type
163 >::type{}));
164# endif
165 }
166
170 inline ts_ms_t fsec_to_ms(fts_t ts) noexcept {
171 return static_cast<ts_ms_t>(std::round(ts * static_cast<fts_t>(MS_PER_SEC)));
172 }
173
179 template<class T1 = ts_t, class T2 = ts_ms_t>
180 TIME_SHIELD_CONSTEXPR T1 ms_to_sec(T2 ts_ms) noexcept {
181 return static_cast<T1>(detail::floor_div(
182 static_cast<int64_t>(ts_ms),
183 static_cast<int64_t>(MS_PER_SEC)));
184 }
185
190 template<class T = ts_ms_t>
191 TIME_SHIELD_CONSTEXPR fts_t ms_to_fsec(T ts_ms) noexcept {
192 return static_cast<fts_t>(ts_ms) / static_cast<fts_t>(MS_PER_SEC);
193 }
194
195//----------------------------------------------------------------------------//
196// Minutes -> Milliseconds
197//----------------------------------------------------------------------------//
198# ifndef TIME_SHIELD_CPP17
203 template<class T>
204 TIME_SHIELD_CONSTEXPR ts_ms_t min_to_ms_impl(T t, std::true_type) noexcept {
205 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_MIN)));
206 }
207
212 template<class T>
213 TIME_SHIELD_CONSTEXPR ts_ms_t min_to_ms_impl(T t, std::false_type) noexcept {
214 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_MIN);
215 }
216# endif // TIME_SHIELD_CPP17
217
223 template<class T1 = ts_ms_t, class T2>
224 TIME_SHIELD_CONSTEXPR T1 min_to_ms(T2 ts) noexcept {
225# ifdef TIME_SHIELD_CPP17
226 if constexpr (std::is_floating_point_v<T2>) {
227 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_MIN)));
228 } else {
229 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_MIN);
230 }
231# else
232 return static_cast<T1>(min_to_ms_impl(ts, typename std::conditional<
233 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
234 std::true_type,
235 std::false_type
236 >::type{}));
237# endif
238 }
239
245 template<class T1 = int, class T2 = ts_ms_t>
246 TIME_SHIELD_CONSTEXPR T1 ms_to_min(T2 ts) noexcept {
247 return static_cast<T1>(detail::floor_div(
248 static_cast<int64_t>(ts),
249 static_cast<int64_t>(MS_PER_MIN)));
250 }
251
252//----------------------------------------------------------------------------//
253// Minutes -> Seconds
254//----------------------------------------------------------------------------//
255# ifndef TIME_SHIELD_CPP17
260 template<class T>
261 TIME_SHIELD_CONSTEXPR ts_t min_to_sec_impl(T t, std::true_type) noexcept {
262 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_MIN)));
263 }
264
269 template<class T>
270 TIME_SHIELD_CONSTEXPR ts_t min_to_sec_impl(T t, std::false_type) noexcept {
271 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_MIN);
272 }
273# endif // TIME_SHIELD_CPP17
274
280 template<class T1 = ts_t, class T2>
281 TIME_SHIELD_CONSTEXPR T1 min_to_sec(T2 ts) noexcept {
282# ifdef TIME_SHIELD_CPP17
283 if constexpr (std::is_floating_point_v<T2>) {
284 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_MIN)));
285 } else {
286 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_MIN);
287 }
288# else
289 return static_cast<T1>(min_to_sec_impl(ts, typename std::conditional<
290 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
291 std::true_type,
292 std::false_type
293 >::type{}));
294# endif
295 }
296
302 template<class T1 = int, class T2 = ts_t>
303 TIME_SHIELD_CONSTEXPR T1 sec_to_min(T2 ts) noexcept {
304 return static_cast<T1>(detail::floor_div(
305 static_cast<int64_t>(ts),
306 static_cast<int64_t>(SEC_PER_MIN)));
307 }
308
313 template<class T = int>
314 TIME_SHIELD_CONSTEXPR fts_t min_to_fsec(T min) noexcept {
315 return static_cast<fts_t>(min) * static_cast<fts_t>(SEC_PER_MIN);
316 }
317
322 template<class T = ts_t>
323 TIME_SHIELD_CONSTEXPR double sec_to_fmin(T ts) noexcept {
324 return static_cast<double>(ts) / static_cast<double>(SEC_PER_MIN);
325 }
326
327//----------------------------------------------------------------------------//
328// Hours -> Milliseconds
329//----------------------------------------------------------------------------//
330
331# ifndef TIME_SHIELD_CPP17
336 template<class T>
337 TIME_SHIELD_CONSTEXPR ts_ms_t hour_to_ms_impl(T t, std::true_type) noexcept {
338 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_HOUR)));
339 }
340
345 template<class T>
346 TIME_SHIELD_CONSTEXPR ts_ms_t hour_to_ms_impl(T t, std::false_type) noexcept {
347 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_HOUR);
348 }
349# endif // TIME_SHIELD_CPP17
350
356 template<class T1 = ts_ms_t, class T2>
357 TIME_SHIELD_CONSTEXPR T1 hour_to_ms(T2 ts) noexcept {
358# ifdef TIME_SHIELD_CPP17
359 if constexpr (std::is_floating_point_v<T2>) {
360 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_HOUR)));
361 } else {
362 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_HOUR);
363 }
364# else
365 return static_cast<T1>(hour_to_ms_impl(ts, typename std::conditional<
366 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
367 std::true_type,
368 std::false_type
369 >::type{}));
370# endif
371 }
372
378 template<class T1 = int, class T2 = ts_ms_t>
379 TIME_SHIELD_CONSTEXPR T1 ms_to_hour(T2 ts) noexcept {
380 return static_cast<T1>(detail::floor_div(
381 static_cast<int64_t>(ts),
382 static_cast<int64_t>(MS_PER_HOUR)));
383 }
384
385//----------------------------------------------------------------------------//
386// Hours -> Seconds
387//----------------------------------------------------------------------------//
388
389# ifndef TIME_SHIELD_CPP17
394 template<class T>
395 TIME_SHIELD_CONSTEXPR ts_t hour_to_sec_impl(T t, std::true_type) noexcept {
396 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_HOUR)));
397 }
398
403 template<class T>
404 TIME_SHIELD_CONSTEXPR ts_t hour_to_sec_impl(T t, std::false_type) noexcept {
405 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_HOUR);
406 }
407# endif // TIME_SHIELD_CPP17
408
414 template<class T1 = ts_t, class T2>
415 TIME_SHIELD_CONSTEXPR T1 hour_to_sec(T2 ts) noexcept {
416# ifdef TIME_SHIELD_CPP17
417 if constexpr (std::is_floating_point_v<T2>) {
418 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_HOUR)));
419 } else {
420 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_HOUR);
421 }
422# else
423 return static_cast<T1>(hour_to_sec_impl(ts, typename std::conditional<
424 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
425 std::true_type,
426 std::false_type
427 >::type{}));
428# endif
429 }
430
436 template<class T1 = int, class T2 = ts_t>
437 TIME_SHIELD_CONSTEXPR T1 sec_to_hour(T2 ts) noexcept {
438 return static_cast<T1>(detail::floor_div(
439 static_cast<int64_t>(ts),
440 static_cast<int64_t>(SEC_PER_HOUR)));
441 }
442
447 template<class T = int>
448 TIME_SHIELD_CONSTEXPR fts_t hour_to_fsec(T hr) noexcept {
449 return static_cast<fts_t>(hr) * static_cast<fts_t>(SEC_PER_HOUR);
450 }
451
456 template<class T = ts_t>
457 TIME_SHIELD_CONSTEXPR double sec_to_fhour(T ts) noexcept {
458 return static_cast<double>(ts) / static_cast<double>(SEC_PER_HOUR);
459 }
460
465 template<class T = int>
466 TIME_SHIELD_CONSTEXPR inline T hour24_to_12(T hour) noexcept {
467 if (hour == 0 || hour > 12) return 12;
468 return hour;
469 }
470
472
473}; // namespace time_shield
474
475#endif // TIME_SHIELD_HEADER_CONVERSIONS_TIME_UNIT_CONVERSIONS_HPP_INCLUDED
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 ts_t min_to_sec_impl(T t, std::true_type) noexcept
Helper function for converting minutes to seconds (floating-point version).
TIME_SHIELD_CONSTEXPR T1 ms_to_sec(T2 ts_ms) noexcept
Converts a timestamp from milliseconds to seconds.
TIME_SHIELD_CONSTEXPR ts_ms_t min_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting minutes to milliseconds (floating-point version).
TIME_SHIELD_CONSTEXPR double sec_to_fmin(T ts) noexcept
Converts a timestamp from seconds to floating-point minutes.
TIME_SHIELD_CONSTEXPR T1 min_to_ms(T2 ts) noexcept
Converts a timestamp from minutes to milliseconds.
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).
TIME_SHIELD_CONSTEXPR T1 ms_to_hour(T2 ts) noexcept
Converts a timestamp from milliseconds to hours.
TIME_SHIELD_CONSTEXPR T ms_of_ts(ts_ms_t ts) noexcept
Alias for ms_part.
TIME_SHIELD_CONSTEXPR T1 sec_to_min(T2 ts) noexcept
Converts a timestamp from seconds to minutes.
TIME_SHIELD_CONSTEXPR T1 ms_to_min(T2 ts) noexcept
Converts a timestamp from milliseconds to minutes.
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).
TIME_SHIELD_CONSTEXPR T ns_part(T2 ts) noexcept
Get the nanosecond part of the timestamp.
TIME_SHIELD_CONSTEXPR fts_t ms_to_fsec(T ts_ms) noexcept
Converts a timestamp from milliseconds to floating-point seconds.
TIME_SHIELD_CONSTEXPR T us_part(ts_us_t ts) noexcept
Get the microsecond part of the timestamp.
TIME_SHIELD_CONSTEXPR T hour24_to_12(T hour) noexcept
Converts a 24-hour format hour to a 12-hour format.
TIME_SHIELD_CONSTEXPR T us_of_ts(ts_us_t ts) noexcept
Alias for us_part.
TIME_SHIELD_CONSTEXPR T1 hour_to_ms(T2 ts) noexcept
Converts a timestamp from hours to milliseconds.
TIME_SHIELD_CONSTEXPR T1 min_to_sec(T2 ts) noexcept
Converts a timestamp from minutes to seconds.
TIME_SHIELD_CONSTEXPR double sec_to_fhour(T ts) noexcept
Converts a timestamp from seconds to floating-point hours.
TIME_SHIELD_CONSTEXPR fts_t hour_to_fsec(T hr) noexcept
Converts a timestamp from hours to floating-point seconds.
TIME_SHIELD_CONSTEXPR T ms_part(ts_ms_t ts) noexcept
Get the millisecond part of the timestamp.
TIME_SHIELD_CONSTEXPR fts_t min_to_fsec(T min) noexcept
Converts a timestamp from minutes to floating-point seconds.
TIME_SHIELD_CONSTEXPR ts_ms_t sec_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting seconds to milliseconds (floating-point version).
TIME_SHIELD_CONSTEXPR T1 sec_to_ms(T2 ts) noexcept
Converts a timestamp from seconds to milliseconds.
TIME_SHIELD_CONSTEXPR ts_ms_t hour_to_ms_impl(T t, std::true_type) noexcept
Helper function for converting hours to milliseconds (floating-point version).
TIME_SHIELD_CONSTEXPR T1 sec_to_hour(T2 ts) noexcept
Converts a timestamp from seconds to hours.
ts_ms_t fsec_to_ms(fts_t ts) noexcept
Converts a floating-point timestamp from seconds to milliseconds.
TIME_SHIELD_CONSTEXPR ts_t hour_to_sec_impl(T t, std::true_type) noexcept
Helper function for converting hours to seconds (floating-point version).
TIME_SHIELD_CONSTEXPR T1 hour_to_sec(T2 ts) noexcept
Converts a timestamp from hours to seconds.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:48
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:49
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:51
int64_t ts_us_t
Unix timestamp in microseconds since epoch.
Definition types.hpp:50
T ns_of_sec() noexcept
Get the nanosecond part of the current second.
ts_t ts() noexcept
Get the current UTC timestamp in seconds.
T ms_of_sec() noexcept
Get the millisecond part of the current second.
ts_ms_t ts_ms() noexcept
Get the current UTC timestamp in milliseconds.
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.