Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_conversions.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
3#define _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
4
10
11#include "enums.hpp"
12#include "validation.hpp"
13#include "time_utils.hpp"
14#include "time_zone_struct.hpp"
15#include <cmath>
16#include <ctime>
17#include <stdexcept>
18
19namespace time_shield {
20
23
28 template<class T = int>
29 constexpr const T ns_of_sec(fts_t ts) noexcept {
30 fts_t temp;
31 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(NS_PER_SEC)));
32 }
33
38 template<class T = int>
39 constexpr const T us_of_sec(fts_t ts) noexcept {
40 fts_t temp;
41 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(US_PER_SEC)));
42 }
43
48 template<class T = int>
49 constexpr const T ms_of_sec(fts_t ts) noexcept {
50 fts_t temp;
51 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(MS_PER_SEC)));
52 }
53
58 template<class T = int>
59 constexpr const T ms_of_ts(ts_ms_t ts) noexcept {
60 return ts % MS_PER_SEC;
61 }
62
63# ifndef TIME_SHIELD_CPP17
69 template<class T>
70 constexpr ts_ms_t sec_to_ms_impl(T t, std::true_type tag) noexcept {
71 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_SEC)));
72 }
73
79 template<class T>
80 constexpr ts_ms_t sec_to_ms_impl(T t, std::false_type tag) noexcept {
81 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_SEC);
82 }
83# endif // TIME_SHIELD_CPP17
84
90 template<class T1 = ts_ms_t, class T2>
91 constexpr T1 sec_to_ms(T2 ts) noexcept {
92# ifdef TIME_SHIELD_CPP17
93 if constexpr (std::is_floating_point_v<T2>) {
94 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_SEC)));
95 } else {
96 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_SEC);
97 }
98# else
99 return sec_to_ms_impl(ts, typename std::conditional<
100 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
101 std::true_type,
102 std::false_type
103 >::type{});
104# endif
105 }
106
110 inline ts_ms_t fsec_to_ms(fts_t ts) noexcept {
111 return static_cast<ts_ms_t>(std::round(ts * static_cast<fts_t>(MS_PER_SEC)));
112 }
113
119 template<class T1 = ts_t, class T2 = ts_ms_t>
120 constexpr const T1 ms_to_sec(T2 ts_ms) noexcept {
121 return static_cast<T1>(ts_ms) / static_cast<T1>(MS_PER_SEC);
122 }
123
128 template<class T = ts_ms_t>
129 constexpr const fts_t ms_to_fsec(T ts_ms) noexcept {
130 return static_cast<fts_t>(ts_ms) / static_cast<fts_t>(MS_PER_SEC);
131 }
132
133//----------------------------------------------------------------------------//
134// Minutes -> Milliseconds
135//----------------------------------------------------------------------------//
136# ifndef TIME_SHIELD_CPP17
142 template<class T>
143 constexpr ts_ms_t min_to_ms_impl(T t, std::true_type tag) noexcept {
144 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_MIN)));
145 }
146
152 template<class T>
153 constexpr ts_ms_t min_to_ms_impl(T t, std::false_type tag) noexcept {
154 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_MIN);
155 }
156# endif // TIME_SHIELD_CPP17
157
163 template<class T1 = ts_ms_t, class T2>
164 constexpr T1 min_to_ms(T2 ts) noexcept {
165# ifdef TIME_SHIELD_CPP17
166 if constexpr (std::is_floating_point_v<T2>) {
167 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_MIN)));
168 } else {
169 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_MIN);
170 }
171# else
172 return min_to_ms_impl(ts, typename std::conditional<
173 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
174 std::true_type,
175 std::false_type
176 >::type{});
177# endif
178 }
179
185 template<class T1 = int, class T2 = ts_ms_t>
186 constexpr T1 ms_to_min(T2 ts) noexcept {
187 return static_cast<T1>(ts) / static_cast<T1>(MS_PER_MIN);
188 }
189
190//----------------------------------------------------------------------------//
191// Minutes -> Seconds
192//----------------------------------------------------------------------------//
193# ifndef TIME_SHIELD_CPP17
199 template<class T>
200 constexpr ts_t min_to_sec_impl(T t, std::true_type tag) noexcept {
201 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_MIN)));
202 }
203
209 template<class T>
210 constexpr ts_t min_to_sec_impl(T t, std::false_type tag) noexcept {
211 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_MIN);
212 }
213# endif // TIME_SHIELD_CPP17
214
220 template<class T1 = ts_t, class T2>
221 constexpr T1 min_to_sec(T2 ts) noexcept {
222# ifdef TIME_SHIELD_CPP17
223 if constexpr (std::is_floating_point_v<T2>) {
224 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_MIN)));
225 } else {
226 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_MIN);
227 }
228# else
229 return min_to_sec_impl(ts, typename std::conditional<
230 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
231 std::true_type,
232 std::false_type
233 >::type{});
234# endif
235 }
236
242 template<class T1 = int, class T2 = ts_t>
243 constexpr T1 sec_to_min(T2 ts) noexcept {
244 return static_cast<T1>(ts) / static_cast<T1>(SEC_PER_MIN);
245 }
246
251 template<class T = int>
252 constexpr fts_t min_to_fsec(T min) noexcept {
253 return static_cast<fts_t>(min) * static_cast<fts_t>(SEC_PER_MIN);
254 }
255
260 template<class T = ts_t>
261 constexpr double sec_to_fmin(T ts) noexcept {
262 return static_cast<double>(ts) / static_cast<double>(SEC_PER_MIN);
263 }
264
265//----------------------------------------------------------------------------//
266// Hours -> Milliseconds
267//----------------------------------------------------------------------------//
268
269# ifndef TIME_SHIELD_CPP17
275 template<class T>
276 constexpr ts_ms_t hour_to_ms_impl(T t, std::true_type tag) noexcept {
277 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_HOUR)));
278 }
279
285 template<class T>
286 constexpr ts_ms_t hour_to_ms_impl(T t, std::false_type tag) noexcept {
287 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_HOUR);
288 }
289# endif // TIME_SHIELD_CPP17
290
296 template<class T1 = ts_ms_t, class T2>
297 constexpr T1 hour_to_ms(T2 ts) noexcept {
298# ifdef TIME_SHIELD_CPP17
299 if constexpr (std::is_floating_point_v<T2>) {
300 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_HOUR)));
301 } else {
302 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_HOUR);
303 }
304# else
305 return hour_to_ms_impl(ts, typename std::conditional<
306 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
307 std::true_type,
308 std::false_type
309 >::type{});
310# endif
311 }
312
318 template<class T1 = int, class T2 = ts_ms_t>
319 constexpr T1 ms_to_hour(T2 ts) noexcept {
320 return static_cast<T1>(ts) / static_cast<T1>(MS_PER_HOUR);
321 }
322
323//----------------------------------------------------------------------------//
324// Hours -> Seconds
325//----------------------------------------------------------------------------//
326
327# ifndef TIME_SHIELD_CPP17
333 template<class T>
334 constexpr ts_t hour_to_sec_impl(T t, std::true_type tag) noexcept {
335 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_HOUR)));
336 }
337
343 template<class T>
344 constexpr ts_t hour_to_sec_impl(T t, std::false_type tag) noexcept {
345 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_HOUR);
346 }
347# endif // TIME_SHIELD_CPP17
348
354 template<class T1 = ts_t, class T2>
355 constexpr T1 hour_to_sec(T2 ts) noexcept {
356# ifdef TIME_SHIELD_CPP17
357 if constexpr (std::is_floating_point_v<T2>) {
358 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_HOUR)));
359 } else {
360 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_HOUR);
361 }
362# else
363 return hour_to_sec_impl(ts, typename std::conditional<
364 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
365 std::true_type,
366 std::false_type
367 >::type{});
368# endif
369 }
370
376 template<class T1 = int, class T2 = ts_t>
377 constexpr T1 sec_to_hour(T2 ts) noexcept {
378 return static_cast<T1>(ts) / static_cast<T1>(SEC_PER_HOUR);
379 }
380
385 template<class T = int>
386 constexpr fts_t hour_to_fsec(T hr) noexcept {
387 return static_cast<fts_t>(hr) * static_cast<fts_t>(SEC_PER_HOUR);
388 }
389
394 template<class T = ts_t>
395 constexpr double sec_to_fhour(T ts) noexcept {
396 return static_cast<double>(ts) / static_cast<double>(SEC_PER_HOUR);
397 }
398
399//------------------------------------------------------------------------------
400
405 template<class T = year_t>
406 constexpr const T get_unix_year(ts_t ts) noexcept {
407 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
408 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
409 // Поэтому пришлось снизить до 9223371890843040000
410 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
411 constexpr int64_t BIAS_2000 = 946684800LL;
412
413 int64_t y = MAX_YEAR;
414 int64_t secs = -((ts - BIAS_2000) - BIAS_292277022000);
415
416 const int64_t n_400_years = secs / SEC_PER_400_YEARS;
417 secs -= n_400_years * SEC_PER_400_YEARS;
418 y -= n_400_years * 400;
419
420 const int64_t n_100_years = secs / SEC_PER_100_YEARS;
421 secs -= n_100_years * SEC_PER_100_YEARS;
422 y -= n_100_years * 100;
423
424 const int64_t n_4_years = secs / SEC_PER_4_YEARS;
425 secs -= n_4_years * SEC_PER_4_YEARS;
426 y -= n_4_years * 4;
427
428 const int64_t n_1_years = secs / SEC_PER_YEAR;
429 secs -= n_1_years * SEC_PER_YEAR;
430 y -= n_1_years;
431
432 y = secs == 0 ? y : y - 1;
433 return y - UNIX_EPOCH;
434 }
435
436//------------------------------------------------------------------------------
437
442 template<class T = int>
443 TIME_SHIELD_CONSTEXPR inline const T hour24_to_12(T hour) noexcept {
444 if (hour == 0 || hour > 12) return 12;
445 return hour;
446 }
447
448//------------------------------------------------------------------------------
449
460 template<class T1 = DateTimeStruct, class T2 = ts_t>
462 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
463 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
464 // Поэтому пришлось снизить до 9223371890843040000
465 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
466 constexpr int64_t BIAS_2000 = 946684800LL;
467
468 int64_t y = MAX_YEAR;
469 uint64_t secs = -((ts - BIAS_2000) - BIAS_292277022000);
470
471 const uint64_t n_400_years = secs / SEC_PER_400_YEARS;
472 secs -= n_400_years * SEC_PER_400_YEARS;
473 y -= n_400_years * 400;
474
475 const uint64_t n_100_years = secs / SEC_PER_100_YEARS;
476 secs -= n_100_years * SEC_PER_100_YEARS;
477 y -= n_100_years * 100;
478
479 const uint64_t n_4_years = secs / SEC_PER_4_YEARS;
480 secs -= n_4_years * SEC_PER_4_YEARS;
481 y -= n_4_years * 4;
482
483 const uint64_t n_1_years = secs / SEC_PER_YEAR;
484 secs -= n_1_years * SEC_PER_YEAR;
485 y -= n_1_years;
486
487 T1 date_time;
488
489 if (secs == 0) {
490 date_time.year = y;
491 date_time.mon = 1;
492 date_time.day = 1;
493 return date_time;
494 }
495
496 date_time.year = y - 1;
497 const bool is_leap_year = is_leap_year_date(date_time.year);
498 secs = is_leap_year ? SEC_PER_LEAP_YEAR - secs : SEC_PER_YEAR - secs;
499 const int days = secs / SEC_PER_DAY;
500
501 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60 - 1;
502 constexpr int TABLE_MONTH_OF_YEAR[] = {
503 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 31 январь
504 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 28 февраль
505 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 31 март
506 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 30 апрель
507 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
508 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
509 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
510 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
511 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
512 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
513 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
514 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
515 };
516 constexpr int TABLE_DAY_OF_YEAR[] = {
517 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 31 январь
518 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28, // 28 февраль
519 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 31 март
520 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, // 30 апрель
521 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
522 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
523 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
524 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
525 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
526 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
527 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
528 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
529 };
530
531 if (is_leap_year) {
532 const int prev_days = days - 1;
533 date_time.day = days == JAN_AND_FEB_DAY_LEAP_YEAR ? (TABLE_DAY_OF_YEAR[prev_days] + 1) :
534 (days > JAN_AND_FEB_DAY_LEAP_YEAR ? TABLE_DAY_OF_YEAR[prev_days] : TABLE_DAY_OF_YEAR[days]);
535 date_time.mon = days >= JAN_AND_FEB_DAY_LEAP_YEAR ? TABLE_MONTH_OF_YEAR[prev_days] : TABLE_MONTH_OF_YEAR[days];
536 } else {
537 date_time.day = TABLE_DAY_OF_YEAR[days];
538 date_time.mon = TABLE_MONTH_OF_YEAR[days];
539 }
540
541 ts_t day_secs = secs % SEC_PER_DAY;
542 date_time.hour = day_secs / SEC_PER_HOUR;
543 ts_t min_secs = day_secs - date_time.hour * SEC_PER_HOUR;
544 date_time.min = min_secs / SEC_PER_MIN;
545 date_time.sec = min_secs - date_time.min * SEC_PER_MIN;
546# ifdef TIME_SHIELD_CPP17
547 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T2>::value) {
548 date_time.ms = static_cast<int>(std::round(std::fmod(static_cast<double>(ts), static_cast<double>(MS_PER_SEC))));
549 } else date_time.ms = 0;
550# else
551 if (std::is_floating_point<T2>::value) {
552 date_time.ms = static_cast<int>(std::round(std::fmod(static_cast<double>(ts), static_cast<double>(MS_PER_SEC))));
553 } else date_time.ms = 0;
554# endif
555 return date_time;
556 }
557
558//------------------------------------------------------------------------------
559
565 template<class T>
568 date_time.ms = ms_of_ts(ts); // Extract and set the ms component
569 return date_time;
570 }
571
572//------------------------------------------------------------------------------
573
604 template<class T1 = year_t, class T2 = int>
605 TIME_SHIELD_CONSTEXPR inline const ts_t to_timestamp(
606 T1 year,
607 T2 month,
608 T2 day,
609 T2 hour = 0,
610 T2 min = 0,
611 T2 sec = 0) {
612
613 if (day >= UNIX_EPOCH && year <= 31) {
614 return to_timestamp((T1)day, month, (T2)year, hour, min, sec);
615 }
616 if (!is_valid_date_time(year, month, day, hour, min, sec)) {
617 throw std::invalid_argument("Invalid date-time combination");
618 }
619
620 int64_t secs = 0;
621 uint64_t years = (static_cast<int64_t>(MAX_YEAR) - year);
622
623 const int64_t n_400_years = years / 400;
624 secs += n_400_years * SEC_PER_400_YEARS;
625 years -= n_400_years * 400;
626
627 const int64_t n_100_years = years / 100;
628 secs += n_100_years * SEC_PER_100_YEARS;
629 years -= n_100_years * 100;
630
631 const int64_t n_4_years = years / 4;
632 secs += n_4_years * SEC_PER_4_YEARS;
633 years -= n_4_years * 4;
634
635 secs += years * SEC_PER_YEAR;
636
637 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
638 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
639 // Поэтому пришлось снизить до 9223371890843040000
640 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
641 constexpr int64_t BIAS_2000 = 946684800LL;
642
643 secs = BIAS_292277022000 - secs;
644 secs += BIAS_2000;
645
646 if (month == 1 && day == 1 &&
647 hour == 0 && min == 0 &&
648 sec == 0) {
649 return secs;
650 }
651
652 constexpr int lmos[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
653 constexpr int mos[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
654
655 secs += (is_leap_year_date(year) ? (lmos[month - 1] + day - 1) : (mos[month - 1] + day - 1)) * SEC_PER_DAY;
656 secs += SEC_PER_HOUR * hour + SEC_PER_MIN * min + sec;
657 return secs;
658 }
659
660//------------------------------------------------------------------------------
661
672 template<class T>
673 TIME_SHIELD_CONSTEXPR inline const ts_t dt_to_timestamp(
674 const T& date_time) {
675 return to_timestamp(
676 date_time.year,
677 date_time.mon,
678 date_time.day,
679 date_time.hour,
680 date_time.min,
681 date_time.sec);
682 }
683
684//------------------------------------------------------------------------------
685
694 TIME_SHIELD_CONSTEXPR inline const ts_t tm_to_timestamp(
695 const std::tm *timeinfo) {
696 return to_timestamp(
697 timeinfo->tm_year + 1900,
698 timeinfo->tm_mon + 1,
699 timeinfo->tm_mday,
700 timeinfo->tm_hour,
701 timeinfo->tm_min,
702 timeinfo->tm_sec);
703 }
704
705//------------------------------------------------------------------------------
706
723 template<class T1 = year_t, class T2 = int>
724 TIME_SHIELD_CONSTEXPR inline const ts_ms_t to_timestamp_ms(
725 T1 year,
726 T2 month,
727 T2 day,
728 T2 hour = 0,
729 T2 min = 0,
730 T2 sec = 0,
731 T2 ms = 0) {
732 return sec_to_ms(to_timestamp<T1, T2>(year, month, day, hour, min, sec)) + ms;
733 }
734
735//------------------------------------------------------------------------------
736
747 template<class T>
748 TIME_SHIELD_CONSTEXPR inline const ts_t dt_to_timestamp_ms(
749 const T& date_time) {
750 return sec_to_ms(dt_to_timestamp(date_time)) + date_time.ms;
751 }
752
753//------------------------------------------------------------------------------
754
763 TIME_SHIELD_CONSTEXPR inline const ts_t tm_to_timestamp_ms(
764 const std::tm *timeinfo) {
765 return sec_to_ms(tm_to_timestamp(timeinfo));
766 }
767
768//------------------------------------------------------------------------------
769
788 template<class T1 = year_t, class T2 = int, class T3 = int>
789 TIME_SHIELD_CONSTEXPR inline const fts_t to_ftimestamp(
790 T1 year,
791 T2 month,
792 T2 day,
793 T2 hour = 0,
794 T2 min = 0,
795 T2 sec = 0,
796 T3 ms = 0) {
797 return static_cast<fts_t>(to_timestamp(year, month, day, hour, min, sec)) +
798 static_cast<fts_t>(ms)/static_cast<fts_t>(MS_PER_SEC);
799 }
800
801//------------------------------------------------------------------------------
802
814 template<class T>
815 TIME_SHIELD_CONSTEXPR inline const fts_t dt_to_ftimestamp(
816 const T& date_time) {
817 return static_cast<fts_t>(to_timestamp(date_time)) +
818 static_cast<fts_t>(date_time.ms)/static_cast<fts_t>(MS_PER_SEC);
819 }
820
821//------------------------------------------------------------------------------
822
832 TIME_SHIELD_CONSTEXPR inline const fts_t tm_to_ftimestamp(
833 const std::tm* timeinfo) {
834 return static_cast<fts_t>(tm_to_timestamp(timeinfo));
835 }
836
837//------------------------------------------------------------------------------
838
846 template<class T = uday_t>
847 constexpr const T get_unix_day(ts_t ts = time_shield::ts()) noexcept {
848 return ts / SEC_PER_DAY;
849 }
850
851//------------------------------------------------------------------------------
852
861 template<class T = int>
862 constexpr const T get_days_difference(ts_t start, ts_t stop) noexcept {
863 return (stop - start) / SEC_PER_DAY;
864 }
865
866//------------------------------------------------------------------------------
867
875 template<class T = uday_t>
876 constexpr const T get_unix_day_ms(ts_ms_t t_ms = time_shield::ts_ms()) noexcept {
877 return get_unix_day(ms_to_sec(t_ms));
878 }
879
880//------------------------------------------------------------------------------
881
890 template<class T = ts_t>
891 constexpr const T unix_day_to_timestamp(uday_t unix_day) noexcept {
892 return unix_day * SEC_PER_DAY;
893 }
894
895//------------------------------------------------------------------------------
896
905 template<class T = ts_t>
906 constexpr const T unix_day_to_timestamp_ms(uday_t unix_day) noexcept {
907 return unix_day * MS_PER_DAY;
908 }
909
910//------------------------------------------------------------------------------
911
920 template<class T = ts_t>
921 constexpr const T end_of_day_from_unix_day(uday_t unix_day) noexcept {
922 return unix_day * SEC_PER_DAY + SEC_PER_DAY - 1;
923 }
924
933 template<class T = ts_ms_t>
934 constexpr const T end_of_day_from_unix_day_ms(uday_t unix_day) noexcept {
935 return unix_day * MS_PER_DAY + MS_PER_DAY - 1;
936 }
937
946 template<class T = ts_ms_t>
947 constexpr const T start_of_next_day_from_unix_day(uday_t unix_day) noexcept {
949 }
950
959 template<class T = ts_ms_t>
961 return unix_day * MS_PER_DAY + MS_PER_DAY;
962 }
963
964//------------------------------------------------------------------------------
965
973 template<class T = int64_t>
974 constexpr const T get_unix_min(ts_t ts = ts()) {
975 return ts / SEC_PER_MIN;
976 }
977
978//------------------------------------------------------------------------------
979
987 template<class T = int>
988 constexpr const T sec_of_day(ts_t ts = ts()) noexcept {
989 return ts % SEC_PER_DAY;
990 }
991
999 template<class T = int>
1000 constexpr const T sec_of_day_ms(ts_ms_t ts_ms) noexcept {
1001 return sec_of_day(ms_to_sec(ts_ms));
1002 }
1003
1014 template<class T1 = int, class T2 = int>
1015 constexpr const T1 sec_of_day(
1016 T2 hour,
1017 T2 min,
1018 T2 sec) noexcept {
1019 return hour * SEC_PER_HOUR + min * SEC_PER_MIN + sec;
1020 }
1021
1029 template<class T = int>
1030 constexpr const T sec_of_min(ts_t ts = ts()) {
1031 return (ts % SEC_PER_MIN);
1032 }
1033
1041 template<class T = int>
1042 constexpr const T sec_of_hour(ts_t ts = ts()) {
1043 return (ts % SEC_PER_HOUR);
1044 }
1045
1046//------------------------------------------------------------------------------
1047
1055 template<class T = year_t>
1056 TIME_SHIELD_CONSTEXPR inline const T get_year(ts_t ts = ts()) {
1057 return get_unix_year(ts) + UNIX_EPOCH;
1058 }
1059
1060//------------------------------------------------------------------------------
1061
1069 template<class T = year_t>
1070 TIME_SHIELD_CONSTEXPR inline const T get_year_ms(ts_ms_t ts_ms = ts_ms()) {
1071 return get_year(ms_to_sec(ts_ms));
1072 }
1073
1074//------------------------------------------------------------------------------
1075
1083 TIME_SHIELD_CONSTEXPR inline const ts_t start_of_year(ts_t ts) noexcept {
1084 constexpr ts_t BIAS_2100 = 4102444800;
1085 if (ts < BIAS_2100) {
1086 constexpr ts_t SEC_PER_YEAR_X2 = SEC_PER_YEAR * 2;
1087 ts_t year_start_ts = ts % SEC_PER_4_YEARS;
1088 if (year_start_ts < SEC_PER_YEAR) {
1089 return ts - year_start_ts;
1090 } else
1091 if (year_start_ts < SEC_PER_YEAR_X2) {
1092 return ts + SEC_PER_YEAR - year_start_ts;
1093 } else
1094 if (year_start_ts < (SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR)) {
1095 return ts + SEC_PER_YEAR_X2 - year_start_ts;
1096 }
1097 return ts + (SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR) - year_start_ts;
1098 }
1099
1100 constexpr ts_t BIAS_2000 = 946684800;
1101 ts_t secs = ts - BIAS_2000;
1102
1103 ts_t offset_y400 = secs % SEC_PER_400_YEARS;
1104 ts_t start_ts = secs - offset_y400 + BIAS_2000;
1105 secs = offset_y400;
1106
1107 if (secs >= SEC_PER_FIRST_100_YEARS) {
1109 start_ts += SEC_PER_FIRST_100_YEARS;
1110 while (secs >= SEC_PER_100_YEARS) {
1111 secs -= SEC_PER_100_YEARS;
1112 start_ts += SEC_PER_100_YEARS;
1113 }
1114
1115 constexpr ts_t SEC_PER_4_YEARS_V2 = 4 * SEC_PER_YEAR;
1116 if (secs >= SEC_PER_4_YEARS_V2) {
1117 secs -= SEC_PER_4_YEARS_V2;
1118 start_ts += SEC_PER_4_YEARS_V2;
1119 } else {
1120 start_ts += secs - secs % SEC_PER_YEAR;
1121 return start_ts;
1122 }
1123 }
1124
1125 ts_t offset_4y = secs % SEC_PER_4_YEARS;
1126 start_ts += secs - offset_4y;
1127 secs = offset_4y;
1128
1129 if (secs >= SEC_PER_LEAP_YEAR) {
1130 secs -= SEC_PER_LEAP_YEAR;
1131 start_ts += SEC_PER_LEAP_YEAR;
1132 start_ts += secs - secs % SEC_PER_YEAR;
1133 }
1134 return start_ts;
1135 }
1136
1137//------------------------------------------------------------------------------
1138
1146 TIME_SHIELD_CONSTEXPR inline const ts_ms_t start_of_year_ms(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1148 }
1149
1150//------------------------------------------------------------------------------
1151
1159 template<class T = year_t>
1160 TIME_SHIELD_CONSTEXPR inline const ts_t start_of_year_date(T year) {
1161 if (year < 2100) {
1162 const ts_t year_diff = year >= UNIX_EPOCH ? year - UNIX_EPOCH : UNIX_EPOCH - year;
1163 const ts_t year_start_ts = (year_diff / 4) * SEC_PER_4_YEARS;
1164 const ts_t year_remainder = year_diff % 4;
1165 constexpr ts_t SEC_PER_YEAR_X2 = 2 * SEC_PER_YEAR;
1166 constexpr ts_t SEC_PER_YEAR_V2 = SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR;
1167 switch (year_remainder) {
1168 case 0: return year_start_ts;
1169 case 1: return year_start_ts + SEC_PER_YEAR;
1170 case 2: return year_start_ts + SEC_PER_YEAR_X2;
1171 default: return year_start_ts + SEC_PER_YEAR_V2;
1172 };
1173 return year_start_ts + SEC_PER_YEAR_V2;
1174 }
1175 return to_timestamp(year, 1, 1);
1176 }
1177
1178//------------------------------------------------------------------------------
1179
1187 template<class T = year_t>
1188 TIME_SHIELD_CONSTEXPR inline const ts_ms_t start_of_year_date_ms(T year) {
1190 }
1191
1192//------------------------------------------------------------------------------
1193
1200 TIME_SHIELD_CONSTEXPR inline ts_t end_of_year(ts_t ts = time_shield::ts()) {
1201 constexpr ts_t BIAS_2100 = 4102444800;
1202 if (ts < BIAS_2100) {
1203 constexpr ts_t SEC_PER_YEAR_X2 = SEC_PER_YEAR * 2;
1204 constexpr ts_t SEC_PER_YEAR_X3 = SEC_PER_YEAR * 3;
1205 constexpr ts_t SEC_PER_YEAR_X3_V2 = SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR;
1206 ts_t year_end_ts = ts % SEC_PER_4_YEARS;
1207 if (year_end_ts < SEC_PER_YEAR) {
1208 return ts + SEC_PER_YEAR - year_end_ts - 1;
1209 } else
1210 if (year_end_ts < SEC_PER_YEAR_X2) {
1211 return ts + SEC_PER_YEAR_X2 - year_end_ts - 1;
1212 } else
1213 if (year_end_ts < SEC_PER_YEAR_X3_V2) {
1214 return ts + SEC_PER_YEAR_X3_V2 - year_end_ts - 1;
1215 }
1216 return ts + (SEC_PER_YEAR_X3 + SEC_PER_LEAP_YEAR) - year_end_ts - 1;
1217 }
1218
1219 constexpr ts_t BIAS_2000 = 946684800;
1220 ts_t secs = ts - BIAS_2000;
1221
1222 ts_t offset_y400 = secs % SEC_PER_400_YEARS;
1223 ts_t end_ts = secs - offset_y400 + BIAS_2000;
1224 secs = offset_y400;
1225
1226 if (secs >= SEC_PER_FIRST_100_YEARS) {
1228 end_ts += SEC_PER_FIRST_100_YEARS;
1229 while (secs >= SEC_PER_100_YEARS) {
1230 secs -= SEC_PER_100_YEARS;
1231 end_ts += SEC_PER_100_YEARS;
1232 }
1233
1234 constexpr ts_t SEC_PER_4_YEARS_V2 = 4 * SEC_PER_YEAR;
1235 if (secs >= SEC_PER_4_YEARS_V2) {
1236 secs -= SEC_PER_4_YEARS_V2;
1237 end_ts += SEC_PER_4_YEARS_V2;
1238 } else {
1239 end_ts += secs - secs % SEC_PER_YEAR;
1240 return end_ts + SEC_PER_YEAR - 1;
1241 }
1242 }
1243
1244 ts_t offset_4y = secs % SEC_PER_4_YEARS;
1245 end_ts += secs - offset_4y;
1246 secs = offset_4y;
1247
1248 if (secs >= SEC_PER_LEAP_YEAR) {
1249 secs -= SEC_PER_LEAP_YEAR;
1250 end_ts += SEC_PER_LEAP_YEAR;
1251 end_ts += secs - secs % SEC_PER_YEAR;
1252 end_ts += SEC_PER_YEAR;
1253 } else {
1254 end_ts += SEC_PER_LEAP_YEAR;
1255 }
1256 return end_ts - 1;
1257 }
1258
1259//------------------------------------------------------------------------------
1260
1267 template<class T = year_t>
1268 TIME_SHIELD_CONSTEXPR inline const ts_ms_t end_of_year_ms(ts_ms_t ts_ms = ts_ms()) {
1270 }
1271
1272//------------------------------------------------------------------------------
1273
1280 template<class T = int>
1281 inline const T day_of_year(ts_t ts = time_shield::ts()) {
1282 return ((ts - start_of_year(ts)) / SEC_PER_DAY) + 1;
1283 }
1284
1285//------------------------------------------------------------------------------
1286
1293 template<class T = Month>
1294 TIME_SHIELD_CONSTEXPR inline const T month_of_year(ts_t ts) noexcept {
1295 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60;
1296 constexpr int TABLE_MONTH_OF_YEAR[] = {
1297 0,
1298 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 31 январь
1299 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 28 февраль
1300 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 31 март
1301 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, // 30 апрель
1302 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1303 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1304 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1305 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
1306 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
1307 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
1308 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
1309 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
1310 };
1311 const size_t dy = day_of_year(ts);
1312 return static_cast<T>((is_leap_year(ts) && dy >= JAN_AND_FEB_DAY_LEAP_YEAR) ? TABLE_MONTH_OF_YEAR[dy - 1] : TABLE_MONTH_OF_YEAR[dy]);
1313 }
1314
1315//------------------------------------------------------------------------------
1316
1323 template<class T = int>
1324 TIME_SHIELD_CONSTEXPR inline const T day_of_month(ts_t ts = time_shield::ts()) {
1325 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60;
1326 // таблица для обычного года, не високосного
1327 constexpr int TABLE_DAY_OF_YEAR[] = {
1328 0,
1329 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 31 январь
1330 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28, // 28 февраль
1331 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, // 31 март
1332 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, // 30 апрель
1333 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1334 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
1335 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1336 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1337 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
1338 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1339 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
1340 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
1341 };
1342 const size_t dy = day_of_year(ts);
1343 if(is_leap_year(ts)) {
1344 if(dy == JAN_AND_FEB_DAY_LEAP_YEAR) return TABLE_DAY_OF_YEAR[dy - 1] + 1;
1345 if(dy > JAN_AND_FEB_DAY_LEAP_YEAR) return TABLE_DAY_OF_YEAR[dy - 1];
1346 }
1347 return TABLE_DAY_OF_YEAR[dy];
1348 }
1349
1350//------------------------------------------------------------------------------
1351
1359 template<class T1 = int, class T2 = year_t, class T3 = int>
1360 constexpr const T1 num_days_in_month(T2 year, T3 month) noexcept {
1361 if (month > MONTHS_PER_YEAR || month < 0) return 0;
1362 constexpr T1 num_days[13] = {0,31,30,31,30,31,30,31,31,30,31,30,31};
1363 if (month == FEB) {
1364 if (is_leap_year_date(year)) return 29;
1365 return 28;
1366 }
1367 return num_days[month];
1368 }
1369
1370//------------------------------------------------------------------------------
1371
1378 template<class T1 = int>
1379 TIME_SHIELD_CONSTEXPR const T1 num_days_in_month_ts(ts_t ts = time_shield::ts()) noexcept {
1380 constexpr T1 num_days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
1381 const int month = month_of_year(ts);
1382 if (month == FEB) {
1383 return is_leap_year(ts) ? 29 : 28;
1384 }
1385 return num_days[month];
1386 }
1387
1388//------------------------------------------------------------------------------
1389
1396 template<class T1 = int, class T2 = year_t>
1397 constexpr const T1 num_days_in_year(T2 year) noexcept {
1399 return DAYS_PER_YEAR;
1400 }
1401
1402//------------------------------------------------------------------------------
1403
1410 template<class T = int>
1413 return DAYS_PER_YEAR;
1414 }
1415
1416//------------------------------------------------------------------------------
1417
1425 constexpr const ts_t start_of_day(ts_t ts = time_shield::ts()) noexcept {
1426 return ts - (ts % SEC_PER_DAY);
1427 }
1428
1429//------------------------------------------------------------------------------
1430
1438 template<class T = int>
1439 constexpr const ts_t start_of_prev_day(ts_t ts = time_shield::ts(), T days = 1) noexcept {
1440 return ts - (ts % SEC_PER_DAY) - SEC_PER_DAY * days;
1441 }
1442
1443//------------------------------------------------------------------------------
1444
1452 constexpr const ts_t start_of_day_sec(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1453 return start_of_day(ms_to_sec(ts_ms));
1454 }
1455
1456//------------------------------------------------------------------------------
1457
1466 return ts_ms - (ts_ms % MS_PER_DAY);
1467 }
1468
1469//------------------------------------------------------------------------------
1470
1479 template<class T = int>
1480 constexpr const ts_t start_of_next_day(ts_t ts, T days = 1) noexcept {
1481 return start_of_day(ts) + days * SEC_PER_DAY;
1482 }
1483
1484//------------------------------------------------------------------------------
1485
1494 template<class T = int>
1495 constexpr const ts_ms_t start_of_next_day_ms(ts_ms_t ts_ms, T days = 1) noexcept {
1497 }
1498
1499//------------------------------------------------------------------------------
1500
1508 template<class T = int>
1509 constexpr const ts_t next_day(ts_t ts, T days = 1) noexcept {
1510 return ts + days * SEC_PER_DAY;
1511 }
1512
1520 template<class T = int>
1521 constexpr const ts_ms_t next_day_ms(ts_ms_t ts_ms, T days = 1) noexcept {
1522 return ts_ms + days * MS_PER_DAY;
1523 }
1524
1525//------------------------------------------------------------------------------
1526
1533 constexpr const ts_t end_of_day(const ts_t& ts = time_shield::ts()) noexcept {
1534 return ts - (ts % SEC_PER_DAY) + SEC_PER_DAY - 1;
1535 }
1536
1537//------------------------------------------------------------------------------
1538
1545 constexpr const ts_t end_of_day_sec(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1546 return end_of_day(ms_to_sec(ts_ms));
1547 }
1548
1549//------------------------------------------------------------------------------
1550
1557 constexpr const ts_ms_t end_of_day_ms(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1558 return ts_ms - (ts_ms % MS_PER_DAY) + MS_PER_DAY - 1;
1559 }
1560
1561//------------------------------------------------------------------------------
1562
1572 template<class T1 = Weekday, class T2 = year_t, class T3 = int, class T4 = int>
1573 constexpr const T1 day_of_week_date(T2 year, T3 month, T4 day) {
1574 year_t a, y, m, R;
1575 a = (14 - month) / MONTHS_PER_YEAR;
1576 y = year - a;
1577 m = month + MONTHS_PER_YEAR * a - 2;
1578 R = 7000 + ( day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m) / MONTHS_PER_YEAR);
1579 return static_cast<T1>(R % DAYS_PER_WEEK);
1580 }
1581
1582//------------------------------------------------------------------------------
1583
1592 template<class T1 = Weekday, class T2>
1593 constexpr const T1 get_weekday_from_date(const T2& date) {
1594 return day_of_week_date(date.year, date.mon, date.day);
1595 }
1596
1597//------------------------------------------------------------------------------
1598
1602 template<class T = Weekday>
1603 constexpr const T get_weekday_from_ts(ts_t ts) noexcept {
1604 return static_cast<T>((ts / SEC_PER_DAY + THU) % DAYS_PER_WEEK);
1605 }
1606
1607//------------------------------------------------------------------------------
1608
1612 template<class T = Weekday>
1615 }
1616
1617//------------------------------------------------------------------------------
1618
1626 TIME_SHIELD_CONSTEXPR inline const ts_t start_of_month(ts_t ts = time_shield::ts()) {
1627 return start_of_day(ts) - (day_of_month(ts) - 1) * SEC_PER_DAY;
1628 }
1629
1630//------------------------------------------------------------------------------
1631
1639 TIME_SHIELD_CONSTEXPR inline const ts_t end_of_month(ts_t ts = time_shield::ts()) {
1641 }
1642
1643//------------------------------------------------------------------------------
1644
1652 TIME_SHIELD_CONSTEXPR inline ts_t last_sunday_of_month(ts_t ts = time_shield::ts()) {
1654 }
1655
1656//------------------------------------------------------------------------------
1657
1665 template<class T1 = int, class T2 = year_t, class T3 = int>
1666 TIME_SHIELD_CONSTEXPR inline const T1 last_sunday_month_day(T2 year, T3 month) {
1667 const T1 days = num_days_in_month(year, month);
1668 return days - day_of_week_date(year, month, days);
1669 }
1670
1671//------------------------------------------------------------------------------
1672
1679 constexpr const ts_t start_of_hour(ts_t ts = time_shield::ts()) noexcept {
1680 return ts - (ts % SEC_PER_HOUR);
1681 }
1682
1683//------------------------------------------------------------------------------
1684
1692 return start_of_hour(ms_to_sec(ts_ms));
1693 }
1694
1695//------------------------------------------------------------------------------
1696
1702 return ts_ms - (ts_ms % MS_PER_HOUR);
1703 }
1704
1705//------------------------------------------------------------------------------
1706
1711 constexpr const ts_t end_of_hour(ts_t ts = time_shield::ts()) noexcept {
1712 return ts - (ts % SEC_PER_HOUR) + SEC_PER_HOUR - 1;
1713 }
1714
1715//------------------------------------------------------------------------------
1716
1723 constexpr const ts_t end_of_hour_sec(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1724 return end_of_hour(ms_to_sec(ts_ms));
1725 }
1726
1727//------------------------------------------------------------------------------
1728
1736 return ts_ms - (ts_ms % MS_PER_HOUR) + MS_PER_HOUR - 1;
1737 }
1738
1739//------------------------------------------------------------------------------
1740
1747 template<class T = int>
1748 constexpr const T hour_of_day(ts_t ts = time_shield::ts()) noexcept {
1749 return ((ts / SEC_PER_HOUR) % HOURS_PER_DAY);
1750 }
1751
1752//------------------------------------------------------------------------------
1753
1763 }
1764
1765//------------------------------------------------------------------------------
1766
1774 constexpr const ts_t end_of_week(ts_t ts = time_shield::ts()) {
1776 }
1777
1778//------------------------------------------------------------------------------
1779
1789 }
1790
1791//------------------------------------------------------------------------------
1792
1796 constexpr const ts_t start_of_min(ts_t ts = time_shield::ts()) noexcept {
1797 return ts - (ts % SEC_PER_MIN);
1798 }
1799
1800//------------------------------------------------------------------------------
1801
1805 constexpr const ts_t end_of_min(ts_t ts = time_shield::ts()) noexcept {
1806 return ts - (ts % SEC_PER_MIN) + SEC_PER_MIN - 1;
1807 }
1808
1809//------------------------------------------------------------------------------
1810
1815 template<class T = int>
1816 constexpr const T min_of_day(ts_t ts = time_shield::ts()) noexcept {
1817 return ((ts / SEC_PER_MIN) % MIN_PER_DAY);
1818 }
1819
1820//------------------------------------------------------------------------------
1821
1826 template<class T = int>
1827 constexpr const T min_of_hour(ts_t ts = time_shield::ts()) noexcept {
1828 return ((ts / SEC_PER_MIN) % MIN_PER_HOUR);
1829 }
1830
1831//------------------------------------------------------------------------------
1832
1837 template<class T = int>
1838 constexpr const ts_t start_of_period(T p, ts_t ts = time_shield::ts()) {
1839 return ts - (ts % p);
1840 }
1841
1842//------------------------------------------------------------------------------
1843
1848 template<class T = int>
1849 constexpr const ts_t end_of_period(T p, ts_t ts = time_shield::ts()) {
1850 return ts - (ts % p) + p - 1;
1851 }
1852
1853//------------------------------------------------------------------------------
1854
1860 template<class T = TimeZoneStruct>
1861 inline const T to_time_zone(tz_t offset) {
1862 T tz;
1863 int abs_val = std::abs(offset);
1864 tz.hour = abs_val / SEC_PER_HOUR;
1865 tz.min = abs_val % SEC_PER_MIN;
1866 tz.is_positive = (offset >= 0);
1867 return tz;
1868 }
1869
1871
1872}; // namespace time_shield
1873
1875
1876#endif // _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
Header file with enumerations for weekdays, months, and other time-related categories.
constexpr int64_t MIN_PER_HOUR
Minutes per hour.
Definition constants.hpp:87
constexpr int64_t DAYS_PER_WEEK
Days per week.
constexpr int64_t SEC_PER_YEAR
Seconds per year (365 days)
Definition constants.hpp:77
constexpr int64_t SEC_PER_FIRST_100_YEARS
Seconds per first 100 years.
Definition constants.hpp:81
const int64_t MONTHS_PER_YEAR
Months per year.
constexpr int64_t DAYS_PER_YEAR
Days per year.
constexpr int64_t HOURS_PER_DAY
Hours per day.
constexpr int64_t SEC_PER_100_YEARS
Seconds per 100 years.
Definition constants.hpp:82
constexpr int64_t MAX_YEAR
Maximum representable year.
constexpr int64_t MS_PER_MIN
Milliseconds per minute.
Definition constants.hpp:45
constexpr int64_t SEC_PER_LEAP_YEAR
Seconds per leap year (366 days)
Definition constants.hpp:79
constexpr int64_t MIN_PER_DAY
Minutes per day.
Definition constants.hpp:88
constexpr int64_t DAYS_PER_LEAP_YEAR
Days per leap year.
constexpr int64_t SEC_PER_HOUR
Seconds per hour.
Definition constants.hpp:69
constexpr int64_t UNIX_EPOCH
Start year of UNIX time.
constexpr int64_t MS_PER_DAY
Milliseconds per day.
Definition constants.hpp:59
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:39
constexpr int64_t SEC_PER_400_YEARS
Seconds per 400 years.
Definition constants.hpp:83
constexpr int64_t SEC_PER_DAY
Seconds per day.
Definition constants.hpp:76
constexpr int64_t SEC_PER_MIN
Seconds per minute.
Definition constants.hpp:62
constexpr int64_t NS_PER_SEC
Nanoseconds per second.
Definition constants.hpp:35
constexpr int64_t MS_PER_HOUR
Milliseconds per hour.
Definition constants.hpp:52
constexpr int64_t US_PER_SEC
Microseconds per second.
Definition constants.hpp:38
constexpr int64_t SEC_PER_4_YEARS
Seconds per 4 years.
Definition constants.hpp:80
constexpr const T sec_of_hour(ts_t ts=ts())
Get the second of the hour.
TIME_SHIELD_CONSTEXPR const fts_t dt_to_ftimestamp(const T &date_time)
Converts a date-time structure to a floating-point timestamp.
constexpr const ts_t start_of_hour_sec(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the start of the hour.
TIME_SHIELD_CONSTEXPR const fts_t tm_to_ftimestamp(const std::tm *timeinfo)
Converts a std::tm structure to a floating-point timestamp.
constexpr T unix_day(ts_t ts=time_shield::ts()) noexcept
Alias for get_unix_day function.
constexpr const T num_days_in_year_ts(ts_t ts=time_shield::ts())
Get the number of days in the current year.
constexpr const T get_unix_day_ms(ts_ms_t t_ms=time_shield::ts_ms()) noexcept
Get UNIX day from milliseconds timestamp.
TIME_SHIELD_CONSTEXPR const ts_t to_timestamp_ms(const T &date_time)
Alias for dt_to_timestamp_ms function.
constexpr const T start_of_next_day_from_unix_day_ms(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp representing the start of the next day in milliseconds.
constexpr const ts_ms_t start_of_day_ms(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the start of the day timestamp in milliseconds.
constexpr const ts_ms_t next_day_ms(ts_ms_t ts_ms, T days=1) noexcept
Calculate the timestamp for a specified number of days in the future (milliseconds).
constexpr const ts_t end_of_hour(ts_t ts=time_shield::ts()) noexcept
Get the timestamp at the end of the hour. This function sets the minute and second to 59.
const T to_time_zone(tz_t offset)
Converts an integer to a time zone structure.
TIME_SHIELD_CONSTEXPR const T1 num_days_in_month_ts(ts_t ts=time_shield::ts()) noexcept
Get the number of days in the month of the given timestamp.
T to_date_time_ms(ts_ms_t ts)
Converts a timestamp in milliseconds to a date-time structure with milliseconds.
constexpr const ts_t end_of_min(ts_t ts=time_shield::ts()) noexcept
Get the timestamp of the end of the minute.
constexpr const ts_t next_day(ts_t ts, T days=1) noexcept
Calculate the timestamp for a specified number of days in the future.
constexpr const T end_of_day_from_unix_day_ms(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp representing the end of the day in milliseconds.
constexpr const ts_t start_of_period(T p, ts_t ts=time_shield::ts())
Get the timestamp of the start of the period.
constexpr T1 min_to_sec(T2 ts) noexcept
Converts a timestamp from minutes to seconds.
constexpr const ts_ms_t end_of_day_ms(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the end of the day in milliseconds.
constexpr const T1 get_weekday_from_date(const T2 &date)
Get the day of the week from a date structure.
TIME_SHIELD_CONSTEXPR const ts_t start_of_year_date(T year)
Get the timestamp of the start of the year.
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.
TIME_SHIELD_CONSTEXPR ts_t end_of_year(ts_t ts=time_shield::ts())
Get the end-of-year timestamp.
constexpr double sec_to_fhour(T ts) noexcept
Converts a timestamp from seconds to floating-point hours.
constexpr const T min_of_day(ts_t ts=time_shield::ts()) noexcept
Get minute of day. This function returns a value between 0 to 1439 (minute of day).
constexpr ts_ms_t sec_to_ms_impl(T t, std::true_type tag) noexcept
Helper function for converting seconds to milliseconds (floating-point version).
constexpr T1 ms_to_hour(T2 ts) noexcept
Converts a timestamp from milliseconds to hours.
TIME_SHIELD_CONSTEXPR const ts_t tm_to_timestamp_ms(const std::tm *timeinfo)
Converts a std::tm structure to a timestamp in milliseconds.
constexpr const ts_t end_of_week(ts_t ts=time_shield::ts())
Get the timestamp of the end of the week.
constexpr T1 hour_to_sec(T2 ts) noexcept
Converts a timestamp from hours to seconds.
constexpr const ts_t end_of_period(T p, ts_t ts=time_shield::ts())
Get the timestamp of the end of the period.
constexpr const T ms_of_ts(ts_ms_t ts) noexcept
Get the millisecond part of the timestamp.
constexpr const ts_t start_of_hour(ts_t ts=time_shield::ts()) noexcept
Get the timestamp at the start of the hour.
TIME_SHIELD_CONSTEXPR const ts_ms_t start_of_year_date_ms(T year)
Get the timestamp in milliseconds of the start of the year.
constexpr ts_t min_to_sec_impl(T t, std::true_type tag) noexcept
Helper function for converting minutes to seconds (floating-point version).
constexpr const T get_days_difference(ts_t start, ts_t stop) noexcept
Get the number of days between two timestamps.
constexpr const T min_of_hour(ts_t ts=time_shield::ts()) noexcept
Get minute of hour. This function returns a value between 0 to 59.
constexpr double sec_to_fmin(T ts) noexcept
Converts a timestamp from seconds to floating-point minutes.
constexpr const ts_t end_of_day_sec(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the end of the day in seconds.
TIME_SHIELD_CONSTEXPR const T month_of_year(ts_t ts) noexcept
Get the month of the year.
constexpr const T1 num_days_in_month(ts_t ts=time_shield::ts()) noexcept
Alias for num_days_in_month_ts function.
constexpr ts_t hour_to_sec_impl(T t, std::true_type tag) noexcept
Helper function for converting hours to seconds (floating-point version).
TIME_SHIELD_CONSTEXPR const ts_t start_of_month(ts_t ts=time_shield::ts())
Get the timestamp at the start of the current month.
constexpr const T end_of_day_from_unix_day(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp representing the end of the day in seconds.
TIME_SHIELD_CONSTEXPR const T1 last_sunday_month_day(T2 year, T3 month)
Get the day of the last Sunday of the given month and year.
TIME_SHIELD_CONSTEXPR const ts_ms_t start_of_year_ms(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the start of the year timestamp in milliseconds.
constexpr const T get_unix_year(ts_t ts) noexcept
Converts a UNIX timestamp to a year.
constexpr const T1 day_of_week_date(T2 year, T3 month, T4 day)
Get the day of the week.
constexpr const T get_weekday_from_ts(ts_t ts) noexcept
Get the weekday from a timestamp.
constexpr fts_t hour_to_fsec(T hr) noexcept
Converts a timestamp from hours to floating-point seconds.
constexpr const ts_ms_t start_of_hour_ms(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the start of the hour. This function sets the minute and second to zero.
constexpr fts_t min_to_fsec(T min) noexcept
Converts a timestamp from minutes to floating-point seconds.
TIME_SHIELD_CONSTEXPR const ts_t dt_to_timestamp(const T &date_time)
Converts a date-time structure to a timestamp.
constexpr fts_t to_ftimestamp(const T &date_time)
Alias for dt_to_ftimestamp.
constexpr const T get_unix_day(ts_t ts=time_shield::ts()) noexcept
Get UNIX day.
TIME_SHIELD_CONSTEXPR const T hour24_to_12(T hour) noexcept
Converts a 24-hour format hour to a 12-hour format.
constexpr const T unix_day_to_timestamp(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp in seconds.
constexpr ts_ms_t ts_ms(year_t year, int month, int day)
Alias for to_timestamp_ms.
constexpr const ts_t start_of_next_day(ts_t ts, T days=1) noexcept
Get the timestamp of the start of the day after a specified number of days.
constexpr const T get_weekday_from_ts_ms(ts_ms_t ts_ms)
Get the weekday from a timestamp in milliseconds.
constexpr const ts_t start_of_min(ts_t ts=time_shield::ts()) noexcept
Get the timestamp of the beginning of the minute.
TIME_SHIELD_CONSTEXPR const ts_t tm_to_timestamp(const std::tm *timeinfo)
Converts a std::tm structure to a timestamp.
constexpr const T unix_day_to_timestamp_ms(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp in milliseconds.
constexpr const ts_ms_t start_of_next_day_ms(ts_ms_t ts_ms, T days=1) noexcept
Get the timestamp of the start of the day after a specified number of days.
constexpr T1 min_to_ms(T2 ts) noexcept
Converts a timestamp from minutes to milliseconds.
constexpr const T sec_of_day(ts_t ts=ts()) noexcept
Get the second of the day.
TIME_SHIELD_CONSTEXPR ts_t last_sunday_of_month(ts_t ts=time_shield::ts())
Get the timestamp of the last Sunday of the current month.
constexpr T1 ms_to_min(T2 ts) noexcept
Converts a timestamp from milliseconds to minutes.
TIME_SHIELD_CONSTEXPR const T get_year_ms(ts_ms_t ts_ms=ts_ms())
Get the year from the timestamp in milliseconds.
T1 to_date_time(T2 ts)
Converts a timestamp to a date-time structure.
constexpr T1 sec_to_min(T2 ts) noexcept
Converts a timestamp from seconds to minutes.
constexpr const ts_t end_of_day(const ts_t &ts=time_shield::ts()) noexcept
Get the timestamp at the end of the day.
TIME_SHIELD_CONSTEXPR const ts_ms_t end_of_year_ms(ts_ms_t ts_ms=ts_ms())
Get the timestamp in milliseconds of the end of the year.
constexpr T1 sec_to_hour(T2 ts) noexcept
Converts a timestamp from seconds to hours.
constexpr const T start_of_next_day_from_unix_day(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp representing the start of the next day in seconds.
TIME_SHIELD_CONSTEXPR const T get_year(ts_t ts=ts())
Get the year from the timestamp.
constexpr const T1 num_days_in_year(T2 year) noexcept
Get the number of days in a given year.
TIME_SHIELD_CONSTEXPR const T day_of_month(ts_t ts=time_shield::ts())
Get the day of the month.
TIME_SHIELD_CONSTEXPR const ts_t dt_to_timestamp_ms(const T &date_time)
Converts a date-time structure to a timestamp in milliseconds.
constexpr T1 sec_to_ms(T2 ts) noexcept
Converts a timestamp from seconds to milliseconds.
constexpr ts_ms_t hour_to_ms_impl(T t, std::true_type tag) noexcept
Helper function for converting hours to milliseconds (floating-point version).
constexpr ts_ms_t min_to_ms_impl(T t, std::true_type tag) noexcept
Helper function for converting minutes to milliseconds (floating-point version).
constexpr const ts_t end_of_hour_sec(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the end of the hour.
TIME_SHIELD_CONSTEXPR const T year(ts_t ts=ts())
Alias for get_year function.
constexpr const T get_unix_min(ts_t ts=ts())
Get UNIX minute.
constexpr const T days(ts_t start, ts_t stop) noexcept
Alias for get_days_difference function.
TIME_SHIELD_CONSTEXPR const ts_t to_timestamp(const T &date_time)
Alias for dt_to_timestamp function.
constexpr const ts_t start_of_day(ts_t ts=time_shield::ts()) noexcept
Get the start of the day timestamp.
TIME_SHIELD_CONSTEXPR const ts_t start_of_year(ts_t ts) noexcept
Get the start of the year timestamp.
constexpr const ts_ms_t end_of_hour_ms(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the timestamp at the end of the hour.
constexpr const ts_t start_of_saturday(ts_t ts=time_shield::ts())
Get the timestamp of the start of Saturday.
TIME_SHIELD_CONSTEXPR const ts_t end_of_month(ts_t ts=time_shield::ts())
Get the last timestamp of the current month.
constexpr const T sec_of_day_ms(ts_ms_t ts_ms) noexcept
Get the second of the day from milliseconds timestamp.
constexpr const ts_t start_of_prev_day(ts_t ts=time_shield::ts(), T days=1) noexcept
Get timestamp of the start of the previous day.
constexpr const ts_t start_of_day_sec(ts_ms_t ts_ms=time_shield::ts_ms()) noexcept
Get the start of the day timestamp in seconds.
constexpr const T hour_of_day(ts_t ts=time_shield::ts()) noexcept
Get the hour of the day.
constexpr const T sec_of_min(ts_t ts=ts())
Get the second of the minute.
constexpr const ts_t start_of_week(ts_t ts=time_shield::ts())
Get the timestamp of the beginning of the week.
const T day_of_year(ts_t ts=time_shield::ts())
Get the day of the year.
constexpr const fts_t ms_to_fsec(T ts_ms) noexcept
Converts a timestamp from milliseconds to floating-point seconds.
ts_ms_t fsec_to_ms(fts_t ts) noexcept
Converts a floating-point timestamp from seconds to milliseconds.
constexpr const T1 ms_to_sec(T2 ts_ms) noexcept
Converts a timestamp from milliseconds to seconds.
@ FEB
February.
Definition enums.hpp:94
@ SAT
Saturday.
Definition enums.hpp:33
@ THU
Thursday.
Definition enums.hpp:31
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:45
int32_t tz_t
Time zone offset in minutes from UTC (e.g., +180 = UTC+3).
Definition types.hpp:57
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:46
int64_t uday_t
Unix day count since 1970‑01‑01 (days since epoch).
Definition types.hpp:41
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:48
int64_t year_t
Year as an integer (e.g., 2024).
Definition types.hpp:40
const ts_t ts() noexcept
Get the current UTC timestamp in seconds.
const T us_of_sec() noexcept
Get the microsecond part of the current second.
const T ns_of_sec() noexcept
Get the nanosecond part of the current second.
const ts_ms_t ts_ms() noexcept
Get the current UTC timestamp in milliseconds.
const T ms_of_sec() noexcept
Get the millisecond part of the current second.
constexpr const bool is_leap_year_date(T year) noexcept
Checks if the given year is a leap year.
TIME_SHIELD_CONSTEXPR bool is_leap_year(ts_t ts)
Alias for is_leap_year_ts function.
TIME_SHIELD_CONSTEXPR bool is_valid_date_time(T1 year, T2 month, T2 day, T2 hour=0, T2 min=0, T2 sec=0, T3 ms=0) noexcept
Checks the correctness of a date and time.
TIME_SHIELD_CONSTEXPR bool is_leap_year_ts(ts_t ts)
Checks if the given year is a leap year.
Main namespace for the Time Shield library.
Doxygen-only stubs for alias functions defined via macros.
Header file with time-related utility functions.
Header for time zone structure and related functions.
Header file with time-related validation functions.