stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
chrono.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023 Amebis
4*/
5
6#pragma once
7
8#include "sal.hpp"
9#include "system.hpp"
10#include <stdint.h>
11#include <chrono>
12#include <stdexcept>
13
14namespace stdex {
15 namespace chrono
16 {
20 struct aosn_date
21 {
22 using rep = int32_t;
23 using period = std::ratio<86400>; // 1 day
24 using duration = std::chrono::duration<rep, period>;
25 using time_point = std::chrono::time_point<aosn_date>;
26 static constexpr bool is_steady = false;
27
31 static time_point now() noexcept
32 {
33#ifdef _WIN32
34 FILETIME t;
35 GetSystemTimeAsFileTime(&t);
36 return from_system(t);
37#else
38 time_t t;
39 time(&t);
40 return from_time_t(t);
41#endif
42 }
43
47 static __time64_t to_time_t(_In_ const time_point tp) noexcept
48 {
49 return static_cast<__time64_t>(tp.time_since_epoch().count()) * 86400 - 210866803200;
50 }
51
55 static time_point from_time_t(_In_ __time64_t t) noexcept
56 {
57 return time_point(duration(static_cast<rep>((t + 210866803200) / 86400)));
58 }
59
60#ifdef _WIN32
64 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
65 {
66 return from_dmy(static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear));
67 }
68
72 static time_point from_system(_In_ const FILETIME& t) noexcept
73 {
74 uint64_t x = ((static_cast<uint64_t>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
75 return time_point(duration(static_cast<rep>(x / 86400000 + 2305814))); // Convert from 100 ns to 1-day interval and adjust epoch
76 }
77
81 static time_point from_system(_In_ DATE t)
82 {
83 SYSTEMTIME st;
84 if (!VariantTimeToSystemTime(t, &st))
85 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
86 return from_system(st);
87 }
88#else
92 static time_point from_system(_In_ const struct timespec& t) noexcept
93 {
94 return from_time_t(t.tv_sec);
95 }
96#endif
97
101 static time_point from_dmy(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year) noexcept
102 {
103 int32_t mtmp, ytmp;
104 if (month > 2) {
105 mtmp = month - 3;
106 ytmp = year;
107 }
108 else {
109 mtmp = month + 9;
110 ytmp = year - 1;
111 }
112 int32_t ctmp = (ytmp / 100);
113 int32_t dtmp = ytmp - (100 * ctmp);
114 int32_t result1 = 146097L * ctmp / 4;
115 int32_t result2 = (1461 * dtmp) / 4;
116 int32_t result3 = (153 * mtmp + 2) / 5;
117 return time_point(duration(static_cast<int32_t>(result1) + day + result2 + 1721119L + result3));
118 }
119
123 static void to_dmy(_In_ const time_point tp, _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year) noexcept
124 {
125 int32_t mtmp = tp.time_since_epoch().count() - 1721119L;
126 int32_t yr = (4 * mtmp - 1) / 146097L;
127 mtmp = 4 * mtmp - 1 - 146097L * yr;
128 int32_t da = mtmp / 4;
129 mtmp = (4 * da + 3) / 1461;
130 da = 4 * da + 3 - 1461 * mtmp;
131 da = (da + 4) / 4;
132 int32_t mo = (5 * da - 3) / 153;
133 da = 5 * da - 3 - 153 * mo;
134 da = (da + 5) / 5;
135 yr = 100 * yr + mtmp;
136 if (mo < 10)
137 mo += 3;
138 else {
139 mo -= 9;
140 yr++;
141 }
142 if (day) *day = static_cast<uint8_t>(da);
143 if (month) *month = static_cast<uint8_t>(mo);
144 if (year) *year = yr;
145 }
146
150 static uint8_t day_of_week(_In_ const time_point tp)
151 {
152 return static_cast<uint8_t>(tp.time_since_epoch().count() % 7);
153 }
154
158 static uint8_t day_of_week(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year)
159 {
160 return static_cast<uint8_t>(from_dmy(day, month, year).time_since_epoch().count() % 7);
161 }
162 };
163
168 {
169 using rep = int64_t;
170 using period = std::ratio<1, 1'000'000>; // 1 microsecond
171 using duration = std::chrono::duration<rep, period>;
172 using time_point = std::chrono::time_point<aosn_timestamp>;
173 static constexpr bool is_steady = false;
174
175 static constexpr rep f_second = 1000; // number of milliseconds per second
176 static constexpr rep f_minute = 60; // number of seconds per minute
177 static constexpr rep f_hour = 60; // number of minutes per hour
178 static constexpr rep f_day = 24; // number of hours per day
179 static constexpr rep f_week = 7; // number of days per week
180
181 static constexpr rep p_second = f_second; // number of milliseconds per second
182 static constexpr rep p_minute = f_minute * p_second; // number of milliseconds per minute
183 static constexpr rep p_hour = f_hour * p_minute; // number of milliseconds per hour
184 static constexpr rep p_day = f_day * p_hour; // number of milliseconds per day
185 static constexpr rep p_week = f_week * p_day; // number of milliseconds per week
186
190 static time_point now() noexcept
191 {
192#ifdef _WIN32
193 FILETIME t;
194 GetSystemTimeAsFileTime(&t);
195 return from_system(t);
196#else
197 time_t t;
198 time(&t);
199 return from_time_t(t);
200#endif
201 }
202
206 static __time64_t to_time_t(_In_ const time_point tp) noexcept
207 {
208 return tp.time_since_epoch().count() / p_second - 210866803200;
209 }
210
214 static time_point from_time_t(_In_ __time64_t t) noexcept
215 {
216 return time_point(duration((static_cast<rep>(t) + 210866803200) * p_second));
217 }
218
219#ifdef _WIN32
223 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
224 {
225 return from_dmy(
226 static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear),
227 static_cast<uint8_t>(t.wHour), static_cast<uint8_t>(t.wMinute), static_cast<uint8_t>(t.wSecond), static_cast<uint16_t>(t.wMilliseconds));
228 }
229
233 static time_point from_system(_In_ const FILETIME& t) noexcept
234 {
235 rep x = ((static_cast<rep>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
236 return time_point(duration(x / 10000 + 199222329600000)); // Convert from 100 ns to 1 ms interval and adjust epoch
237 }
238
242 static time_point from_system(_In_ DATE t)
243 {
244 SYSTEMTIME st;
245 if (!VariantTimeToSystemTime(t, &st))
246 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
247 return from_system(st);
248 }
249#else
253 static time_point from_system(_In_ const struct timespec& t) noexcept
254 {
255 return from_time_t(t.tv_sec) + t.tv_nsec / 1000;
256 }
257#endif
258
262 static aosn_date::time_point to_date(_In_ time_point tp) noexcept
263 {
264 return aosn_date::time_point(aosn_date::duration(static_cast<aosn_date::rep>(tp.time_since_epoch().count() / p_day)));
265 }
266
270 static time_point from_date(_In_ aosn_date::time_point date) noexcept
271 {
272 return time_point(duration(static_cast<rep>(date.time_since_epoch().count()) * p_day));
273 }
274
278 static time_point from_dmy(
279 _In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year,
280 _In_ uint8_t hour, _In_ uint8_t minute, _In_ uint8_t second, _In_ uint16_t millisecond) noexcept
281 {
282 return time_point(duration(
283 (static_cast<rep>(aosn_date::from_dmy(day, month, year).time_since_epoch().count()) * p_day) +
284 (static_cast<rep>(hour) * p_hour + static_cast<rep>(minute) * p_minute + static_cast<rep>(second) * p_second + millisecond)));
285 }
286
290 static void to_dmy(_In_ const time_point tp,
291 _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year,
292 _Out_opt_ uint8_t* hour, _Out_opt_ uint8_t* minute, _Out_opt_ uint8_t* second, _Out_opt_ uint16_t* millisecond) noexcept
293 {
294 aosn_date::to_dmy(to_date(tp), day, month, year);
295 int32_t u = static_cast<int32_t>(tp.time_since_epoch().count() % p_day);
296 if (millisecond) *millisecond = static_cast<uint16_t>(u % f_second);
297 u = u / f_second;
298 if (second) *second = static_cast<uint8_t>(u % f_minute);
299 u = u / f_minute;
300 if (minute) *minute = static_cast<uint8_t>(u % f_hour);
301 u = u / f_hour;
302 if (hour) *hour = static_cast<uint8_t>(u);
303 }
304 };
305 }
306}
AOsn date.
Definition chrono.hpp:21
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year) noexcept
Returns time point from calendar day, month and year.
Definition chrono.hpp:101
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year) noexcept
Returns calendar day, month and year from time point.
Definition chrono.hpp:123
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:47
static uint8_t day_of_week(const time_point tp)
Returns day-of-week from time point (0 = Mon, 1 = Tue...)
Definition chrono.hpp:150
static uint8_t day_of_week(uint8_t day, uint8_t month, int32_t year)
Returns day-of-week from calendar day, month and year (0 = Mon, 1 = Tue...)
Definition chrono.hpp:158
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:55
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:92
static time_point now() noexcept
Gets current date.
Definition chrono.hpp:31
AOsn timestamp.
Definition chrono.hpp:168
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:206
static time_point from_date(aosn_date::time_point date) noexcept
Returns time point from aosn_date::time_point.
Definition chrono.hpp:270
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond) noexcept
Returns time point from calendar day, month, year and time.
Definition chrono.hpp:278
static aosn_date::time_point to_date(time_point tp) noexcept
Returns aosn_date::time_point from time point.
Definition chrono.hpp:262
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:253
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:214
static time_point now() noexcept
Gets current timestamp.
Definition chrono.hpp:190
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year, uint8_t *hour, uint8_t *minute, uint8_t *second, uint16_t *millisecond) noexcept
Returns calendar day, month, year and time from time point.
Definition chrono.hpp:290