LCOV - code coverage report
Current view: top level - ezlibs - ezTime.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 7.5 % 161 12
Test Date: 2025-09-16 22:55:37 Functions: 4.8 % 42 2
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75.0 % 4 3

             Branch data     Line data    Source code
       1                 :             : #pragma once
       2                 :             : 
       3                 :             : /*
       4                 :             : MIT License
       5                 :             : 
       6                 :             : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
       7                 :             : 
       8                 :             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :             : of this software and associated documentation files (the "Software"), to deal
      10                 :             : in the Software without restriction, including without limitation the rights
      11                 :             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :             : copies of the Software, and to permit persons to whom the Software is
      13                 :             : furnished to do so, subject to the following conditions:
      14                 :             : 
      15                 :             : The above copyright notice and this permission notice shall be included in all
      16                 :             : copies or substantial portions of the Software.
      17                 :             : 
      18                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24                 :             : SOFTWARE.
      25                 :             : */
      26                 :             : 
      27                 :             : // ezTime is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
      28                 :             : 
      29                 :             : #include "ezOS.hpp"
      30                 :             : 
      31                 :             : #include <ctime>
      32                 :             : #include <string>
      33                 :             : #include <chrono>
      34                 :             : #include <thread>
      35                 :             : #include <iomanip>
      36                 :             : #include <sstream>
      37                 :             : #include <cstdint>
      38                 :             : #include <functional>
      39                 :             : 
      40                 :             : #ifndef EZ_TIME
      41                 :             : #define EZ_TIME
      42                 :             : #endif  // EZ_TIME
      43                 :             : 
      44                 :             : namespace ez {
      45                 :             : namespace time {
      46                 :             : 
      47                 :             : // convert a string ISO8601 time to epoch time
      48                 :           0 : inline bool iso8601ToEpoch(const std::string& vIsoDateTime, const std::string& vTimeFormat, std::time_t& vOutTime) {
      49                 :           0 :     if (!vIsoDateTime.empty() && !vTimeFormat.empty()) {
      50                 :           0 :         struct std::tm time = {};
      51                 :           0 :         std::istringstream iss(vIsoDateTime);
      52                 :           0 :         iss >> std::get_time(&time, vTimeFormat.c_str());
      53                 :           0 :         if (!iss.fail()) {
      54                 :           0 :             time.tm_hour = 0;
      55                 :           0 :             time.tm_min = 0;
      56                 :           0 :             time.tm_sec = 0;
      57                 :           0 : #ifdef WINDOWS_OS
      58                 :           0 :             vOutTime = _mkgmtime(&time);
      59                 :           0 : #else
      60                 :           0 :             vOutTime = timegm(&time);
      61                 :           0 : #endif
      62                 :           0 :             return true;
      63                 :           0 :         }
      64                 :           0 :     }
      65                 :           0 :     return false;
      66                 :           0 : }
      67                 :             : 
      68                 :             : // convert a epoch time to a string ISO8601 time
      69                 :           0 : inline bool epochToISO8601(const std::time_t& vEpochTime, std::string& vOutTime) {
      70                 :           0 :     auto tp = std::chrono::system_clock::from_time_t(vEpochTime);
      71                 :           0 :     auto tt = std::chrono::system_clock::to_time_t(tp);
      72                 :           0 : #ifdef _MSC_VER
      73                 :           0 :     tm _timeinfo;
      74                 :           0 :     tm* pTimeInfo = &_timeinfo;
      75                 :           0 :     if (localtime_s(pTimeInfo, &tt) != 0) {
      76                 :           0 :         return false;
      77                 :           0 :     }
      78                 :           0 : #else
      79                 :           0 :     auto* pTimeInfo = std::localtime(&tt);
      80                 :           0 : #endif
      81                 :           0 :     std::ostringstream oss;
      82                 :           0 :     oss << std::put_time(pTimeInfo, "%Y-%m-%d");
      83                 :           0 :     if (!oss.fail()) {
      84                 :           0 :         vOutTime = oss.str();
      85                 :           0 :         return true;
      86                 :           0 :     }
      87                 :           0 :     return false;
      88                 :           0 : }
      89                 :             : 
      90                 :             : // TODO: TO TEST
      91                 :           0 : inline tm decomposeEpoch(const std::time_t& vEpochTime) {
      92                 :           0 :     tm ret{};
      93                 :           0 :     auto tp = std::chrono::system_clock::from_time_t(vEpochTime);
      94                 :           0 :     auto tt = std::chrono::system_clock::to_time_t(tp);
      95                 :           0 : #ifdef _MSC_VER
      96                 :           0 :     tm _timeinfo;
      97                 :           0 :     tm* pTimeInfo = &_timeinfo;
      98                 :           0 :     if (localtime_s(pTimeInfo, &tt) != 0) {
      99                 :           0 :         return ret;
     100                 :           0 :     }
     101                 :           0 : #else
     102                 :           0 :     auto* pTimeInfo = std::localtime(&tt);
     103                 :           0 : #endif
     104                 :           0 :     ret = *pTimeInfo;
     105                 :           0 :     return ret;
     106                 :           0 : }
     107                 :             : 
     108                 :             : // TODO: TO TEST
     109                 :           0 : inline std::string getCurrentDate() {
     110                 :           0 :     auto curr_date_t = std::time(nullptr);
     111                 :           0 : #ifdef _MSC_VER
     112                 :           0 :     tm _timeinfo;
     113                 :           0 :     tm* tm_curr_date = &_timeinfo;
     114                 :           0 :     if (localtime_s(tm_curr_date, &curr_date_t) != 0) {
     115                 :           0 :         return {};
     116                 :           0 :     }
     117                 :           0 : #else
     118                 :           0 :     auto* tm_curr_date = std::localtime(&curr_date_t);
     119                 :           0 : #endif
     120                 :           0 :     char buffer[32 + 1]{};
     121                 :           0 :     auto s = strftime(buffer, 32, "%Y-%m-%d", tm_curr_date);
     122                 :           0 :     buffer[s] = '\0';
     123                 :           0 :     return std::string(buffer);
     124                 :           0 : }
     125                 :             : 
     126                 :             : // TODO: TO TEST
     127                 :           0 : inline std::string getCurrentDate(size_t vHoursOffset) {
     128                 :           0 :     auto curr_date_t = std::time(nullptr);
     129                 :           0 : #ifdef _MSC_VER
     130                 :           0 :     tm _timeinfo;
     131                 :           0 :     tm* tm_curr_date = &_timeinfo;
     132                 :           0 :     if (localtime_s(tm_curr_date, &curr_date_t) != 0) {
     133                 :           0 :         return {};
     134                 :           0 :     }
     135                 :           0 : #else
     136                 :           0 :     std::localtime(&curr_date_t);
     137                 :           0 : #endif
     138                 :           0 :     std::chrono::hours offset_hours(vHoursOffset);
     139                 :           0 :     auto curr_date = std::chrono::system_clock::from_time_t(curr_date_t);
     140                 :           0 :     auto offset_date_t = std::chrono::system_clock::to_time_t(curr_date + offset_hours);
     141                 :           0 : #ifdef _MSC_VER
     142                 :           0 :     tm* tm_offset_date = &_timeinfo;
     143                 :           0 :     if (localtime_s(tm_offset_date, &offset_date_t) != 0) {
     144                 :           0 :         return {};
     145                 :           0 :     }
     146                 :           0 : #else
     147                 :           0 :     auto* tm_offset_date = std::localtime(&offset_date_t);
     148                 :           0 : #endif
     149                 :           0 :     char buffer[32+1]{};
     150                 :           0 :     auto s = strftime(buffer, 32, "%Y-%m-%d", tm_offset_date);
     151                 :           0 :     buffer[s] = '\0';
     152                 :           0 :     return std::string(buffer);
     153                 :           0 : }
     154                 :             : 
     155                 :        1211 : inline uint64_t getTicks() {
     156                 :        1211 :     return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
     157                 :        1211 : }
     158                 :             : 
     159                 :             : // TODO: TO TEST
     160                 :           0 : inline float getTimeInterval() {
     161                 :           0 :     static auto S_lastTick = getTicks();
     162                 :           0 :     const uint64_t ticks = getTicks();
     163                 :           0 :     static float secMult = 1.0f / 1000.0f;
     164                 :           0 :     const float interval = (ticks - S_lastTick) * secMult;
     165                 :           0 :     S_lastTick = ticks;
     166                 :           0 :     return interval;
     167                 :           0 : }
     168                 :             : 
     169                 :             : // TODO: TO TEST
     170                 :             : class ActionTime {
     171                 :             : private:
     172                 :             :     uint64_t m_LastTick = 0U;
     173                 :             :     uint64_t m_PauseTick = 0U;
     174                 :             :     uint64_t m_ResumeTick = 0U;
     175                 :             :     bool m_Play = true;
     176                 :             : 
     177                 :             : public:
     178                 :           0 :     ActionTime() {
     179                 :           0 :         m_LastTick = getTicks();
     180                 :           0 :     }
     181                 :             :     
     182                 :           0 :     void fix() {  // fixe les marqueur de temps
     183                 :           0 :         m_LastTick = getTicks();
     184                 :           0 :         m_PauseTick = getTicks();
     185                 :           0 :         m_ResumeTick = getTicks();
     186                 :           0 :     }
     187                 :             :     
     188                 :           0 :     void fixTime(double vValue) {  // fixe les marqueur de temps
     189                 :           0 :         fix();
     190                 :           0 :         setTime(vValue);
     191                 :           0 :     }
     192                 :             :     
     193                 :           0 :     void pause() {
     194                 :           0 :         m_PauseTick = getTicks();
     195                 :           0 :         m_Play = false;
     196                 :           0 :     }
     197                 :             :     
     198                 :           0 :     void resume() {
     199                 :           0 :         m_ResumeTick = getTicks();
     200                 :           0 :         m_LastTick += m_ResumeTick - m_PauseTick;
     201                 :           0 :         m_Play = true;
     202                 :           0 :     }
     203                 :             :     
     204                 :           0 :     uint64_t get() const {
     205                 :           0 :         return getTicks() - m_LastTick;
     206                 :           0 :     }
     207                 :             :     
     208                 :           0 :     double getTime() const {
     209                 :           0 :         static double secMult = 1e-3;
     210                 :           0 :         return (getTicks() - m_LastTick) * secMult;
     211                 :           0 :     }
     212                 :             : 
     213                 :           0 :     void setTime(double vValue){  // set le temps
     214                 :           0 :         const auto v = (uint64_t)(vValue * 1000.0);
     215                 :           0 :         m_LastTick = getTicks() - v;
     216                 :           0 :     }
     217                 :             : 
     218                 :             :     // verifie si vMs millisecond depuis le dernier fix et donc si on peut agir
     219                 :             :     // vFix permet de fixer le temps pour la prochaine action
     220                 :             :     // on pourrait vouloir interroger sans vouloir permettre la prochaine action
     221                 :           0 :     bool isTimeToAct(long vMs, bool vFix) {
     222                 :           0 :         if (get() > (uint64_t)vMs) {
     223                 :           0 :             if (vFix) {
     224                 :           0 :                 fix();
     225                 :           0 :             }
     226                 :           0 :             return true;
     227                 :           0 :         }
     228                 :           0 :         return false;
     229                 :           0 :     }
     230                 :             : };
     231                 :             : 
     232                 :             : // TODO: TO TEST
     233                 :             : //! Measure the time in microsecondes of a operation passed via lambda fucntion
     234                 :             : //! the operation will be executed many time according to vCountOperations and averaged
     235                 :             : template <typename TLAMBDA>
     236                 :             : double measureOperationUs(TLAMBDA vLambda, size_t vCountOperations = 1) {
     237                 :             :     using clock = std::chrono::high_resolution_clock;
     238                 :             :     std::chrono::duration<double, std::micro> total{0};
     239                 :             :     for (size_t i = 0; i < vCountOperations; ++i) {
     240                 :             :         auto t0 = clock::now();
     241                 :             :         vLambda();
     242                 :             :         total += clock::now() - t0;
     243                 :             :     }
     244                 :             :     if (vCountOperations > 1) {
     245                 :             :         total /= static_cast<double>(vCountOperations);
     246                 :             :     }
     247                 :             :     return total.count();
     248                 :             : }
     249                 :             : 
     250                 :             : // will wait the condition to be true with a timeout and a step for inc time until ok or timeout
     251                 :           4 : static bool waitUntil(const std::function<bool(void)>& vCond, uint32_t vTimeoutMs, uint32_t vStepMs = 50) {
     252                 :           4 :     using clock = std::chrono::steady_clock;
     253                 :           4 :     auto start = clock::now();
     254         [ +  + ]:           7 :     while (!vCond()) {
     255         [ -  + ]:           3 :         if (std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - start).count() >= vTimeoutMs) {
     256                 :           0 :             return vCond();  // last chance
     257                 :           0 :         }
     258                 :           3 :         std::this_thread::sleep_for(std::chrono::milliseconds(vStepMs));
     259                 :           3 :     }
     260                 :           4 :     return true;
     261                 :           4 : }
     262                 :             : 
     263                 :             : }  // namespace time
     264                 :             : }  // namespace ez
        

Generated by: LCOV version 2.0-1