Time Shield Library
C++ library for working with time
Loading...
Searching...
No Matches
validation.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2#pragma once
3#ifndef _TIME_SHIELD_VALIDATION_HPP_INCLUDED
4#define _TIME_SHIELD_VALIDATION_HPP_INCLUDED
5
10
11#include "config.hpp"
12#include "types.hpp"
13#include "constants.hpp"
14#include "enums.hpp"
15#include "time_zone_struct.hpp"
16
17namespace time_shield {
18
50
55 template<class T = year_t>
56 constexpr bool is_leap_year_date(T year) noexcept {
57 return ((year & 3) == 0 && ((year % 25) != 0 || (year & 15) == 0));
58 }
59
62 template<class T = year_t>
63 constexpr bool check_leap_year(T year) noexcept {
64 return is_leap_year_date(year);
65 }
66
69 template<class T = year_t>
70 constexpr bool leap_year(T year) noexcept {
71 return is_leap_year_date(year);
72 }
73
74//------------------------------------------------------------------------------
75
84 TIME_SHIELD_CONSTEXPR inline bool is_leap_year_ts(ts_t ts) {
85 // 9223372029693630000 - значение на момент 292277024400 от 2000 года
86 // Такое значение приводит к неправильному вычислению умножения n_400_years * SEC_PER_400_YEARS
87 // Поэтому пришлось снизить до 9223371890843040000
88 constexpr int64_t BIAS_292277022000 = 9223371890843040000LL;
89 constexpr int64_t BIAS_2000 = 946684800LL;
90
91 int64_t y = MAX_YEAR;
92 int64_t secs = -((ts - BIAS_2000) - BIAS_292277022000);
93
94 const int64_t n_400_years = secs / SEC_PER_400_YEARS;
95 secs -= n_400_years * SEC_PER_400_YEARS;
96 y -= n_400_years * 400;
97
98 const int64_t n_100_years = secs / SEC_PER_100_YEARS;
99 secs -= n_100_years * SEC_PER_100_YEARS;
100 y -= n_100_years * 100;
101
102 const int64_t n_4_years = secs / SEC_PER_4_YEARS;
103 secs -= n_4_years * SEC_PER_4_YEARS;
104 y -= n_4_years * 4;
105
106 const int64_t n_1_years = secs / SEC_PER_YEAR;
107 secs -= n_1_years * SEC_PER_YEAR;
108 y -= n_1_years;
109
110 y = secs == 0 ? y : y - 1;
111 return is_leap_year_date(y);
112 }
113
116 TIME_SHIELD_CONSTEXPR inline bool leap_year_ts(ts_t ts) {
117 return is_leap_year_ts(ts);
118 }
119
122 TIME_SHIELD_CONSTEXPR inline bool check_leap_year_ts(ts_t ts) {
123 return is_leap_year_ts(ts);
124 }
125
128 TIME_SHIELD_CONSTEXPR inline bool is_leap_year(ts_t ts) {
129 return is_leap_year_ts(ts);
130 }
131
132//------------------------------------------------------------------------------
133
139 template<class T = int>
140 TIME_SHIELD_CONSTEXPR inline bool is_valid_time_zone(
141 T hour,
142 T min) noexcept {
143 if (hour < 0 || hour > 23) return false;
144 if (min < 0 || min > 59) return false;
145 return true;
146 }
147
150 template<class T = int>
151 TIME_SHIELD_CONSTEXPR inline bool is_valid_tz(
152 T hour,
153 T min) {
154 return is_valid_time_zone(hour, min);
155 }
156
157//------------------------------------------------------------------------------
158
164 template<class T = TimeZoneStruct>
165 TIME_SHIELD_CONSTEXPR inline bool is_valid_time_zone_offset(
166 const T& time_zone) noexcept {
167 return is_valid_time_zone(time_zone.hour, time_zone.min);
168 }
169
173 template<class T = TimeZoneStruct>
174 TIME_SHIELD_CONSTEXPR inline bool is_valid_time_zone(
175 const T& time_zone) {
176 return is_valid_time_zone_offset(time_zone);
177 }
178
182 template<class T = TimeZoneStruct>
183 TIME_SHIELD_CONSTEXPR inline bool is_valid_tz(
184 const T& time_zone) {
185 return is_valid_time_zone_offset(time_zone);
186 }
187
188//------------------------------------------------------------------------------
189
198 template<class T1 = int, class T2 = int>
199 TIME_SHIELD_CONSTEXPR inline bool is_valid_time(
200 T1 hour,
201 T1 min,
202 T1 sec,
203 T2 ms = 0) noexcept {
204 if (hour < 0 || hour > 23) return false;
205 if (min < 0 || min > 59) return false;
206 if (sec < 0 || sec > 59) return false;
207 if (ms < 0 || ms > 999) return false;
208 return true;
209 }
210
216 template<class T>
217 TIME_SHIELD_CONSTEXPR inline bool is_valid_time(
218 const T& time) noexcept {
219 return is_valid_time(time.hour, time.min, time.sec, time.ms);
220 }
221
229 template<class T1 = year_t, class T2 = int>
230 TIME_SHIELD_CONSTEXPR inline bool is_valid_date(
231 T1 year,
232 T2 month,
233 T2 day) noexcept {
234 if (day > 31 && year <= 31) {
235 return is_valid_date((T1)day, month, (T2)year);
236 }
237 if (year < MIN_YEAR) return false;
238 if (year > MAX_YEAR) return false;
239 if (month < 1 || month > 12) return false;
240 if (day < 1 || day > 31) return false;
241 if (month == FEB) {
242 const bool is_leap_year = is_leap_year_date(year);
243 if (is_leap_year && day > 29) return false;
244 if (!is_leap_year && day > 28) return false;
245 } else {
246 switch(month) {
247 case 4:
248 case 6:
249 case 9:
250 case 11:
251 if (day > 30) return false;
252 default:
253 break;
254 };
255 }
256 return true;
257 }
258
264 template<class T>
265 TIME_SHIELD_CONSTEXPR inline bool is_valid_date(const T& date) noexcept {
266 return is_valid_date(date.year, date.mon, date.day);
267 }
268
281 template<class T1 = year_t, class T2 = int, class T3 = int>
282 TIME_SHIELD_CONSTEXPR inline bool is_valid_date_time(
283 T1 year,
284 T2 month,
285 T2 day,
286 T2 hour = 0,
287 T2 min = 0,
288 T2 sec = 0,
289 T3 ms = 0) noexcept {
290 if (!is_valid_date(year, month, day)) return false;
291 if (!is_valid_time(hour, min, sec, ms)) return false;
292 return true;
293 }
294
300 template<class T>
301 TIME_SHIELD_CONSTEXPR inline bool is_valid_date_time(
302 const T &date_time) noexcept {
303 if (!is_valid_date(date_time)) return false;
304 if (!is_valid_time(date_time)) return false;
305 return true;
306 }
307
308//------------------------------------------------------------------------------
309
316 TIME_SHIELD_CONSTEXPR inline bool is_day_off(ts_t ts) noexcept {
317 const int64_t day = static_cast<int64_t>(ts) / static_cast<int64_t>(SEC_PER_DAY);
318 int64_t wd64 = (day + static_cast<int64_t>(THU)) % static_cast<int64_t>(DAYS_PER_WEEK);
319 if (wd64 < 0) wd64 += static_cast<int64_t>(DAYS_PER_WEEK); // for ts < 0
320 const int wd = static_cast<int>(wd64);
321 return (wd == SUN || wd == SAT);
322 }
323
326 TIME_SHIELD_CONSTEXPR inline bool is_weekend(ts_t ts) noexcept {
327 return is_day_off(ts);
328 }
329
330//------------------------------------------------------------------------------
331
337 template<class T = uday_t>
338 TIME_SHIELD_CONSTEXPR inline bool is_day_off_unix_day(T unix_day) noexcept {
339 int64_t wd = (static_cast<int64_t>(unix_day) + THU) % DAYS_PER_WEEK;
340 wd += (wd < 0) ? DAYS_PER_WEEK : 0;
341 return (wd == SUN || wd == SAT);
342 }
343
346 template<class T = uday_t>
347 TIME_SHIELD_CONSTEXPR inline bool is_weekend_unix_day(T unix_day) noexcept {
349 }
350
351//------------------------------------------------------------------------------
352
356 TIME_SHIELD_CONSTEXPR inline bool is_workday(ts_t ts) noexcept {
357 return !is_day_off(ts);
358 }
359
363 TIME_SHIELD_CONSTEXPR inline bool is_workday_ms(ts_ms_t ts_ms) noexcept {
364 return is_workday(static_cast<ts_t>(ts_ms / MS_PER_SEC));
365 }
366
372 TIME_SHIELD_CONSTEXPR inline bool is_workday(year_t year, int month, int day) noexcept {
373 const auto y = static_cast<year_t>(year);
374 const auto m = static_cast<int>(month);
375 const auto d = static_cast<int>(day);
376 if (!is_valid_date(y, m, d)) {
377 return false;
378 }
379
380 const int64_t adj_y = static_cast<int64_t>(y) - (static_cast<int64_t>(m) <= 2 ? 1 : 0);
381 const int64_t adj_m = static_cast<int64_t>(m) <= 2
382 ? static_cast<int64_t>(m) + 9
383 : static_cast<int64_t>(m) - 3;
384 const int64_t era = (adj_y >= 0 ? adj_y : adj_y - 399) / 400;
385 const int64_t yoe = adj_y - era * 400;
386 const int64_t doy = (153 * adj_m + 2) / 5 + static_cast<int64_t>(d) - 1;
387 const int64_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
388 const uday_t unix_day = static_cast<uday_t>(era * 146097 + doe - 719468);
389
391 }
392
394
395} // namespace time_shield
396
397#endif // _TIME_SHIELD_VALIDATION_HPP_INCLUDED
Configuration macros for the library.
Header file with time-related constants.
Header file with enumerations for weekdays, months, and other time-related categories.
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_100_YEARS
Seconds per 100 years.
constexpr int64_t MAX_YEAR
Maximum representable year.
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_4_YEARS
Seconds per 4 years.
constexpr int64_t MIN_YEAR
Minimum representable year.
constexpr T unix_day(ts_t ts=time_shield::ts()) noexcept
Alias for days_since_epoch function.
TIME_SHIELD_CONSTEXPR ts_t ts(year_t year, int month, int day)
Alias for to_timestamp.
TIME_SHIELD_CONSTEXPR ts_ms_t ts_ms(year_t year, int month, int day)
Alias for to_timestamp_ms.
constexpr T1 wd(const T2 &date)
Alias for weekday_of_date.
TIME_SHIELD_CONSTEXPR T year(ts_t ts=time_shield::ts())
Alias for year_of function.
@ FEB
February.
Definition enums.hpp:95
@ SUN
Sunday.
Definition enums.hpp:28
@ SAT
Saturday.
Definition enums.hpp:34
@ THU
Thursday.
Definition enums.hpp:32
bool is_workday(const std::string &str)
Parse ISO8601 string and check if it falls on a workday (seconds precision).
bool is_workday_ms(const std::string &str)
Parse ISO8601 string and check if it falls on a workday (milliseconds precision).
TIME_SHIELD_CONSTEXPR bool is_valid_time_zone_offset(const T &time_zone) noexcept
Check if the time zone is valid.
int64_t ts_t
Unix timestamp in seconds since 1970‑01‑01T00:00:00Z.
Definition types.hpp:48
int64_t ts_ms_t
Unix timestamp in milliseconds since epoch.
Definition types.hpp:49
int64_t uday_t
Unix day count since 1970‑01‑01 (days since epoch).
Definition types.hpp:42
int64_t year_t
Year as an integer (e.g., 2024).
Definition types.hpp:41
TIME_SHIELD_CONSTEXPR bool is_day_off(ts_t ts) noexcept
Check if a given timestamp corresponds to a weekend day (Saturday or Sunday).
constexpr bool check_leap_year(T year) noexcept
Alias for is_leap_year_date function.
TIME_SHIELD_CONSTEXPR bool is_leap_year(ts_t ts)
Alias for is_leap_year_ts function.
TIME_SHIELD_CONSTEXPR bool is_valid_tz(T hour, T min)
Alias for is_valid_time_zone function.
TIME_SHIELD_CONSTEXPR bool is_valid_time_zone(T hour, T min) noexcept
Check if the time zone is valid.
TIME_SHIELD_CONSTEXPR bool is_valid_date(T1 year, T2 month, T2 day) noexcept
Checks the correctness of the specified date.
TIME_SHIELD_CONSTEXPR bool is_weekend(ts_t ts) noexcept
Alias for is_day_off function.
TIME_SHIELD_CONSTEXPR bool is_valid_time(T1 hour, T1 min, T1 sec, T2 ms=0) noexcept
Checks the correctness of the specified time.
TIME_SHIELD_CONSTEXPR bool leap_year_ts(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_weekend_unix_day(T unix_day) noexcept
Alias for is_day_off_unix_day function.
TIME_SHIELD_CONSTEXPR bool is_day_off_unix_day(T unix_day) noexcept
Check if a given day (since Unix epoch) corresponds to a weekend day (Saturday or Sunday)....
constexpr bool is_leap_year_date(T year) noexcept
Checks if the given year is a leap year.
TIME_SHIELD_CONSTEXPR bool check_leap_year_ts(ts_t ts)
Alias for is_leap_year_ts function.
TIME_SHIELD_CONSTEXPR bool is_leap_year_ts(ts_t ts)
Checks if the given year is a leap year.
constexpr bool leap_year(T year) noexcept
Alias for is_leap_year_date function.
Main namespace for the Time Shield library.
Header for time zone structure and related functions.
Type definitions for time-related units and formats.