Skip to content

Instantly share code, notes, and snippets.

@luncliff
Last active March 16, 2021 09:37
Show Gist options
  • Save luncliff/2f7458ee109ca19e694f2626245b674a to your computer and use it in GitHub Desktop.
Save luncliff/2f7458ee109ca19e694f2626245b674a to your computer and use it in GitHub Desktop.
C++ Timer with Standard Library
#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);
}
}
#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