Last active
March 16, 2021 09:37
-
-
Save luncliff/2f7458ee109ca19e694f2626245b674a to your computer and use it in GitHub Desktop.
C++ Timer with Standard Library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define CATCH_CONFIG_FAST_COMPILE | |
#define CATCH_CONFIG_MAIN | |
#include <catch2/catch.hpp> | |
#include <chrono> | |
#include <ctime> | |
#include <iomanip> | |
/// @brief ISO-8601 time | |
struct date_time final { | |
using clock_type = std::chrono::system_clock; | |
using time_point = typename clock_type::time_point; | |
time_point point = clock_type::now(); | |
public: | |
date_time() noexcept = default; | |
date_time(std::tm &time) noexcept | |
: point{clock_type::from_time_t(std::mktime(&time))} {} | |
date_time(const std::time_t t64) noexcept | |
: point{clock_type::from_time_t(t64)} {} | |
operator std::tm() const noexcept { | |
const std::time_t t64 = static_cast<std::time_t>(*this); | |
std::tm detailed{}; | |
::gmtime_r(&t64, &detailed); // @note for Windows, use `gmtime_s` | |
return detailed; | |
} | |
/// @see time_t The number of elapsed seconds from UNIX epoch | |
/// (1970-01-01 00:00:00) | |
operator std::time_t() const noexcept { return clock_type::to_time_t(point); } | |
operator std::chrono::system_clock::time_point() const noexcept { | |
return point; | |
} | |
/// @brief Generate `string` with given format | |
/// @see https://en.cppreference.com/w/c/chrono/strftime | |
std::string | |
to_string(const char *format = "%Y-%m-%d %H:%M:%S") const noexcept { | |
const std::tm detailed = static_cast<std::tm>(*this); | |
constexpr auto capacity = 100; | |
char buffer[capacity]{}; | |
return {buffer, ::strftime(buffer, capacity, format, &detailed)}; | |
} | |
void from_string(const char *txt) { | |
std::tm time{}; | |
std::stringstream sin{txt}; | |
sin >> std::get_time(&time, "%Y-%m-%d %H:%M:%S"); | |
point = clock_type::from_time_t(std::mktime(&time)); | |
} | |
}; | |
template <typename R, typename P> | |
date_time operator+(date_time t, | |
std::chrono::duration<R, P> duration) noexcept { | |
t.point += duration; | |
return t; | |
} | |
template <typename R, typename P> | |
date_time operator-(date_time t, | |
std::chrono::duration<R, P> duration) noexcept { | |
t.point -= duration; | |
return t; | |
} | |
using namespace std::chrono_literals; | |
TEST_CASE("date_time to std::string") { | |
date_time t0{}; | |
const auto txt = t0.to_string(); | |
CAPTURE(txt); | |
std::tm time0 = t0; | |
std::tm time1{}; | |
std::stringstream sin{txt}; | |
sin >> std::get_time(&time1, "%Y-%m-%d %H:%M:%S"); | |
REQUIRE(time0.tm_hour == time1.tm_hour); | |
REQUIRE(time0.tm_min == time1.tm_min); | |
REQUIRE(time0.tm_sec == time1.tm_sec); | |
const auto tp = date_time::clock_type::from_time_t(std::mktime(&time1)); | |
REQUIRE(t0.point == tp); | |
} | |
TEST_CASE("date_time - sub") { | |
date_time t0{}; | |
date_time t1 = t0 - 1'000s; | |
REQUIRE(t0 > t1); | |
} | |
TEST_CASE("date_time - add") { | |
date_time t0{}; | |
SECTION("elapsed 1000 sec") { | |
date_time t1 = t0 + 1'000s; | |
REQUIRE(t0 < t1); | |
auto tm0 = static_cast<std::tm>(t0); | |
auto tm1 = static_cast<std::tm>(t1); | |
REQUIRE(tm0.tm_sec != tm1.tm_sec); | |
} | |
SECTION("elapsed 1000 min") { | |
date_time t1 = t0 + 1'000min; | |
REQUIRE(t0 < t1); | |
auto tm0 = static_cast<std::tm>(t0); | |
auto tm1 = static_cast<std::tm>(t1); | |
REQUIRE(tm0.tm_min != tm1.tm_min); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <chrono> | |
#include <ctime> | |
/// @see clock_gettime, CLOCKS_PER_SEC | |
class process_timer_t final { | |
clock_t start = clock(); | |
public: | |
/// @return elapsed seconds in float32 | |
float pick() const noexcept { | |
const auto now = clock(); | |
return static_cast<float>(now - start) / CLOCKS_PER_SEC; | |
} | |
float reset() noexcept { | |
const auto d = this->pick(); | |
start = clock(); | |
return d; | |
} | |
}; | |
/// @see Clock(named requirement) | |
template <typename Clock = std::chrono::system_clock> | |
class stop_watch_t final { | |
public: | |
using clock_type = Clock; | |
using time_point = typename clock_type::time_point; | |
using duration = typename clock_type::duration; | |
private: | |
time_point start = clock_type::now(); | |
public: | |
/// @return elapsed time from start point | |
duration pick() const noexcept { | |
return clock_type::now() - start; | |
}; | |
duration reset() noexcept { | |
const auto d = this->pick(); | |
start = clock_type::now(); | |
return d; | |
} | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment