5#include "acme/prototype/mathematics/numeric.h"
6#include "acme/prototype/time/_structures.h"
9#include "acme/platform/uint64_utilities.h"
22#define _TIME_COMPARISON_WITH(TYPE) \
23 inline bool operator == (const TYPE & t) const { return operator == ((class ::time) t); } \
24 inline ::std::strong_ordering operator <=> (const TYPE & t) const { return operator <=> ((class ::time) t); }
27class CLASS_DECL_ACME
time :
50 static time s_timeFirst;
54 constexpr time(zero_t) : posix_time(zero_t{}) { }
56 time(now_t) : posix_time(no_initialize_t{}), nanosecond(no_initialize_t{}) { Now(); }
58 constexpr time(infinite_t) { Infinite(); }
60 constexpr time(
const class ::time& time) : posix_time(time),nanosecond(time) { }
62 explicit time(const ::earth::gregorian_time & time);
64 explicit time(const ::file_time & filetime);
66 template < prototype_
integer INTEGER >
67 constexpr time(INTEGER iSecond)
68 : posix_time( {posix_time_t{}, (::i64)iSecond}), nanosecond({nanosecond_t{}, 0})
74 template < prototype_
floating FLOATING >
75 time(FLOATING fSeconds)
82 template < prototype_
integer INTEGER1, prototype_
integral INTEGRAL2 >
83 constexpr time(INTEGER1 iSecond, INTEGRAL2 iNanosecond) :
84 posix_time( {posix_time_t{}, (::i64)iSecond}), nanosecond({nanosecond_t{}, (::i64)iNanosecond})
88 template < prototype_
floating FLOATING, prototype_number NUMBER >
89 time(FLOATING fSeconds, NUMBER nanoseconds)
92 fset(fSeconds, nanoseconds);
96 template < prototype_
integral INTEGRAL1, prototype_
integral INTEGRAL2 >
97 constexpr time(enum_raw, INTEGRAL1 iSecond, INTEGRAL2 iNanosecond)
101 m_iNanosecond = iNanosecond;
104 template < prototype_
integral INTEGRAL1 >
105 constexpr time(enum_raw, INTEGRAL1 iSecond) : time(e_raw, iSecond, 0) {}
107 template < prototype_
integral INTEGRAL1, prototype_
integral INTEGRAL2 >
108 constexpr time(enum_normalize, INTEGRAL1 iSecond, INTEGRAL2 iNanosecond)
111 m_iSecond = iSecond + iNanosecond / 1'000'000'000;
113 m_iNanosecond = iNanosecond % 1'000'000'000;
115 while(m_iNanosecond < 0)
120 m_iNanosecond += 1'000'000'000;
127 constexpr time(const ::posix_time & posixtime) : posix_time(posixtime), nanosecond({ nanosecond_t{}, 0 }) {}
130 constexpr void raw_set(posix_time posixtime, nanosecond nanosecond = { nanosecond_t{}, 0 });
131 constexpr void set(posix_time posixtime, nanosecond nanosecond);
132 constexpr void set_null();
133 static constexpr time raw_create(posix_time posixtime, nanosecond nanosecond);
134 static constexpr time create(posix_time posixtime, nanosecond nanosecond);
135 static constexpr time create_null();
138 void fset(::f128 dSeconds);
139 void fset(::f128 dSeconds, ::f64 dNanoseconds);
140 static time fcreate(::f128 dSeconds, ::f64 dNanoseconds);
143 constexpr void set(::i64 i, enum_unit eunit);
144 void set(::f128 d, enum_unit eunit);
148 constexpr bool is_infinite()
const;
149 constexpr bool is_null()
const;
150 constexpr bool is_set()
const {
return ! is_null();}
153 constexpr static class ::time infinity();
158 static class ::time local_offset();
165 constexpr class ::time & operator = (
const class time & time);
166 constexpr class ::time & operator = (const ::earth::time_span & time);
168 inline bool timeout(
const class time & time) {
return timeout(time, now()); }
169 constexpr bool timeout(
const class time & time,
const class time & timeNow);
170 constexpr void normalize();
174 constexpr ::i64 total_nanoseconds()
const {
return m_iSecond * 1'000'000'000 + m_iNanosecond; }
179 [[nodiscard]]
static inline class ::time now() {
return now_t{}; }
181 inline bool is_past()
const {
return now() > *
this; }
183 class ::time & Now();
185 constexpr inline class ::time & Infinite()
188 return *
this = infinity();
193 inline class time elapsed() const {
return elapsed(now()); }
194 constexpr class time elapsed(const class time & time )
const {
return time - *
this; }
195 inline bool is_time_out_ok_with_update(
const class time& timeOut)
198 auto timeNow = now();
200 auto timeElapsed = this->elapsed(timeNow);
202 if (timeElapsed < timeOut)
215 inline bool has_timed_out_with_update(
const class time & timeOut)
218 return !is_time_out_ok_with_update(timeOut);
222 inline time update_elapsed() {
return update_elapsed(now()); }
224 constexpr time update_elapsed(
const class time & timeStop)
227 auto elapsed = timeStop - *
this;
235 inline ::f64 period_rate(
const class time & timePeriod)
const {
return period_rate(timePeriod, now()); }
237 constexpr ::f64 period_rate(
const class time & timePeriod,
const class time & time)
const {
return ((time - *
this) % timePeriod) / timePeriod; }
239 inline ::f64 ramp_up(
const class time & timePeriod)
const {
return ramp_up(timePeriod, now()); }
241 constexpr ::f64 ramp_up(
const class time & timePeriod,
const class time & time)
const;
245 constexpr class ::time & operator -= (
const class time & time) { m_iSecond -= time.m_iSecond; m_iNanosecond -= time.m_iNanosecond; normalize();
return *
this; }
246 constexpr class ::time & operator += (
const class time & time) { m_iSecond += time.m_iSecond; m_iNanosecond += time.m_iNanosecond; normalize();
return *
this; }
249 template < prototype_
floating FLOATING >
250 constexpr class ::time operator / (FLOATING d)
const
253 auto nanosecond = (m_iSecond * 1'000'000'000.0 + m_iNanosecond) / d;
255 return { e_raw, (::i64)(nanosecond / 1'000'000'000.0), (long)fmod(nanosecond, 1'000'000'000.0) };
260 template < prototype_
floating FLOATING >
261 constexpr class ::time operator * (FLOATING d)
const
264 auto nanosecond = (m_iSecond * 1'000'000'000.0 + m_iNanosecond) * d;
266 return { e_raw, (::i64)(nanosecond / 1'000'000'000.0), (long)fmod(nanosecond, 1'000'000'000.0) };
271 template < prototype_
integral INTEGRAL >
272 constexpr class ::time operator / (INTEGRAL i)
const
275 auto nanosecond = (m_iSecond * 1'000'000'000 + m_iNanosecond) / i;
277 return { e_raw, (::i64)(nanosecond / 1'000'000'000), (long)(nanosecond % 1'000'000'000) };
282 template < prototype_
integral INTEGRAL >
283 constexpr class ::time operator * (INTEGRAL i)
const
286 auto nanosecond = (m_iSecond * 1'000'000'000 + m_iNanosecond) * i;
288 return { e_raw, (::i64)(nanosecond / 1'000'000'000), (long)(nanosecond % 1'000'000'000) };
293 template < prototype_
floating FLOATING >
294 constexpr class ::time & operator /= (FLOATING d)
297 return operator=(*
this / d);
302 template < prototype_
floating FLOATING >
303 constexpr class ::time & operator *= (FLOATING d)
306 return operator= (*
this / d);
311 template < prototype_
integral INTEGRAL >
312 constexpr class ::time & operator /= (INTEGRAL i)
315 return operator= (*
this / i);
320 template < prototype_
integral INTEGRAL >
321 constexpr class ::time & operator *= (INTEGRAL i)
324 return operator= (*
this * i);
329 constexpr class ::time half()
const;
332 constexpr class ::time & operator %= (
const class time & time);
336 constexpr posix_time GetTimeSpan()
const;
341 inline time remaining(
const class time & time,
const class time & timeNow = now_t{});
344 constexpr class ::time wait()
const;
346 bool on_off(
const class time & period)
const
349 return on_off(period, now());
354 constexpr bool on_off(
const class time & period,
const class time & now)
const
357 return (elapsed(now) % period) < (period / 2);
383 constexpr ::i64 integral_day()
const {
return m_iSecond / 86'400; }
384 constexpr ::i64 integral_hour()
const {
return m_iSecond / 3'600; }
385 constexpr ::i64 integral_minute()
const {
return m_iSecond / 60; }
386 constexpr ::i64 integral_second()
const {
return m_iSecond; }
387 constexpr ::i64 integral_millisecond()
const {
return m_iSecond * 1'000 + m_iNanosecond / 1'000'000; }
388 constexpr ::i64 integral_microsecond()
const {
return m_iSecond * 1'000'000 + m_iNanosecond / 1'000; }
389 constexpr ::i64 integral_nanosecond()
const {
return m_iSecond * 1'000'000'000 + m_iNanosecond; }
392 constexpr ::f64 floating_day()
const {
return floating_second() / 86'400.0; }
393 constexpr ::f64 floating_hour()
const {
return floating_second() / 3'600.0; }
394 constexpr ::f64 floating_minute()
const {
return floating_second() / 60.0; }
395 constexpr ::f64 floating_second()
const {
return ((::f64)m_iSecond) + ((::f64) m_iNanosecond / 1'000'000'000.0); }
396 constexpr ::f64 floating_millisecond()
const {
return ((::f64)m_iSecond * 1'000.0) + ((::f64)m_iNanosecond / 1'000'000.0);}
397 constexpr ::f64 floating_microsecond()
const {
return ((::f64)m_iSecond * 1'000'000.0) + ((::f64)m_iNanosecond / 1'000.0); }
398 constexpr ::f64 floating_nanosecond()
const {
return (::f64)integral_nanosecond(); }
401 ::i32 millisecond()
const {
return (::i32) (m_iNanosecond / 1'000'000); }
404 constexpr bool operator == (
const class time & time)
const {
return m_iSecond == time.m_iSecond && m_iNanosecond == time.m_iNanosecond; }
406 constexpr ::std::strong_ordering operator <=> (
const class time & time)
const
409 auto order = m_iSecond <=> time.m_iSecond;
411 return order != 0 ? order : m_iNanosecond <=> time.m_iNanosecond;
418 ::pair < ::collection::count, time > count_and_remainder(
const class time & time)
const
421 auto d = *
this / time;
423 auto count = (::collection::count)::floor(d);
425 auto remainder = *
this % time;
427 return { count, remainder };
431 constexpr time operator %(
const class time & time)
const;
432 constexpr ::f64 operator /(
const class time & time)
const;
433 constexpr time operator +(
const class time & time)
const {
return { e_normalize, this->m_iSecond + time.m_iSecond, this->m_iNanosecond + time.m_iNanosecond }; }
434 constexpr time operator -(
const class time & time)
const {
return { e_normalize, this->m_iSecond - time.m_iSecond, this->m_iNanosecond - time.m_iNanosecond }; }
437 constexpr time operator -()
const {
return { e_raw, -m_iSecond, -m_iNanosecond}; }
953 posix_time::operator = (posixtime);
955 nanosecond::operator = (nanosecond);
963 raw_set(posixtime, nanosecond);
970constexpr void time::set_null()
973 raw_set({ posix_time_t{}, 0 }, { nanosecond_t{}, 0 });
983 time.raw_set(posixtime, nanosecond);
996 time.set(posixtime, nanosecond);
1003constexpr class ::time time::create_null()
1023constexpr bool time::is_infinite()
const
1026 return m_iSecond == ::numeric_info <
decltype(m_iSecond) > ::maximum();
1030constexpr bool time::is_null()
const
1033 return m_iSecond == 0 && m_iNanosecond == 0;
1045constexpr class ::time time::infinity()
1048 return {(::i64)I64_MAXIMUM,(::i64)0};
1069constexpr posix_time time::GetTimeSpan()
const
1097template < prototype_
floating FLOATING >
1098class time operator * (FLOATING d,
const class time &
time)
1103 return { e_raw, (::i64)(
nanosecond / 1'000'000'000.0), (long)fmod(
nanosecond, 1'000'000'000.0) };
1108template < prototype_
integral INTEGRAL >
1109class time operator * (INTEGRAL i,
const class time &
time)
1130constexpr bool time::timeout(
const class time &
time,
const class time & timeNow)
1133 if (elapsed(timeNow) < time)
1140 operator =(timeNow);
1147inline class time time::remaining(const class time & time, const class time & timeNow)
1150 auto timeRemaining = time - elapsed(timeNow);
1152 return timeRemaining;
1243template < prototype_
integral INTEGRAL >
1244constexpr class time nanosecond_time(INTEGRAL i) {
return { (INTEGRAL)i / 1'000'000'000, (
long)(i % 1'000'000'000) }; }
1245template < prototype_
floating FLOATING >
1246constexpr class time nanosecond_time(FLOATING f) {
return { (::i64)(f / 1'000'000'000.0), (long)(fmod(f, 1'000'000'000.0)) }; }
1247template < prototype_
integral INTEGRAL >
1248constexpr class time microsecond_time(INTEGRAL i) {
return { i / 1'000'000, (long)((i % 1'000'000) * 1'000) }; }
1249template < prototype_
floating FLOATING >
1250constexpr class time microsecond_time(FLOATING f) {
return { (::i64)(f / 1'000'000.0), (long)(fmod(f, 1'000'000.0) * 1'000.0) }; }
1251template < prototype_
integral INTEGRAL >
1252constexpr class time millisecond_time(INTEGRAL i) {
return { i / 1'000, (long)((i % 1'000) * 1'000'000) }; }
1253template < prototype_
floating FLOATING >
1254constexpr class time millisecond_time(FLOATING f) {
return { (::i64)(f / 1'000.0), (long)(fmod(f, 1'000.0) * 1'000'000.0) }; }
1255template < prototype_
integral INTEGRAL >
1256constexpr class time second_time(INTEGRAL i) {
return { i }; }
1257template < prototype_
integral NUMERATOR, prototype_
integral DENOMINATOR >
1258constexpr class time second_time(NUMERATOR numerator, DENOMINATOR denominator)
1262 (::i64) (numerator / denominator),
1263 (::i64) muldiv64((numerator % denominator), 1'000'000'000 , denominator)
1266template < prototype_
floating FLOATING >
1267constexpr class time second_time(FLOATING f) {
return { (FLOATING)(f), (long)(fmod(f, 1.0) * 1'000'000'000.0) }; }
1268template < prototype_
integral INTEGRAL >
1269constexpr class time minute_time(INTEGRAL i) {
return { i * 60 }; }
1270template < prototype_
floating FLOATING >
1271constexpr class time minute_time(FLOATING f) {
return { (FLOATING)(f * 60.0), (long)(fmod(f * 60.0, 1.0) * 1'000'000'000.0) }; }
1272template < prototype_
integral INTEGRAL >
1273constexpr class time hour_time(INTEGRAL i) {
return { i * 3'600 }; }
1274template < prototype_
floating FLOATING >
1275constexpr class time hour_time(FLOATING f) {
return { (FLOATING)(f * 3'600.0), (long)(fmod(f * 3'600.0, 1.0) * 1'000'000'000.0) }; }
1276template < prototype_
integral INTEGRAL >
1277constexpr class time day_time(INTEGRAL i) {
return { i * 86'400 }; }
1278template < prototype_
floating FLOATING >
1279constexpr class time day_time(FLOATING f) {
return { (FLOATING)(f * 86'400.0), (long)(fmod(f * 86'400.0, 1.0) * 1'000'000'000.0) }; }
1284constexpr void time::normalize()
1287 m_iSecond += m_iNanosecond / SECOND_NANOS;
1289 m_iNanosecond %= SECOND_NANOS;
1291 ::i32 iSecondSign = ::numeric::sign(m_iSecond);
1293 ::i32 iNanosecondSign = ::numeric::sign(m_iNanosecond);
1295 if (iSecondSign == -iNanosecondSign && iSecondSign != 0)
1298 m_iSecond -= iSecondSign;
1300 m_iNanosecond += iSecondSign * SECOND_NANOS;
1316constexpr class ::time time::half()
const
1319 auto nanosecond = (m_iSecond * 1'000'000'000 + m_iNanosecond);
1321 auto iSecond = (::i64)(nanosecond / 1'000'000'000);
1323 auto iNanosecond = (long)(nanosecond % 1'000'000'000);
1325 return { e_raw, iSecond, iNanosecond };
1331constexpr class ::time & time::operator %= (
const class time &
time)
1334 auto nanosecondThis = m_iSecond * 1'000'000'000 + m_iNanosecond;
1336 auto nanosecond = time.m_iSecond * 1'000'000'000 + time.m_iNanosecond;
1338 nanosecondThis %= nanosecond;
1340 m_iSecond = nanosecondThis / 1'000'000'000;
1342 m_iNanosecond = nanosecondThis % 1'000'000'000;
1349constexpr class ::time time::operator % (
const class time &
time)
const
1352 class ::time timeResult(*
this);
1361constexpr ::f64 time::operator / (
const class time &
time)
const
1364 auto nanosecondThis = m_iSecond * 1'000'000'000 + m_iNanosecond;
1366 auto nanosecond = time.m_iSecond * 1'000'000'000 + time.m_iNanosecond;
1368 return (::f64)nanosecondThis / (::f64)nanosecond;
1375constexpr void time::set(::i64 i, enum_unit eunit)
1381 raw_set({ posix_time_t{}, i / (1000 * 1000 * 1000) }, { nanosecond_t{}, i % (1000 * 1000 * 1000) });
1384 raw_set({ posix_time_t{},i / (1000 * 1000) }, { nanosecond_t{},(i / 1000) % (1000 * 1000 * 1000) });
1387 raw_set({ posix_time_t{}, i / 1000 }, { nanosecond_t{},(i / (1000 * 1000)) % (1000 * 1000 * 1000) });
1390 raw_set({ posix_time_t{}, i }, { nanosecond_t{},0});
1393 raw_set({ posix_time_t{},i * 60 },{ nanosecond_t{},0});
1396 raw_set({ posix_time_t{},i * 60 * 60 }, { nanosecond_t{}, 0 });
1399 throw_exception(error_bad_argument);
Definition earth_gregorian_time.h:15
Definition aaa_nanosecond.h:9
Definition posix_time.h:8