Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
time_conversions.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
4#define _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
5
11
12#include "enums.hpp"
13#include "validation.hpp"
14#include "time_utils.hpp"
15#include "time_zone_struct.hpp"
16#include "date_time_struct.hpp"
17#include <cmath>
18#include <ctime>
19#include <stdexcept>
20
21namespace time_shield {
22
25
30 template<class T = int>
31 constexpr T ns_of_sec(fts_t ts) noexcept {
32 fts_t temp;
33 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(NS_PER_SEC)));
34 }
35
40 template<class T = int>
41 constexpr T us_of_sec(fts_t ts) noexcept {
42 fts_t temp;
43 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(US_PER_SEC)));
44 }
45
50 template<class T = int>
51 constexpr T ms_of_sec(fts_t ts) noexcept {
52 fts_t temp;
53 return static_cast<T>(std::round(std::modf(ts, &temp) * static_cast<fts_t>(MS_PER_SEC)));
54 }
55
60 template<class T = int>
61 constexpr T ms_of_ts(ts_ms_t ts) noexcept {
62 return ts % MS_PER_SEC;
63 }
64
65# ifndef TIME_SHIELD_CPP17
71 template<class T>
72 constexpr ts_ms_t sec_to_ms_impl(T t, std::true_type tag) noexcept {
73 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_SEC)));
74 }
75
81 template<class T>
82 constexpr ts_ms_t sec_to_ms_impl(T t, std::false_type tag) noexcept {
83 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_SEC);
84 }
85# endif // TIME_SHIELD_CPP17
86
92 template<class T1 = ts_ms_t, class T2>
93 constexpr T1 sec_to_ms(T2 ts) noexcept {
94# ifdef TIME_SHIELD_CPP17
95 if constexpr (std::is_floating_point_v<T2>) {
96 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_SEC)));
97 } else {
98 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_SEC);
99 }
100# else
101 return sec_to_ms_impl(ts, typename std::conditional<
102 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
103 std::true_type,
104 std::false_type
105 >::type{});
106# endif
107 }
108
112 inline ts_ms_t fsec_to_ms(fts_t ts) noexcept {
113 return static_cast<ts_ms_t>(std::round(ts * static_cast<fts_t>(MS_PER_SEC)));
114 }
115
121 template<class T1 = ts_t, class T2 = ts_ms_t>
122 constexpr T1 ms_to_sec(T2 ts_ms) noexcept {
123 return static_cast<T1>(ts_ms) / static_cast<T1>(MS_PER_SEC);
124 }
125
130 template<class T = ts_ms_t>
131 constexpr fts_t ms_to_fsec(T ts_ms) noexcept {
132 return static_cast<fts_t>(ts_ms) / static_cast<fts_t>(MS_PER_SEC);
133 }
134
135//----------------------------------------------------------------------------//
136// Minutes -> Milliseconds
137//----------------------------------------------------------------------------//
138# ifndef TIME_SHIELD_CPP17
144 template<class T>
145 constexpr ts_ms_t min_to_ms_impl(T t, std::true_type tag) noexcept {
146 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_MIN)));
147 }
148
154 template<class T>
155 constexpr ts_ms_t min_to_ms_impl(T t, std::false_type tag) noexcept {
156 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_MIN);
157 }
158# endif // TIME_SHIELD_CPP17
159
165 template<class T1 = ts_ms_t, class T2>
166 constexpr T1 min_to_ms(T2 ts) noexcept {
167# ifdef TIME_SHIELD_CPP17
168 if constexpr (std::is_floating_point_v<T2>) {
169 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_MIN)));
170 } else {
171 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_MIN);
172 }
173# else
174 return min_to_ms_impl(ts, typename std::conditional<
175 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
176 std::true_type,
177 std::false_type
178 >::type{});
179# endif
180 }
181
187 template<class T1 = int, class T2 = ts_ms_t>
188 constexpr T1 ms_to_min(T2 ts) noexcept {
189 return static_cast<T1>(ts) / static_cast<T1>(MS_PER_MIN);
190 }
191
192//----------------------------------------------------------------------------//
193// Minutes -> Seconds
194//----------------------------------------------------------------------------//
195# ifndef TIME_SHIELD_CPP17
201 template<class T>
202 constexpr ts_t min_to_sec_impl(T t, std::true_type tag) noexcept {
203 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_MIN)));
204 }
205
211 template<class T>
212 constexpr ts_t min_to_sec_impl(T t, std::false_type tag) noexcept {
213 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_MIN);
214 }
215# endif // TIME_SHIELD_CPP17
216
222 template<class T1 = ts_t, class T2>
223 constexpr T1 min_to_sec(T2 ts) noexcept {
224# ifdef TIME_SHIELD_CPP17
225 if constexpr (std::is_floating_point_v<T2>) {
226 return static_cast<T1>(std::round(ts * static_cast<T2>(SEC_PER_MIN)));
227 } else {
228 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_MIN);
229 }
230# else
231 return min_to_sec_impl(ts, typename std::conditional<
232 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
233 std::true_type,
234 std::false_type
235 >::type{});
236# endif
237 }
238
244 template<class T1 = int, class T2 = ts_t>
245 constexpr T1 sec_to_min(T2 ts) noexcept {
246 return static_cast<T1>(ts) / static_cast<T1>(SEC_PER_MIN);
247 }
248
253 template<class T = int>
254 constexpr fts_t min_to_fsec(T min) noexcept {
255 return static_cast<fts_t>(min) * static_cast<fts_t>(SEC_PER_MIN);
256 }
257
262 template<class T = ts_t>
263 constexpr double sec_to_fmin(T ts) noexcept {
264 return static_cast<double>(ts) / static_cast<double>(SEC_PER_MIN);
265 }
266
267//----------------------------------------------------------------------------//
268// Hours -> Milliseconds
269//----------------------------------------------------------------------------//
270
271# ifndef TIME_SHIELD_CPP17
277 template<class T>
278 constexpr ts_ms_t hour_to_ms_impl(T t, std::true_type tag) noexcept {
279 return static_cast<ts_ms_t>(std::round(t * static_cast<T>(MS_PER_HOUR)));
280 }
281
287 template<class T>
288 constexpr ts_ms_t hour_to_ms_impl(T t, std::false_type tag) noexcept {
289 return static_cast<ts_ms_t>(t) * static_cast<ts_ms_t>(MS_PER_HOUR);
290 }
291# endif // TIME_SHIELD_CPP17
292
298 template<class T1 = ts_ms_t, class T2>
299 constexpr T1 hour_to_ms(T2 ts) noexcept {
300# ifdef TIME_SHIELD_CPP17
301 if constexpr (std::is_floating_point_v<T2>) {
302 return static_cast<T1>(std::round(ts * static_cast<T2>(MS_PER_HOUR)));
303 } else {
304 return static_cast<T1>(ts) * static_cast<T1>(MS_PER_HOUR);
305 }
306# else
307 return hour_to_ms_impl(ts, typename std::conditional<
308 (std::is_same<T2, double>::value || std::is_same<T2, float>::value),
309 std::true_type,
310 std::false_type
311 >::type{});
312# endif
313 }
314
320 template<class T1 = int, class T2 = ts_ms_t>
321 constexpr T1 ms_to_hour(T2 ts) noexcept {
322 return static_cast<T1>(ts) / static_cast<T1>(MS_PER_HOUR);
323 }
324
325//----------------------------------------------------------------------------//
326// Hours -> Seconds
327//----------------------------------------------------------------------------//
328
329# ifndef TIME_SHIELD_CPP17
335 template<class T>
336 constexpr ts_t hour_to_sec_impl(T t, std::true_type tag) noexcept {
337 return static_cast<ts_t>(std::round(t * static_cast<T>(SEC_PER_HOUR)));
338 }
339
345 template<class T>
346 constexpr ts_t hour_to_sec_impl(T t, std::false_type tag) noexcept {
347 return static_cast<ts_t>(t) * static_cast<ts_t>(SEC_PER_HOUR);
348 }
349# endif // TIME_SHIELD_CPP17
350
356 template<class T1 = ts_t, class T2>
357 constexpr T1 hour_to_sec(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>(SEC_PER_HOUR)));
361 } else {
362 return static_cast<T1>(ts) * static_cast<T1>(SEC_PER_HOUR);
363 }
364# else
365 return hour_to_sec_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_t>
379 constexpr T1 sec_to_hour(T2 ts) noexcept {
380 return static_cast<T1>(ts) / static_cast<T1>(SEC_PER_HOUR);
381 }
382
387 template<class T = int>
388 constexpr fts_t hour_to_fsec(T hr) noexcept {
389 return static_cast<fts_t>(hr) * static_cast<fts_t>(SEC_PER_HOUR);
390 }
391
396 template<class T = ts_t>
397 constexpr double sec_to_fhour(T ts) noexcept {
398 return static_cast<double>(ts) / static_cast<double>(SEC_PER_HOUR);
399 }
400
401//------------------------------------------------------------------------------
402
407 template<class T = year_t>
408 constexpr T get_unix_year(ts_t ts) noexcept {
409 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
410 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
411 // Поэтому пришлось снизить до 9223371890843040000
412 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
413 constexpr int64_t BIAS_2000 = 946684800LL;
414
415 int64_t y = MAX_YEAR;
416 int64_t secs = -((ts - BIAS_2000) - BIAS_292277022000);
417
418 const int64_t n_400_years = secs / SEC_PER_400_YEARS;
419 secs -= n_400_years * SEC_PER_400_YEARS;
420 y -= n_400_years * 400;
421
422 const int64_t n_100_years = secs / SEC_PER_100_YEARS;
423 secs -= n_100_years * SEC_PER_100_YEARS;
424 y -= n_100_years * 100;
425
426 const int64_t n_4_years = secs / SEC_PER_4_YEARS;
427 secs -= n_4_years * SEC_PER_4_YEARS;
428 y -= n_4_years * 4;
429
430 const int64_t n_1_years = secs / SEC_PER_YEAR;
431 secs -= n_1_years * SEC_PER_YEAR;
432 y -= n_1_years;
433
434 y = secs == 0 ? y : y - 1;
435 return y - UNIX_EPOCH;
436 }
437
438//------------------------------------------------------------------------------
439
444 template<class T = int>
445 TIME_SHIELD_CONSTEXPR inline T hour24_to_12(T hour) noexcept {
446 if (hour == 0 || hour > 12) return 12;
447 return hour;
448 }
449
450//------------------------------------------------------------------------------
451
462 template<class T1 = DateTimeStruct, class T2 = ts_t>
464 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
465 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
466 // Поэтому пришлось снизить до 9223371890843040000
467 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
468 constexpr int64_t BIAS_2000 = 946684800LL;
469
470 int64_t y = MAX_YEAR;
471 uint64_t secs = -((ts - BIAS_2000) - BIAS_292277022000);
472
473 const uint64_t n_400_years = secs / SEC_PER_400_YEARS;
474 secs -= n_400_years * SEC_PER_400_YEARS;
475 y -= n_400_years * 400;
476
477 const uint64_t n_100_years = secs / SEC_PER_100_YEARS;
478 secs -= n_100_years * SEC_PER_100_YEARS;
479 y -= n_100_years * 100;
480
481 const uint64_t n_4_years = secs / SEC_PER_4_YEARS;
482 secs -= n_4_years * SEC_PER_4_YEARS;
483 y -= n_4_years * 4;
484
485 const uint64_t n_1_years = secs / SEC_PER_YEAR;
486 secs -= n_1_years * SEC_PER_YEAR;
487 y -= n_1_years;
488
489 T1 date_time;
490
491 if (secs == 0) {
492 date_time.year = y;
493 date_time.mon = 1;
494 date_time.day = 1;
495 return date_time;
496 }
497
498 date_time.year = y - 1;
499 const bool is_leap_year = is_leap_year_date(date_time.year);
500 secs = is_leap_year ? SEC_PER_LEAP_YEAR - secs : SEC_PER_YEAR - secs;
501 const int days = static_cast<int>(secs / SEC_PER_DAY);
502
503 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60 - 1;
504 constexpr int TABLE_MONTH_OF_YEAR[] = {
505 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 январь
506 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 февраль
507 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 март
508 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 апрель
509 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,
510 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,
511 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,
512 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,
513 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,
514 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,
515 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,
516 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,
517 };
518 constexpr int TABLE_DAY_OF_YEAR[] = {
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, // 28 февраль
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, // 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, // 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,
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,31,
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 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,
530 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,
531 };
532
533 if (is_leap_year) {
534 const int prev_days = days - 1;
535 date_time.day = days == JAN_AND_FEB_DAY_LEAP_YEAR ? (TABLE_DAY_OF_YEAR[prev_days] + 1) :
536 (days > JAN_AND_FEB_DAY_LEAP_YEAR ? TABLE_DAY_OF_YEAR[prev_days] : TABLE_DAY_OF_YEAR[days]);
537 date_time.mon = days >= JAN_AND_FEB_DAY_LEAP_YEAR ? TABLE_MONTH_OF_YEAR[prev_days] : TABLE_MONTH_OF_YEAR[days];
538 } else {
539 date_time.day = TABLE_DAY_OF_YEAR[days];
540 date_time.mon = TABLE_MONTH_OF_YEAR[days];
541 }
542
543 ts_t day_secs = static_cast<ts_t>(secs % SEC_PER_DAY);
544 date_time.hour = static_cast<decltype(date_time.hour)>(day_secs / SEC_PER_HOUR);
545 ts_t min_secs = static_cast<ts_t>(day_secs - date_time.hour * SEC_PER_HOUR);
546 date_time.min = static_cast<decltype(date_time.min)>(min_secs / SEC_PER_MIN);
547 date_time.sec = static_cast<decltype(date_time.sec)>(min_secs - date_time.min * SEC_PER_MIN);
548# ifdef TIME_SHIELD_CPP17
549 if TIME_SHIELD_IF_CONSTEXPR (std::is_floating_point<T2>::value) {
550 date_time.ms = static_cast<int>(std::round(std::fmod(static_cast<double>(ts), static_cast<double>(MS_PER_SEC))));
551 } else date_time.ms = 0;
552# else
553 if (std::is_floating_point<T2>::value) {
554 date_time.ms = static_cast<int>(std::round(std::fmod(static_cast<double>(ts), static_cast<double>(MS_PER_SEC))));
555 } else date_time.ms = 0;
556# endif
557 return date_time;
558 }
559
560//------------------------------------------------------------------------------
561
567 template<class T>
570 date_time.ms = ms_of_ts(ts); // Extract and set the ms component
571 return date_time;
572 }
573
574//------------------------------------------------------------------------------
575
606 template<class T1 = year_t, class T2 = int>
607 TIME_SHIELD_CONSTEXPR inline ts_t to_timestamp(
608 T1 year,
609 T2 month,
610 T2 day,
611 T2 hour = 0,
612 T2 min = 0,
613 T2 sec = 0) {
614
615 if (day >= UNIX_EPOCH && year <= 31) {
616 return to_timestamp((T1)day, month, (T2)year, hour, min, sec);
617 }
618 if (!is_valid_date_time(year, month, day, hour, min, sec)) {
619 throw std::invalid_argument("Invalid date-time combination");
620 }
621
622 int64_t secs = 0;
623 uint64_t years = (static_cast<int64_t>(MAX_YEAR) - year);
624
625 const int64_t n_400_years = years / 400;
626 secs += n_400_years * SEC_PER_400_YEARS;
627 years -= n_400_years * 400;
628
629 const int64_t n_100_years = years / 100;
630 secs += n_100_years * SEC_PER_100_YEARS;
631 years -= n_100_years * 100;
632
633 const int64_t n_4_years = years / 4;
634 secs += n_4_years * SEC_PER_4_YEARS;
635 years -= n_4_years * 4;
636
637 secs += years * SEC_PER_YEAR;
638
639 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
640 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
641 // Поэтому пришлось снизить до 9223371890843040000
642 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
643 constexpr int64_t BIAS_2000 = 946684800LL;
644
645 secs = BIAS_292277022000 - secs;
646 secs += BIAS_2000;
647
648 if (month == 1 && day == 1 &&
649 hour == 0 && min == 0 &&
650 sec == 0) {
651 return secs;
652 }
653
654 constexpr int lmos[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
655 constexpr int mos[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
656
657 secs += (is_leap_year_date(year) ? (lmos[month - 1] + day - 1) : (mos[month - 1] + day - 1)) * SEC_PER_DAY;
658 secs += SEC_PER_HOUR * hour + SEC_PER_MIN * min + sec;
659 return secs;
660 }
661
662//------------------------------------------------------------------------------
663
674 template<class T>
675 TIME_SHIELD_CONSTEXPR inline ts_t dt_to_timestamp(
676 const T& date_time) {
677 return to_timestamp(
678 date_time.year,
679 date_time.mon,
680 date_time.day,
681 date_time.hour,
682 date_time.min,
683 date_time.sec);
684 }
685
686//------------------------------------------------------------------------------
687
696 TIME_SHIELD_CONSTEXPR inline ts_t tm_to_timestamp(
697 const std::tm *timeinfo) {
698 return to_timestamp(
699 timeinfo->tm_year + 1900,
700 timeinfo->tm_mon + 1,
701 timeinfo->tm_mday,
702 timeinfo->tm_hour,
703 timeinfo->tm_min,
704 timeinfo->tm_sec);
705 }
706
707//------------------------------------------------------------------------------
708
725 template<class T1 = year_t, class T2 = int>
726 TIME_SHIELD_CONSTEXPR inline ts_ms_t to_timestamp_ms(
727 T1 year,
728 T2 month,
729 T2 day,
730 T2 hour = 0,
731 T2 min = 0,
732 T2 sec = 0,
733 T2 ms = 0) {
734 return sec_to_ms(to_timestamp<T1, T2>(year, month, day, hour, min, sec)) + ms;
735 }
736
737//------------------------------------------------------------------------------
738
749 template<class T>
750 TIME_SHIELD_CONSTEXPR inline ts_t dt_to_timestamp_ms(
751 const T& date_time) {
752 return sec_to_ms(dt_to_timestamp(date_time)) + date_time.ms;
753 }
754
755//------------------------------------------------------------------------------
756
765 TIME_SHIELD_CONSTEXPR inline ts_t tm_to_timestamp_ms(
766 const std::tm *timeinfo) {
767 return sec_to_ms(tm_to_timestamp(timeinfo));
768 }
769
770//------------------------------------------------------------------------------
771
790 template<class T1 = year_t, class T2 = int, class T3 = int>
791 TIME_SHIELD_CONSTEXPR inline fts_t to_ftimestamp(
792 T1 year,
793 T2 month,
794 T2 day,
795 T2 hour = 0,
796 T2 min = 0,
797 T2 sec = 0,
798 T3 ms = 0) {
799 return static_cast<fts_t>(to_timestamp(year, month, day, hour, min, sec)) +
800 static_cast<fts_t>(ms)/static_cast<fts_t>(MS_PER_SEC);
801 }
802
803//------------------------------------------------------------------------------
804
816 template<class T>
817 TIME_SHIELD_CONSTEXPR inline fts_t dt_to_ftimestamp(
818 const T& date_time) {
819 return static_cast<fts_t>(to_timestamp(date_time)) +
820 static_cast<fts_t>(date_time.ms)/static_cast<fts_t>(MS_PER_SEC);
821 }
822
823//------------------------------------------------------------------------------
824
834 TIME_SHIELD_CONSTEXPR inline fts_t tm_to_ftimestamp(
835 const std::tm* timeinfo) {
836 return static_cast<fts_t>(tm_to_timestamp(timeinfo));
837 }
838
839//------------------------------------------------------------------------------
840
848 template<class T = uday_t>
849 constexpr T get_unix_day(ts_t ts = time_shield::ts()) noexcept {
850 return ts / SEC_PER_DAY;
851 }
852
853//------------------------------------------------------------------------------
854
863 template<class T = int>
864 constexpr T get_days_difference(ts_t start, ts_t stop) noexcept {
865 return (stop - start) / SEC_PER_DAY;
866 }
867
868//------------------------------------------------------------------------------
869
877 template<class T = uday_t>
878 constexpr T get_unix_day_ms(ts_ms_t t_ms = time_shield::ts_ms()) noexcept {
879 return get_unix_day(ms_to_sec(t_ms));
880 }
881
882//------------------------------------------------------------------------------
883
892 template<class T = ts_t>
893 constexpr T unix_day_to_timestamp(uday_t unix_day) noexcept {
894 return unix_day * SEC_PER_DAY;
895 }
896
897//------------------------------------------------------------------------------
898
907 template<class T = ts_t>
909 return unix_day * MS_PER_DAY;
910 }
911
912//------------------------------------------------------------------------------
913
922 template<class T = ts_t>
924 return unix_day * SEC_PER_DAY + SEC_PER_DAY - 1;
925 }
926
935 template<class T = ts_ms_t>
937 return unix_day * MS_PER_DAY + MS_PER_DAY - 1;
938 }
939
948 template<class T = ts_ms_t>
951 }
952
961 template<class T = ts_ms_t>
965
966//------------------------------------------------------------------------------
967
975 template<class T = int64_t>
977 return ts / SEC_PER_MIN;
978 }
979
980//------------------------------------------------------------------------------
981
989 template<class T = int>
990 constexpr T sec_of_day(ts_t ts = time_shield::ts()) noexcept {
991 return ts % SEC_PER_DAY;
992 }
993
1001 template<class T = int>
1002 constexpr T sec_of_day_ms(ts_ms_t ts_ms) noexcept {
1003 return sec_of_day(ms_to_sec(ts_ms));
1004 }
1005
1016 template<class T1 = int, class T2 = int>
1017 constexpr T1 sec_of_day(
1018 T2 hour,
1019 T2 min,
1020 T2 sec) noexcept {
1021 return hour * SEC_PER_HOUR + min * SEC_PER_MIN + sec;
1022 }
1023
1031 template<class T = int>
1033 return (ts % SEC_PER_MIN);
1034 }
1035
1043 template<class T = int>
1045 return (ts % SEC_PER_HOUR);
1046 }
1047
1048//------------------------------------------------------------------------------
1049
1057 template<class T = year_t>
1058 TIME_SHIELD_CONSTEXPR inline T get_year(ts_t ts = time_shield::ts()) {
1059 return get_unix_year(ts) + UNIX_EPOCH;
1060 }
1061
1062//------------------------------------------------------------------------------
1063
1071 template<class T = year_t>
1072 TIME_SHIELD_CONSTEXPR inline T get_year_ms(ts_ms_t ts_ms = time_shield::ts_ms()) {
1073 return get_year(ms_to_sec(ts_ms));
1074 }
1075
1076//------------------------------------------------------------------------------
1077
1085 TIME_SHIELD_CONSTEXPR inline ts_t start_of_year(ts_t ts) noexcept {
1086 constexpr ts_t BIAS_2100 = 4102444800;
1087 if (ts < BIAS_2100) {
1088 constexpr ts_t SEC_PER_YEAR_X2 = SEC_PER_YEAR * 2;
1089 ts_t year_start_ts = ts % SEC_PER_4_YEARS;
1090 if (year_start_ts < SEC_PER_YEAR) {
1091 return ts - year_start_ts;
1092 } else
1093 if (year_start_ts < SEC_PER_YEAR_X2) {
1094 return ts + SEC_PER_YEAR - year_start_ts;
1095 } else
1096 if (year_start_ts < (SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR)) {
1097 return ts + SEC_PER_YEAR_X2 - year_start_ts;
1098 }
1099 return ts + (SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR) - year_start_ts;
1100 }
1101
1102 constexpr ts_t BIAS_2000 = 946684800;
1103 ts_t secs = ts - BIAS_2000;
1104
1105 ts_t offset_y400 = secs % SEC_PER_400_YEARS;
1106 ts_t start_ts = secs - offset_y400 + BIAS_2000;
1107 secs = offset_y400;
1108
1109 if (secs >= SEC_PER_FIRST_100_YEARS) {
1111 start_ts += SEC_PER_FIRST_100_YEARS;
1112 while (secs >= SEC_PER_100_YEARS) {
1113 secs -= SEC_PER_100_YEARS;
1114 start_ts += SEC_PER_100_YEARS;
1115 }
1116
1117 constexpr ts_t SEC_PER_4_YEARS_V2 = 4 * SEC_PER_YEAR;
1118 if (secs >= SEC_PER_4_YEARS_V2) {
1119 secs -= SEC_PER_4_YEARS_V2;
1120 start_ts += SEC_PER_4_YEARS_V2;
1121 } else {
1122 start_ts += secs - secs % SEC_PER_YEAR;
1123 return start_ts;
1124 }
1125 }
1126
1127 ts_t offset_4y = secs % SEC_PER_4_YEARS;
1128 start_ts += secs - offset_4y;
1129 secs = offset_4y;
1130
1131 if (secs >= SEC_PER_LEAP_YEAR) {
1132 secs -= SEC_PER_LEAP_YEAR;
1133 start_ts += SEC_PER_LEAP_YEAR;
1134 start_ts += secs - secs % SEC_PER_YEAR;
1135 }
1136 return start_ts;
1137 }
1138
1139//------------------------------------------------------------------------------
1140
1148 TIME_SHIELD_CONSTEXPR inline ts_ms_t start_of_year_ms(ts_ms_t ts_ms = time_shield::ts_ms()) noexcept {
1150 }
1151
1152//------------------------------------------------------------------------------
1153
1161 template<class T = year_t>
1162 TIME_SHIELD_CONSTEXPR inline ts_t start_of_year_date(T year) {
1163 if (year < 2100) {
1164 const ts_t year_diff = year >= UNIX_EPOCH ? year - UNIX_EPOCH : UNIX_EPOCH - year;
1165 const ts_t year_start_ts = (year_diff / 4) * SEC_PER_4_YEARS;
1166 const ts_t year_remainder = year_diff % 4;
1167 constexpr ts_t SEC_PER_YEAR_X2 = 2 * SEC_PER_YEAR;
1168 constexpr ts_t SEC_PER_YEAR_V2 = SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR;
1169 switch (year_remainder) {
1170 case 0: return year_start_ts;
1171 case 1: return year_start_ts + SEC_PER_YEAR;
1172 case 2: return year_start_ts + SEC_PER_YEAR_X2;
1173 default: break;
1174 };
1175 return year_start_ts + SEC_PER_YEAR_V2;
1176 }
1177 return to_timestamp(year, 1, 1);
1178 }
1179
1180//------------------------------------------------------------------------------
1181
1189 template<class T = year_t>
1190 TIME_SHIELD_CONSTEXPR inline ts_ms_t start_of_year_date_ms(T year) {
1192 }
1193
1194//------------------------------------------------------------------------------
1195
1202 TIME_SHIELD_CONSTEXPR inline ts_t end_of_year(ts_t ts = time_shield::ts()) {
1203 constexpr ts_t BIAS_2100 = 4102444800;
1204 if (ts < BIAS_2100) {
1205 constexpr ts_t SEC_PER_YEAR_X2 = SEC_PER_YEAR * 2;
1206 constexpr ts_t SEC_PER_YEAR_X3 = SEC_PER_YEAR * 3;
1207 constexpr ts_t SEC_PER_YEAR_X3_V2 = SEC_PER_YEAR_X2 + SEC_PER_LEAP_YEAR;
1208 ts_t year_end_ts = ts % SEC_PER_4_YEARS;
1209 if (year_end_ts < SEC_PER_YEAR) {
1210 return ts + SEC_PER_YEAR - year_end_ts - 1;
1211 } else
1212 if (year_end_ts < SEC_PER_YEAR_X2) {
1213 return ts + SEC_PER_YEAR_X2 - year_end_ts - 1;
1214 } else
1215 if (year_end_ts < SEC_PER_YEAR_X3_V2) {
1216 return ts + SEC_PER_YEAR_X3_V2 - year_end_ts - 1;
1217 }
1218 return ts + (SEC_PER_YEAR_X3 + SEC_PER_LEAP_YEAR) - year_end_ts - 1;
1219 }
1220
1221 constexpr ts_t BIAS_2000 = 946684800;
1222 ts_t secs = ts - BIAS_2000;
1223
1224 ts_t offset_y400 = secs % SEC_PER_400_YEARS;
1225 ts_t end_ts = secs - offset_y400 + BIAS_2000;
1226 secs = offset_y400;
1227
1228 if (secs >= SEC_PER_FIRST_100_YEARS) {
1230 end_ts += SEC_PER_FIRST_100_YEARS;
1231 while (secs >= SEC_PER_100_YEARS) {
1232 secs -= SEC_PER_100_YEARS;
1233 end_ts += SEC_PER_100_YEARS;
1234 }
1235
1236 constexpr ts_t SEC_PER_4_YEARS_V2 = 4 * SEC_PER_YEAR;
1237 if (secs >= SEC_PER_4_YEARS_V2) {
1238 secs -= SEC_PER_4_YEARS_V2;
1239 end_ts += SEC_PER_4_YEARS_V2;
1240 } else {
1241 end_ts += secs - secs % SEC_PER_YEAR;
1242 return end_ts + SEC_PER_YEAR - 1;
1243 }
1244 }
1245
1246 ts_t offset_4y = secs % SEC_PER_4_YEARS;
1247 end_ts += secs - offset_4y;
1248 secs = offset_4y;
1249
1250 if (secs >= SEC_PER_LEAP_YEAR) {
1251 secs -= SEC_PER_LEAP_YEAR;
1252 end_ts += SEC_PER_LEAP_YEAR;
1253 end_ts += secs - secs % SEC_PER_YEAR;
1254 end_ts += SEC_PER_YEAR;
1255 } else {
1256 end_ts += SEC_PER_LEAP_YEAR;
1257 }
1258 return end_ts - 1;
1259 }
1260
1261//------------------------------------------------------------------------------
1262
1269 template<class T = year_t>
1270 TIME_SHIELD_CONSTEXPR inline ts_ms_t end_of_year_ms(ts_ms_t ts_ms = time_shield::ts_ms()) {
1272 }
1273
1274//------------------------------------------------------------------------------
1275
1282 template<class T = int>
1284 return static_cast<T>(((ts - start_of_year(ts)) / SEC_PER_DAY) + 1);
1285 }
1286
1287//------------------------------------------------------------------------------
1288
1295 template<class T = Month>
1296 TIME_SHIELD_CONSTEXPR inline T month_of_year(ts_t ts) noexcept {
1297 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60;
1298 constexpr int TABLE_MONTH_OF_YEAR[] = {
1299 0,
1300 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 январь
1301 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 февраль
1302 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 март
1303 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 апрель
1304 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,
1305 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,
1306 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,
1307 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,
1308 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,
1309 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,
1310 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,
1311 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,
1312 };
1313 const size_t dy = day_of_year(ts);
1314 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]);
1315 }
1316
1317//------------------------------------------------------------------------------
1318
1325 template<class T = int>
1326 TIME_SHIELD_CONSTEXPR inline T day_of_month(ts_t ts = time_shield::ts()) {
1327 constexpr int JAN_AND_FEB_DAY_LEAP_YEAR = 60;
1328 // таблица для обычного года, не високосного
1329 constexpr int TABLE_DAY_OF_YEAR[] = {
1330 0,
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, // 28 февраль
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, // 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, // 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,
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,31,
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 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,
1342 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,
1343 };
1344 const size_t dy = day_of_year(ts);
1345 if(is_leap_year(ts)) {
1346 if(dy == JAN_AND_FEB_DAY_LEAP_YEAR) return TABLE_DAY_OF_YEAR[dy - 1] + 1;
1347 if(dy > JAN_AND_FEB_DAY_LEAP_YEAR) return TABLE_DAY_OF_YEAR[dy - 1];
1348 }
1349 return TABLE_DAY_OF_YEAR[dy];
1350 }
1351
1352//------------------------------------------------------------------------------
1353
1361 template<class T1 = int, class T2 = year_t, class T3 = int>
1362 constexpr T1 num_days_in_month(T2 year, T3 month) noexcept {
1363 if (month > MONTHS_PER_YEAR || month < 0) return 0;
1364 constexpr T1 num_days[13] = {0,31,30,31,30,31,30,31,31,30,31,30,31};
1365 if (month == FEB) {
1366 if (is_leap_year_date(year)) return 29;
1367 return 28;
1368 }
1369 return num_days[month];
1370 }
1371
1372//------------------------------------------------------------------------------
1373
1380 template<class T1 = int>
1381 TIME_SHIELD_CONSTEXPR T1 num_days_in_month_ts(ts_t ts = time_shield::ts()) noexcept {
1382 constexpr T1 num_days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
1383 const int month = month_of_year(ts);
1384 if (month == FEB) {
1385 return is_leap_year(ts) ? 29 : 28;
1386 }
1387 return num_days[month];
1388 }
1389
1390//------------------------------------------------------------------------------
1391
1398 template<class T1 = int, class T2 = year_t>
1399 constexpr T1 num_days_in_year(T2 year) noexcept {
1401 return DAYS_PER_YEAR;
1402 }
1403
1404//------------------------------------------------------------------------------
1405
1412 template<class T = int>
1415 return DAYS_PER_YEAR;
1416 }
1417
1418//------------------------------------------------------------------------------
1419
1427 constexpr ts_t start_of_day(ts_t ts = time_shield::ts()) noexcept {
1428 return ts - (ts % SEC_PER_DAY);
1429 }
1430
1431//------------------------------------------------------------------------------
1432
1440 template<class T = int>
1441 constexpr ts_t start_of_prev_day(ts_t ts = time_shield::ts(), T days = 1) noexcept {
1442 return ts - (ts % SEC_PER_DAY) - SEC_PER_DAY * days;
1443 }
1444
1445//------------------------------------------------------------------------------
1446
1455 return start_of_day(ms_to_sec(ts_ms));
1456 }
1457
1458//------------------------------------------------------------------------------
1459
1468 return ts_ms - (ts_ms % MS_PER_DAY);
1469 }
1470
1471//------------------------------------------------------------------------------
1472
1481 template<class T = int>
1482 constexpr ts_t start_of_next_day(ts_t ts, T days = 1) noexcept {
1483 return start_of_day(ts) + days * SEC_PER_DAY;
1484 }
1485
1486//------------------------------------------------------------------------------
1487
1496 template<class T = int>
1497 constexpr ts_ms_t start_of_next_day_ms(ts_ms_t ts_ms, T days = 1) noexcept {
1499 }
1500
1501//------------------------------------------------------------------------------
1502
1510 template<class T = int>
1511 constexpr ts_t next_day(ts_t ts, T days = 1) noexcept {
1512 return ts + days * SEC_PER_DAY;
1513 }
1514
1522 template<class T = int>
1523 constexpr ts_ms_t next_day_ms(ts_ms_t ts_ms, T days = 1) noexcept {
1524 return ts_ms + days * MS_PER_DAY;
1525 }
1526
1527//------------------------------------------------------------------------------
1528
1535 constexpr ts_t end_of_day(ts_t ts = time_shield::ts()) noexcept {
1536 return ts - (ts % SEC_PER_DAY) + SEC_PER_DAY - 1;
1537 }
1538
1539//------------------------------------------------------------------------------
1540
1548 return end_of_day(ms_to_sec(ts_ms));
1549 }
1550
1551//------------------------------------------------------------------------------
1552
1560 return ts_ms - (ts_ms % MS_PER_DAY) + MS_PER_DAY - 1;
1561 }
1562
1563//------------------------------------------------------------------------------
1564
1574 template<class T1 = Weekday, class T2 = year_t, class T3 = int, class T4 = int>
1575 constexpr T1 day_of_week_date(T2 year, T3 month, T4 day) {
1576 year_t a, y, m, R;
1577 a = (14 - month) / MONTHS_PER_YEAR;
1578 y = year - a;
1579 m = month + MONTHS_PER_YEAR * a - 2;
1580 R = 7000 + ( day + y + (y / 4) - (y / 100) + (y / 400) + (31 * m) / MONTHS_PER_YEAR);
1581 return static_cast<T1>(R % DAYS_PER_WEEK);
1582 }
1583
1584//------------------------------------------------------------------------------
1585
1594 template<class T1 = Weekday, class T2>
1595 constexpr T1 get_weekday_from_date(const T2& date) {
1596 return day_of_week_date(date.year, date.mon, date.day);
1597 }
1598
1599//------------------------------------------------------------------------------
1600
1604 template<class T = Weekday>
1605 constexpr T get_weekday_from_ts(ts_t ts) noexcept {
1606 return static_cast<T>((ts / SEC_PER_DAY + THU) % DAYS_PER_WEEK);
1607 }
1608
1609//------------------------------------------------------------------------------
1610
1614 template<class T = Weekday>
1618
1619//------------------------------------------------------------------------------
1620
1628 TIME_SHIELD_CONSTEXPR inline ts_t start_of_month(ts_t ts = time_shield::ts()) {
1629 return start_of_day(ts) - (day_of_month(ts) - 1) * SEC_PER_DAY;
1630 }
1631
1632//------------------------------------------------------------------------------
1633
1641 TIME_SHIELD_CONSTEXPR inline ts_t end_of_month(ts_t ts = time_shield::ts()) {
1643 }
1644
1645//------------------------------------------------------------------------------
1646
1654 TIME_SHIELD_CONSTEXPR inline ts_t last_sunday_of_month(ts_t ts = time_shield::ts()) {
1656 }
1657
1658//------------------------------------------------------------------------------
1659
1667 template<class T1 = int, class T2 = year_t, class T3 = int>
1668 TIME_SHIELD_CONSTEXPR inline T1 last_sunday_month_day(T2 year, T3 month) {
1669 const T1 days = num_days_in_month(year, month);
1670 return days - day_of_week_date(year, month, days);
1671 }
1672
1673//------------------------------------------------------------------------------
1674
1681 constexpr ts_t start_of_hour(ts_t ts = time_shield::ts()) noexcept {
1682 return ts - (ts % SEC_PER_HOUR);
1683 }
1684
1685//------------------------------------------------------------------------------
1686
1694 return start_of_hour(ms_to_sec(ts_ms));
1695 }
1696
1697//------------------------------------------------------------------------------
1698
1704 return ts_ms - (ts_ms % MS_PER_HOUR);
1705 }
1706
1707//------------------------------------------------------------------------------
1708
1713 constexpr ts_t end_of_hour(ts_t ts = time_shield::ts()) noexcept {
1714 return ts - (ts % SEC_PER_HOUR) + SEC_PER_HOUR - 1;
1715 }
1716
1717//------------------------------------------------------------------------------
1718
1726 return end_of_hour(ms_to_sec(ts_ms));
1727 }
1728
1729//------------------------------------------------------------------------------
1730
1738 return ts_ms - (ts_ms % MS_PER_HOUR) + MS_PER_HOUR - 1;
1739 }
1740
1741//------------------------------------------------------------------------------
1742
1749 template<class T = int>
1750 constexpr T hour_of_day(ts_t ts = time_shield::ts()) noexcept {
1751 return ((ts / SEC_PER_HOUR) % HOURS_PER_DAY);
1752 }
1753
1754//------------------------------------------------------------------------------
1755
1766
1767//------------------------------------------------------------------------------
1768
1779
1780//------------------------------------------------------------------------------
1781
1792
1793//------------------------------------------------------------------------------
1794
1798 constexpr ts_t start_of_min(ts_t ts = time_shield::ts()) noexcept {
1799 return ts - (ts % SEC_PER_MIN);
1800 }
1801
1802//------------------------------------------------------------------------------
1803
1807 constexpr ts_t end_of_min(ts_t ts = time_shield::ts()) noexcept {
1808 return ts - (ts % SEC_PER_MIN) + SEC_PER_MIN - 1;
1809 }
1810
1811//------------------------------------------------------------------------------
1812
1817 template<class T = int>
1818 constexpr T min_of_day(ts_t ts = time_shield::ts()) noexcept {
1819 return ((ts / SEC_PER_MIN) % MIN_PER_DAY);
1820 }
1821
1822//------------------------------------------------------------------------------
1823
1828 template<class T = int>
1829 constexpr T min_of_hour(ts_t ts = time_shield::ts()) noexcept {
1830 return ((ts / SEC_PER_MIN) % MIN_PER_HOUR);
1831 }
1832
1833//------------------------------------------------------------------------------
1834
1839 template<class T = int>
1841 return ts - (ts % p);
1842 }
1843
1844//------------------------------------------------------------------------------
1845
1850 template<class T = int>
1852 return ts - (ts % p) + p - 1;
1853 }
1854
1855//------------------------------------------------------------------------------
1856
1862 template<class T = TimeZoneStruct>
1863 inline T to_time_zone(tz_t offset) {
1864 T tz;
1865 int abs_val = std::abs(offset);
1866 tz.hour = abs_val / SEC_PER_HOUR;
1867 tz.min = (abs_val % SEC_PER_HOUR) / SEC_PER_MIN;
1868 tz.is_positive = (offset >= 0);
1869 return tz;
1870 }
1871
1873
1874}; // namespace time_shield
1875
1877
1878#endif // _TIME_SHIELD_TIME_CONVERSIONS_HPP_INCLUDED
Header for date and time structure and related functions.
Header file with enumerations for weekdays, months, and other time-related categories.
constexpr int64_t MIN_PER_HOUR
Minutes per hour.
constexpr int64_t DAYS_PER_WEEK
Days per week.
constexpr int64_t SEC_PER_YEAR
Seconds per year (365 days)
constexpr int64_t SEC_PER_FIRST_100_YEARS
Seconds per first 100 years.
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.
constexpr int64_t MAX_YEAR
Maximum representable year.
constexpr int64_t MS_PER_MIN
Milliseconds per minute.
Definition constants.hpp:83
constexpr int64_t SEC_PER_LEAP_YEAR
Seconds per leap year (366 days)
constexpr int64_t MIN_PER_DAY
Minutes per day.
constexpr int64_t DAYS_PER_LEAP_YEAR
Days per leap year.
constexpr int64_t SEC_PER_HOUR
Seconds per hour.
constexpr int64_t UNIX_EPOCH
Start year of UNIX time.
constexpr int64_t MS_PER_DAY
Milliseconds per day.
Definition constants.hpp:97
constexpr int64_t MS_PER_SEC
Milliseconds per second.
Definition constants.hpp:77
constexpr int64_t SEC_PER_400_YEARS
Seconds per 400 years.
constexpr int64_t SEC_PER_DAY
Seconds per day.
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
constexpr int64_t SEC_PER_4_YEARS
Seconds per 4 years.
TIME_SHIELD_CONSTEXPR ts_t tm_to_timestamp(const std::tm *timeinfo)
Converts a std::tm structure to a timestamp.
constexpr T sec_of_hour(ts_t ts=time_shield::ts())
Get the second of the hour.
TIME_SHIELD_CONSTEXPR T day_of_month(ts_t ts=time_shield::ts())
Get the day of the month.
constexpr 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.
constexpr T unix_day(ts_t ts=time_shield::ts()) noexcept
Alias for get_unix_day function.
constexpr 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.
TIME_SHIELD_CONSTEXPR fts_t dt_to_ftimestamp(const T &date_time)
Converts a date-time structure to a floating-point timestamp.
constexpr T sec_of_min(ts_t ts=time_shield::ts())
Get the second of the minute.
TIME_SHIELD_CONSTEXPR fts_t tm_to_ftimestamp(const std::tm *timeinfo)
Converts a std::tm structure to a floating-point timestamp.
constexpr ts_t start_of_saturday(ts_t ts=time_shield::ts())
Get the timestamp of the start of Saturday.
constexpr ts_t end_of_week(ts_t ts=time_shield::ts())
Get the timestamp of the end of the week.
constexpr ts_t start_of_period(T p, ts_t ts=time_shield::ts())
Get the timestamp of the start of the period.
TIME_SHIELD_CONSTEXPR T get_year(ts_t ts=time_shield::ts())
Get the year from the timestamp.
TIME_SHIELD_CONSTEXPR ts_ms_t end_of_year_ms(ts_ms_t ts_ms=time_shield::ts_ms())
Get the timestamp in milliseconds of the end of the year.
T to_date_time_ms(ts_ms_t ts)
Converts a timestamp in milliseconds to a date-time structure with milliseconds.
constexpr T get_unix_day(ts_t ts=time_shield::ts()) noexcept
Get UNIX day.
constexpr ts_t start_of_min(ts_t ts=time_shield::ts()) noexcept
Get the timestamp of the beginning of the minute.
TIME_SHIELD_CONSTEXPR T month_of_year(ts_t ts) noexcept
Get the month of the year.
constexpr T get_days_difference(ts_t start, ts_t stop) noexcept
Get the number of days between two timestamps.
constexpr T1 min_to_sec(T2 ts) noexcept
Converts a timestamp from minutes to seconds.
TIME_SHIELD_CONSTEXPR T1 last_sunday_month_day(T2 year, T3 month)
Get the day of the last Sunday of the given month and year.
constexpr 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 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.
constexpr 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 T sec_of_day(ts_t ts=time_shield::ts()) noexcept
Get the second of the day.
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
Get the millisecond part of the timestamp.
TIME_SHIELD_CONSTEXPR ts_t end_of_year(ts_t ts=time_shield::ts())
Get the end-of-year timestamp.
constexpr T get_unix_day_ms(ts_ms_t t_ms=time_shield::ts_ms()) noexcept
Get UNIX day from milliseconds timestamp.
constexpr double sec_to_fhour(T ts) noexcept
Converts a timestamp from seconds to floating-point hours.
constexpr 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 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 T min_of_hour(ts_t ts=time_shield::ts()) noexcept
Get minute of hour. This function returns a value between 0 to 59.
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.
constexpr ts_t start_of_hour(ts_t ts=time_shield::ts()) noexcept
Get the timestamp at the start of the hour.
T to_time_zone(tz_t offset)
Converts an integer to a time zone structure.
constexpr T hour_of_day(ts_t ts=time_shield::ts()) noexcept
Get the hour of the day.
constexpr T get_unix_min(ts_t ts=time_shield::ts())
Get UNIX minute.
constexpr T unix_day_to_timestamp(uday_t unix_day) noexcept
Converts a UNIX day to a timestamp in seconds.
constexpr T1 hour_to_sec(T2 ts) noexcept
Converts a timestamp from hours to seconds.
TIME_SHIELD_CONSTEXPR ts_t start_of_year(ts_t ts) noexcept
Get the start of the year timestamp.
TIME_SHIELD_CONSTEXPR T get_year_ms(ts_ms_t ts_ms=time_shield::ts_ms())
Get the year from the timestamp in milliseconds.
constexpr ts_t end_of_day(ts_t ts=time_shield::ts()) noexcept
Get the timestamp at the end of the day.
T day_of_year(ts_t ts=time_shield::ts())
Get the day 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).
TIME_SHIELD_CONSTEXPR ts_t tm_to_timestamp_ms(const std::tm *timeinfo)
Converts a std::tm structure to a timestamp in milliseconds.
constexpr T sec_of_day_ms(ts_ms_t ts_ms) noexcept
Get the second of the day from milliseconds timestamp.
constexpr double sec_to_fmin(T ts) noexcept
Converts a timestamp from seconds to floating-point minutes.
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 ts_t start_of_month(ts_t ts=time_shield::ts())
Get the timestamp at the start of the current month.
constexpr T get_weekday_from_ts_ms(ts_ms_t ts_ms)
Get the weekday from a timestamp in milliseconds.
TIME_SHIELD_CONSTEXPR ts_t dt_to_timestamp(const T &date_time)
Converts a date-time structure to a timestamp.
constexpr fts_t hour_to_fsec(T hr) noexcept
Converts a timestamp from hours to floating-point seconds.
constexpr 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.
TIME_SHIELD_CONSTEXPR 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.
constexpr T1 num_days_in_month(ts_t ts=time_shield::ts()) noexcept
Alias for num_days_in_month_ts function.
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 fts_t to_ftimestamp(const T &date_time)
Alias for dt_to_ftimestamp.
TIME_SHIELD_CONSTEXPR ts_t end_of_month(ts_t ts=time_shield::ts())
Get the last timestamp of the current month.
constexpr ts_t start_of_day(ts_t ts=time_shield::ts()) noexcept
Get the start of the day timestamp.
constexpr 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 ts_t to_timestamp(const T &date_time)
Alias for dt_to_timestamp function.
constexpr ts_ms_t ts_ms(year_t year, int month, int day)
Alias for to_timestamp_ms.
constexpr T num_days_in_year_ts(ts_t ts=time_shield::ts())
Get the number of days in the current year.
constexpr ts_t end_of_min(ts_t ts=time_shield::ts()) noexcept
Get the timestamp of the end of the minute.
constexpr 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.
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.
TIME_SHIELD_CONSTEXPR ts_t start_of_year_date(T year)
Get the timestamp of the start of the year.
constexpr T get_unix_year(ts_t ts) noexcept
Converts a UNIX timestamp to a year.
constexpr 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 ts_t end_of_period(T p, ts_t ts=time_shield::ts())
Get the timestamp of the end of the period.
constexpr 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 T1 ms_to_min(T2 ts) noexcept
Converts a timestamp from milliseconds to minutes.
constexpr ts_t next_day(ts_t ts, T days=1) noexcept
Calculate the timestamp for a specified number of days in the future.
constexpr T unix_day_to_timestamp_ms(uday_t unix_day) noexcept
Converts a UNIX day to a 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.
TIME_SHIELD_CONSTEXPR ts_t dt_to_timestamp_ms(const T &date_time)
Converts a date-time structure to a timestamp in milliseconds.
constexpr T days(ts_t start, ts_t stop) noexcept
Alias for get_days_difference function.
constexpr T1 sec_to_hour(T2 ts) noexcept
Converts a timestamp from seconds to hours.
constexpr T1 day_of_week_date(T2 year, T3 month, T4 day)
Get the day of the week.
constexpr ts_t start_of_week(ts_t ts=time_shield::ts())
Get the timestamp of the beginning of the week.
constexpr 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 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.
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 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 T1 get_weekday_from_date(const T2 &date)
Get the day of the week from a date structure.
constexpr 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).
TIME_SHIELD_CONSTEXPR T year(ts_t ts=time_shield::ts())
Alias for get_year function.
constexpr 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 T get_weekday_from_ts(ts_t ts) noexcept
Get the weekday from a timestamp.
constexpr fts_t ms_to_fsec(T ts_ms) noexcept
Converts a timestamp from milliseconds to floating-point seconds.
TIME_SHIELD_CONSTEXPR ts_ms_t start_of_year_date_ms(T year)
Get the timestamp in milliseconds of the start of the year.
ts_ms_t fsec_to_ms(fts_t ts) noexcept
Converts a floating-point timestamp from seconds to milliseconds.
constexpr 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.
constexpr 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 ts_t to_timestamp_ms(const T &date_time)
Alias for dt_to_timestamp_ms function.
constexpr T1 num_days_in_year(T2 year) noexcept
Get the number of days in a given year.
TIME_SHIELD_CONSTEXPR 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.
@ FEB
February.
Definition enums.hpp:95
@ SAT
Saturday.
Definition enums.hpp:34
@ THU
Thursday.
Definition enums.hpp:32
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:46
int32_t tz_t
Time zone offset in minutes from UTC (e.g., +180 = UTC+3).
Definition types.hpp:58
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:47
int64_t uday_t
Unix day count since 1970‑01‑01 (days since epoch).
Definition types.hpp:42
double fts_t
Floating-point timestamp (fractional seconds since epoch).
Definition types.hpp:49
int64_t year_t
Year as an integer (e.g., 2024).
Definition types.hpp:41
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 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.
constexpr 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(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.