diff --git a/Source/Time/AuCivilTime.cpp b/Source/Time/AuCivilTime.cpp new file mode 100644 index 00000000..6e32890c --- /dev/null +++ b/Source/Time/AuCivilTime.cpp @@ -0,0 +1,183 @@ +/*** + Copyright (C) 2021-2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuCivilTime.cpp + File: AuClock.cpp + Date: 2023-09-18 + Date: 2021-6-13 + Author: Reece +***/ +#include +#include "AuCivilTime.hpp" +#include "Time.hpp" + +#if defined(AURORA_IS_POSIX_DERIVED) + + #include + +#elif defined(AURORA_IS_MODERNNT_DERIVED) + + #define timegm _mkgmtime + +#else + + using steady_clock = std::chrono::steady_clock; + +#endif + +using sys_clock = std::chrono::system_clock; // more stds to remove + +static sys_clock::duration gEpoch; +static sys_clock::duration gUnixDelta; + +static auto InitEpoch() +{ + std::tm start{0, 15, 10, 29, 7, 101, 0, 0, 0}; + auto epoch = sys_clock::from_time_t(timegm(&start)).time_since_epoch(); + + std::tm unixStart{}; + unixStart.tm_mday = 1; + unixStart.tm_year = 70; + + // dont care what the spec says, you can't trust some ms stls + // sys_clock can have its own epoch for all we care + auto nixEpoch = sys_clock::from_time_t(timegm(&unixStart)).time_since_epoch(); + + gUnixDelta = epoch - nixEpoch; + gEpoch = epoch; + return 0; +} + +static auto ___ = InitEpoch(); + +sys_clock::duration __NormalizeEpoch(sys_clock::duration sysEpoch) +{ + return sysEpoch - gEpoch; +} + +sys_clock::duration __DecodeEpoch(sys_clock::duration auroraEpoch) +{ + return auroraEpoch + gEpoch; +} + +template +static auto TimeFromDurationSinceEpoch(Duration_t in) +{ + auto duration = std::chrono::duration_cast(in); + return std::chrono::time_point(__DecodeEpoch(duration)); +} + +template +static time_t CalculateTimeT(AuUInt64 in) +{ + return sys_clock::to_time_t(TimeFromDurationSinceEpoch(Duration_t(in))); +} + +namespace Aurora::Time +{ + AUKN_SYM time_t SToCTime(AuInt64 time) + { + return CalculateTimeT(time); + } + + AUKN_SYM time_t NSToCTime(AuInt64 time) + { + return CalculateTimeT(time); + } + + AUKN_SYM time_t MSToCTime(AuInt64 time) + { + return CalculateTimeT(time); + } + + AUKN_SYM AuInt64 ConvertAuroraToUnixMS(AuInt64 in) + { + return std::chrono::duration_cast(std::chrono::milliseconds(in) + gUnixDelta).count(); + } + + AUKN_SYM AuInt64 ConvertAuroraToUnixNS(AuInt64 in) + { + return std::chrono::duration_cast(std::chrono::nanoseconds(in) + gUnixDelta).count(); + } + + AUKN_SYM AuInt64 ConvertUnixToAuroraMS(AuInt64 in) + { + return std::chrono::duration_cast(std::chrono::milliseconds(in) - gUnixDelta).count(); + } + + AUKN_SYM AuInt64 ConvertUnixToAuroraNS(AuInt64 in) + { + return std::chrono::duration_cast(std::chrono::nanoseconds(in) - gUnixDelta).count(); + } + + AUKN_SYM tm ToCivilTime(AuInt64 time, bool UTC) + { + std::tm ret {}; + auto timet = MSToCTime(time); + if (UTC) + { + #if defined(AURORA_COMPILER_MSVC) + auto tm = gmtime_s(&ret, &timet); + #else + auto tm = gmtime_r(&timet, &ret); + #endif + #if defined(AURORA_COMPILER_MSVC) + SysAssert(!tm, "couldn't convert civil time"); + #else + SysAssert(tm, "couldn't convert civil time"); + #endif + + } + else + { + #if defined(AURORA_COMPILER_MSVC) + if (localtime_s(&ret, &timet)) + #else + if (!localtime_r(&timet, &ret)) + #endif + { + SysPushErrorGeneric("Couldn't convert local civil time"); + return ToCivilTime(time, true); + } + } + tm _; + _.CopyFrom(ret); + return _; + } + + AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool UTC) + { + ::tm tm; + time_t timet; + + time.CopyTo(tm); + + if (UTC) + { + tm.tm_isdst = 0; + timet = timegm(&tm); + } + else + { + tm.tm_isdst = -1; // out of the 2 crts i've bothered to check, out of 3, this is legal + timet = mktime(&tm); + } + + if ((timet == 0) || (timet == -1)) + { + return 0; + } + + return std::chrono::duration_cast(__NormalizeEpoch(std::chrono::system_clock::from_time_t(timet).time_since_epoch())).count(); + } + + AUKN_SYM tm NormalizeCivilTimezone(const Time::tm &time, ETimezoneShift shift) + { + if ((time.tm_isdst == 0) && (shift == ETimezoneShift::eUTC)) + { + return time; + } + + return ToCivilTime(FromCivilTime(time, shift == ETimezoneShift::eUTC)); + } +} \ No newline at end of file diff --git a/Source/Time/AuCivilTime.hpp b/Source/Time/AuCivilTime.hpp new file mode 100644 index 00000000..c063f905 --- /dev/null +++ b/Source/Time/AuCivilTime.hpp @@ -0,0 +1,13 @@ +/*** + Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuCivilTime.cpp + Date: 2023-09-18 + Author: Reece +***/ +#pragma once + +namespace Aurora::Time +{ + +} \ No newline at end of file diff --git a/Source/Time/AuClock.cpp b/Source/Time/AuClock.cpp index ec477405..5569d103 100644 --- a/Source/Time/AuClock.cpp +++ b/Source/Time/AuClock.cpp @@ -10,12 +10,10 @@ #include "Time.hpp" #if defined(AURORA_IS_POSIX_DERIVED) - - #include - -#elif defined(AURORA_IS_MODERNNT_DERIVED) - #define timegm _mkgmtime + #include + +#elif defined(AURORA_IS_MODERNNT_DERIVED) // benchmarking: https://github.com/microsoft/STL/issues/2085 static AuUInt64 _GetSteadyTimeNS() @@ -53,97 +51,43 @@ } } // ~3.0741 seconds - - // ~6.07 seconds + // using high_res_clock = std::chrono::high_resolution_clock; - + // ~6.07 seconds + // holy fuck, we're keeping this // ~2x improvement #else + using steady_clock = std::chrono::steady_clock; + #endif using sys_clock = std::chrono::system_clock; // more stds to remove -static sys_clock::duration gEpoch; -static sys_clock::duration gUnixDelta; +sys_clock::duration __NormalizeEpoch(sys_clock::duration sysEpoch); -static auto InitEpoch() +static AuInt64 _CurrentClock() { - std::tm start{0, 15, 10, 29, 7, 101, 0, 0, 0}; - auto epoch = sys_clock::from_time_t(timegm(&start)).time_since_epoch(); - - std::tm unixStart{}; - unixStart.tm_mday = 1; - unixStart.tm_year = 70; - - // dont care what the spec says, you can't trust some ms stls - // sys_clock can have its own epoch for all we care - auto nixEpoch = sys_clock::from_time_t(timegm(&unixStart)).time_since_epoch(); - - gUnixDelta = epoch - nixEpoch; - gEpoch = epoch; - return 0; -} - -static auto ___ = InitEpoch(); - -template -static inline T NormalizeEpoch(T sysEpoch) -{ - return sysEpoch - gEpoch; -} - -template -static inline T DecodeEpoch(T auroraEpoch) -{ - return auroraEpoch + gEpoch; -} - -template -static auto TimeFromDurationSinceEpoch(Duration_t in) -{ - auto duration = std::chrono::duration_cast(in); - return std::chrono::time_point(DecodeEpoch(duration)); -} - -template -static time_t CalculateTimeT(AuUInt64 in) -{ - return sys_clock::to_time_t(TimeFromDurationSinceEpoch(Duration_t(in))); + return __NormalizeEpoch(sys_clock::now().time_since_epoch()).count(); } static AuInt64 _CurrentClockMS() { - return std::chrono::duration_cast(NormalizeEpoch(sys_clock::now().time_since_epoch())).count(); + return std::chrono::duration_cast(__NormalizeEpoch(sys_clock::now().time_since_epoch())).count(); } static AuInt64 _CurrentClockNS() { - return std::chrono::duration_cast(NormalizeEpoch(sys_clock::now().time_since_epoch())).count(); + return std::chrono::duration_cast(__NormalizeEpoch(sys_clock::now().time_since_epoch())).count(); } namespace Aurora::Time { - AUKN_SYM time_t SToCTime(AuInt64 time) - { - return CalculateTimeT(time); - } - - AUKN_SYM time_t NSToCTime(AuInt64 time) - { - return CalculateTimeT(time); - } - - AUKN_SYM time_t MSToCTime(AuInt64 time) - { - return CalculateTimeT(time); - } - AUKN_SYM AuInt64 CurrentClock() { - return NormalizeEpoch(sys_clock::now().time_since_epoch()).count(); + return _CurrentClock(); } AUKN_SYM AuInt64 CurrentClockMS() @@ -231,12 +175,7 @@ namespace Aurora::Time AUKN_SYM AuInt64 CTimeToMS(time_t time) { - return std::chrono::duration_cast(NormalizeEpoch(sys_clock::from_time_t(time).time_since_epoch())).count(); - } - - AuInt64 CTimeNSNormalize(AuUInt64 time) - { - return std::chrono::duration_cast(NormalizeEpoch(std::chrono::nanoseconds(time))).count(); + return std::chrono::duration_cast(__NormalizeEpoch(sys_clock::from_time_t(time).time_since_epoch())).count(); } #if defined(AURORA_IS_POSIX_DERIVED) @@ -453,95 +392,4 @@ namespace Aurora::Time ADD_CLOCK_FAMILY(Thread, Thread, (ullUser.QuadPart + ullKernel.QuadPart), /*CLOCK_THREAD_CPUTIME_ID*/0, (true, EPseudoPosixClock::eAll)); ADD_CLOCK_FAMILY(ThreadKernel, Thread, (ullKernel.QuadPart), 0, (true, EPseudoPosixClock::eKernel)); ADD_CLOCK_FAMILY(ThreadUser, Thread, (ullUser.QuadPart), /*CLOCK_THREAD_CPUTIME_ID*/0, (true, EPseudoPosixClock::eUser)); - - AUKN_SYM AuInt64 ConvertAuroraToUnixMS(AuInt64 in) - { - return std::chrono::duration_cast(std::chrono::milliseconds(in) + gUnixDelta).count(); - } - - AUKN_SYM AuInt64 ConvertAuroraToUnixNS(AuInt64 in) - { - return std::chrono::duration_cast(std::chrono::nanoseconds(in) + gUnixDelta).count(); - } - - AUKN_SYM AuInt64 ConvertUnixToAuroraMS(AuInt64 in) - { - return std::chrono::duration_cast(std::chrono::milliseconds(in) - gUnixDelta).count(); - } - - AUKN_SYM AuInt64 ConvertUnixToAuroraNS(AuInt64 in) - { - return std::chrono::duration_cast(std::chrono::nanoseconds(in) - gUnixDelta).count(); - } - - AUKN_SYM tm ToCivilTime(AuInt64 time, bool UTC) - { - std::tm ret {}; - auto timet = MSToCTime(time); - if (UTC) - { - #if defined(AURORA_COMPILER_MSVC) - auto tm = gmtime_s(&ret, &timet); - #else - auto tm = gmtime_r(&timet, &ret); - #endif - #if defined(AURORA_COMPILER_MSVC) - SysAssert(!tm, "couldn't convert civil time"); - #else - SysAssert(tm, "couldn't convert civil time"); - #endif - - } - else - { - #if defined(AURORA_COMPILER_MSVC) - if (localtime_s(&ret, &timet)) - #else - if (!localtime_r(&timet, &ret)) - #endif - { - SysPushErrorGeneric("Couldn't convert local civil time"); - return ToCivilTime(time, true); - } - } - tm _; - _.CopyFrom(ret); - return _; - } - - AUKN_SYM AuInt64 FromCivilTime(const tm &time, bool UTC) - { - ::tm tm; - time_t timet; - - time.CopyTo(tm); - - if (UTC) - { - tm.tm_isdst = 0; - timet = timegm(&tm); - } - else - { - tm.tm_isdst = -1; // out of the 2 crts i've bothered to check, out of 3, this is legal - timet = mktime(&tm); - } - - if ((timet == 0) || (timet == -1)) - { - return 0; - } - - return std::chrono::duration_cast(NormalizeEpoch(std::chrono::system_clock::from_time_t(timet).time_since_epoch())).count(); - } - - AUKN_SYM tm NormalizeCivilTimezone(const Time::tm &time, ETimezoneShift shift) - { - if ((time.tm_isdst == 0) && (shift == ETimezoneShift::eUTC)) - { - return time; - } - - return ToCivilTime(FromCivilTime(time, shift == ETimezoneShift::eUTC)); - } } \ No newline at end of file diff --git a/Source/Time/AuClock.hpp b/Source/Time/AuClock.hpp index 26ed8796..d7f67009 100644 --- a/Source/Time/AuClock.hpp +++ b/Source/Time/AuClock.hpp @@ -6,3 +6,8 @@ Author: Reece ***/ #pragma once + +namespace Aurora::Time +{ + +} \ No newline at end of file diff --git a/Source/Time/Time.hpp b/Source/Time/Time.hpp index be5e11e8..93f4e6b8 100644 --- a/Source/Time/Time.hpp +++ b/Source/Time/Time.hpp @@ -13,8 +13,6 @@ namespace Aurora::Time { - AuInt64 CTimeNSNormalize(AuUInt64 time); - #if defined(AURORA_PLATFORM_WIN32) static AuInt64 ConvertTimestamp(const FILETIME &ft)