renamed 32bit durations, added ESP32 implementations in separate .cpp file
This commit is contained in:
@ -4,6 +4,7 @@ set(headers
|
||||
|
||||
set(sources
|
||||
src/espchrono.cpp
|
||||
src/espchrono_espimpl.cpp
|
||||
)
|
||||
|
||||
idf_component_register(INCLUDE_DIRS src SRCS ${headers} ${sources} REQUIRES freertos esp_system cpputils date espcpputils)
|
||||
|
@ -66,6 +66,11 @@ bool daylightSavingTime(local_clock::time_point _timeStamp)
|
||||
return (_tempDateTime.date.day() < 8_d && _tempDateTime.dayOfWeek == 1 && _tempDateTime.hour < 2);
|
||||
} // end else
|
||||
}
|
||||
} // namespace
|
||||
|
||||
auto local_clock::now() noexcept -> time_point
|
||||
{
|
||||
return utcToLocal(utc_clock::now());
|
||||
}
|
||||
|
||||
local_clock::time_point utcToLocal(utc_clock::time_point utc, time_zone timezone)
|
||||
@ -97,8 +102,13 @@ utc_clock::time_point localToUtc(local_clock::time_point local)
|
||||
return utc;
|
||||
}
|
||||
|
||||
local_clock::time_point utcToLocal(utc_clock::time_point ts)
|
||||
{
|
||||
return utcToLocal(ts, local_clock::timezone());
|
||||
}
|
||||
|
||||
namespace {
|
||||
DateTime toDateTime(seconds ts)
|
||||
DateTime toDateTime(seconds32 ts)
|
||||
{
|
||||
auto _time = ts.count();
|
||||
|
||||
@ -188,7 +198,7 @@ std::optional<DateTime> parseDateTime(std::string_view str)
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<seconds> parseDaypoint(std::string_view str)
|
||||
std::optional<seconds32> parseDaypoint(std::string_view str)
|
||||
{
|
||||
int8_t hour, minute, second{};
|
||||
|
||||
@ -199,7 +209,7 @@ std::optional<seconds> parseDaypoint(std::string_view str)
|
||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59)
|
||||
return std::nullopt;
|
||||
|
||||
return hours{hour} + minutes{minute} + seconds{second};
|
||||
return hours32{hour} + minutes32{minute} + seconds32{second};
|
||||
}
|
||||
|
||||
std::string toString(const DateTime &dateTime)
|
||||
@ -217,7 +227,7 @@ std::string toString(const LocalDateTime &dateTime)
|
||||
{
|
||||
char buf[34];
|
||||
|
||||
date::hh_mm_ss helper{dateTime.timezone.offset + hours{dateTime.dst ? 1 : 0}};
|
||||
date::hh_mm_ss helper{dateTime.timezone.offset + hours32{dateTime.dst ? 1 : 0}};
|
||||
|
||||
std::sprintf(buf, "%04i-%02u-%02uT%02hhu:%02hhu:%02hhu %s%02hhu:%02hhu",
|
||||
int{dateTime.date.year()}, unsigned{dateTime.date.month()}, unsigned{dateTime.date.day()},
|
||||
@ -227,7 +237,7 @@ std::string toString(const LocalDateTime &dateTime)
|
||||
return std::string{buf};
|
||||
}
|
||||
|
||||
std::string toDaypointString(seconds seconds)
|
||||
std::string toDaypointString(seconds32 seconds)
|
||||
{
|
||||
date::hh_mm_ss helper(seconds);
|
||||
char buf[10];
|
||||
@ -235,15 +245,15 @@ std::string toDaypointString(seconds seconds)
|
||||
return std::string{buf};
|
||||
}
|
||||
|
||||
milliseconds ago(millis_clock::time_point a)
|
||||
std::chrono::milliseconds ago(millis_clock::time_point a)
|
||||
{
|
||||
return millis_clock::now() - a;
|
||||
}
|
||||
|
||||
std::string toString(milliseconds val) { return std::to_string(val.count()) + "ms"; }
|
||||
std::string toString(seconds val) { return std::to_string(val.count()) + "s"; }
|
||||
std::string toString(minutes val) { return std::to_string(val.count()) + "min"; }
|
||||
std::string toString(hours val) { return std::to_string(val.count()) + "h"; }
|
||||
std::string toString(milliseconds32 val) { return std::to_string(val.count()) + "ms"; }
|
||||
std::string toString(seconds32 val) { return std::to_string(val.count()) + "s"; }
|
||||
std::string toString(minutes32 val) { return std::to_string(val.count()) + "min"; }
|
||||
std::string toString(hours32 val) { return std::to_string(val.count()) + "h"; }
|
||||
|
||||
IMPLEMENT_TYPESAFE_ENUM(DayLightSavingMode, : uint8_t, DayLightSavingModeValues)
|
||||
|
||||
|
@ -17,14 +17,14 @@
|
||||
|
||||
namespace espchrono {
|
||||
|
||||
using milliseconds = std::chrono::duration<long, std::milli>;
|
||||
using seconds = std::chrono::duration<long>;
|
||||
using minutes = std::chrono::duration<long, std::ratio<60>>;
|
||||
using hours = std::chrono::duration<long, std::ratio<3600>>;
|
||||
using milliseconds32 = std::chrono::duration<int32_t, std::milli>;
|
||||
using seconds32 = std::chrono::duration<int32_t>;
|
||||
using minutes32 = std::chrono::duration<int32_t, std::ratio<60>>;
|
||||
using hours32 = std::chrono::duration<int32_t, std::ratio<3600>>;
|
||||
|
||||
struct utc_clock
|
||||
{
|
||||
typedef seconds duration;
|
||||
typedef seconds32 duration;
|
||||
typedef duration::rep rep;
|
||||
typedef duration::period period;
|
||||
typedef std::chrono::time_point<utc_clock, duration> time_point;
|
||||
@ -45,7 +45,7 @@ DECLARE_TYPESAFE_ENUM(DayLightSavingMode, : uint8_t, DayLightSavingModeValues)
|
||||
|
||||
struct time_zone
|
||||
{
|
||||
minutes offset{};
|
||||
minutes32 offset{};
|
||||
DayLightSavingMode dayLightSavingMode{};
|
||||
|
||||
bool operator== (const time_zone &other) const
|
||||
@ -100,7 +100,7 @@ public:
|
||||
|
||||
struct local_clock
|
||||
{
|
||||
typedef seconds duration;
|
||||
typedef seconds32 duration;
|
||||
typedef duration::rep rep;
|
||||
typedef duration::period period;
|
||||
typedef local_time_point<local_clock, duration> time_point;
|
||||
@ -111,6 +111,8 @@ struct local_clock
|
||||
static constexpr bool is_steady = false;
|
||||
|
||||
static time_point now() noexcept;
|
||||
|
||||
static time_zone timezone() noexcept;
|
||||
};
|
||||
|
||||
struct millis_clock
|
||||
@ -162,6 +164,8 @@ struct LocalDateTime : public DateTime
|
||||
local_clock::time_point utcToLocal(utc_clock::time_point timeStamp, time_zone timezone);
|
||||
utc_clock::time_point localToUtc(local_clock::time_point local);
|
||||
|
||||
local_clock::time_point utcToLocal(utc_clock::time_point ts);
|
||||
|
||||
DateTime toDateTime(utc_clock::time_point ts);
|
||||
LocalDateTime toDateTime(local_clock::time_point ts);
|
||||
|
||||
@ -169,18 +173,18 @@ LocalDateTime toDateTime(local_clock::time_point ts);
|
||||
std::optional<DateTime> parseDateTime(std::string_view str);
|
||||
|
||||
//! Returns null if string cannot be parsed
|
||||
std::optional<seconds> parseDaypoint(std::string_view str);
|
||||
std::optional<seconds32> parseDaypoint(std::string_view str);
|
||||
|
||||
std::string toString(const DateTime &dateTime);
|
||||
|
||||
std::string toString(const LocalDateTime &dateTime);
|
||||
|
||||
std::string toDaypointString(seconds seconds);
|
||||
std::string toDaypointString(seconds32 seconds);
|
||||
|
||||
milliseconds ago(millis_clock::time_point a);
|
||||
std::chrono::milliseconds ago(millis_clock::time_point a);
|
||||
|
||||
std::string toString(milliseconds val);
|
||||
std::string toString(seconds val);
|
||||
std::string toString(minutes val);
|
||||
std::string toString(hours val);
|
||||
std::string toString(milliseconds32 val);
|
||||
std::string toString(seconds32 val);
|
||||
std::string toString(minutes32 val);
|
||||
std::string toString(hours32 val);
|
||||
} // namespace espchrono
|
||||
|
27
src/espchrono_espimpl.cpp
Normal file
27
src/espchrono_espimpl.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// local includes
|
||||
#include "espchrono.h"
|
||||
|
||||
// system includes
|
||||
#include <time.h>
|
||||
|
||||
// esp-idf inlcludes
|
||||
#include <esp_timer.h>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
// actual implementations used on the ESP32
|
||||
|
||||
namespace espchrono {
|
||||
auto utc_clock::now() noexcept -> time_point
|
||||
{
|
||||
timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
seconds32 seconds{tv.tv_sec};
|
||||
return time_point{seconds};
|
||||
}
|
||||
|
||||
auto millis_clock::now() noexcept -> time_point
|
||||
{
|
||||
return time_point{std::chrono::floor<duration>(std::chrono::microseconds{esp_timer_get_time()})};
|
||||
}
|
||||
} // namespace espchrono
|
@ -5,7 +5,8 @@ using namespace date;
|
||||
|
||||
const espchrono::time_zone testTimeZone{.offset=60min, .dayLightSavingMode=espchrono::DayLightSavingMode::EuropeanSummerTime};
|
||||
|
||||
espchrono::millis_clock::time_point wallClock{};
|
||||
espchrono::millis_clock::time_point mockedMillisClock{};
|
||||
espchrono::utc_clock::time_point mockedUtcClock{};
|
||||
|
||||
namespace QTest {
|
||||
template<>
|
||||
@ -33,13 +34,13 @@ char *toString(const espchrono::local_clock::time_point &ts)
|
||||
}
|
||||
|
||||
template<>
|
||||
char *toString(const espchrono::seconds &val)
|
||||
char *toString(const espchrono::seconds32 &val)
|
||||
{
|
||||
return ::QTest::toString(espchrono::toDaypointString(val));
|
||||
}
|
||||
|
||||
template<>
|
||||
char *toString(const std::optional<espchrono::seconds> &val)
|
||||
char *toString(const std::optional<espchrono::seconds32> &val)
|
||||
{
|
||||
return val ? ::QTest::toString(*val) : ::QTest::toString("(invalid)");
|
||||
}
|
||||
@ -48,5 +49,13 @@ char *toString(const std::optional<espchrono::seconds> &val)
|
||||
// stub implementation to make unit tests happy
|
||||
auto espchrono::millis_clock::now() noexcept -> time_point
|
||||
{
|
||||
return wallClock;
|
||||
return mockedMillisClock;
|
||||
}
|
||||
auto espchrono::utc_clock::now() noexcept -> time_point
|
||||
{
|
||||
return mockedUtcClock;
|
||||
}
|
||||
auto espchrono::local_clock::timezone() noexcept -> time_zone
|
||||
{
|
||||
return testTimeZone;
|
||||
}
|
||||
|
@ -11,23 +11,28 @@
|
||||
#include "espchrono.h"
|
||||
#include "cpputilstestutils.h"
|
||||
|
||||
Q_DECLARE_METATYPE(espchrono::milliseconds)
|
||||
Q_DECLARE_METATYPE(espchrono::seconds)
|
||||
Q_DECLARE_METATYPE(espchrono::minutes)
|
||||
Q_DECLARE_METATYPE(espchrono::hours)
|
||||
Q_DECLARE_METATYPE(std::chrono::milliseconds)
|
||||
Q_DECLARE_METATYPE(std::chrono::seconds)
|
||||
Q_DECLARE_METATYPE(std::chrono::minutes)
|
||||
Q_DECLARE_METATYPE(std::chrono::hours)
|
||||
Q_DECLARE_METATYPE(espchrono::milliseconds32)
|
||||
Q_DECLARE_METATYPE(espchrono::seconds32)
|
||||
Q_DECLARE_METATYPE(espchrono::minutes32)
|
||||
Q_DECLARE_METATYPE(espchrono::hours32)
|
||||
Q_DECLARE_METATYPE(espchrono::utc_clock::time_point)
|
||||
Q_DECLARE_METATYPE(espchrono::local_clock::time_point)
|
||||
Q_DECLARE_METATYPE(espchrono::DateTime)
|
||||
Q_DECLARE_METATYPE(espchrono::LocalDateTime)
|
||||
Q_DECLARE_METATYPE(std::optional<espchrono::seconds>)
|
||||
Q_DECLARE_METATYPE(std::optional<espchrono::seconds32>)
|
||||
|
||||
extern const espchrono::time_zone testTimeZone;
|
||||
|
||||
extern espchrono::millis_clock::time_point wallClock;
|
||||
extern espchrono::millis_clock::time_point mockedMillisClock;
|
||||
extern espchrono::utc_clock::time_point mockedUtcClock;
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
espchrono::local_clock::time_point makeLocal(T day, espchrono::minutes time)
|
||||
espchrono::local_clock::time_point makeLocal(T day, espchrono::minutes32 time)
|
||||
{
|
||||
espchrono::local_clock::time_point localTime{date::sys_days{day}.time_since_epoch(), testTimeZone, false};
|
||||
localTime += time;
|
||||
@ -35,7 +40,7 @@ espchrono::local_clock::time_point makeLocal(T day, espchrono::minutes time)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
espchrono::utc_clock::time_point makeUtcFromLocal(T day, espchrono::minutes time)
|
||||
espchrono::utc_clock::time_point makeUtcFromLocal(T day, espchrono::minutes32 time)
|
||||
{
|
||||
const auto localTime = makeLocal(day, time);
|
||||
return espchrono::localToUtc(localTime);
|
||||
@ -56,8 +61,8 @@ template<>
|
||||
char *toString(const espchrono::local_clock::time_point &ts);
|
||||
|
||||
template<>
|
||||
char *toString(const espchrono::seconds &val);
|
||||
char *toString(const espchrono::seconds32 &val);
|
||||
|
||||
template<>
|
||||
char *toString(const std::optional<espchrono::seconds> &val);
|
||||
char *toString(const std::optional<espchrono::seconds32> &val);
|
||||
} // namespace QTest
|
||||
|
@ -139,20 +139,20 @@ private slots:
|
||||
QTest::addColumn<espchrono::utc_clock::time_point>("time_point");
|
||||
QTest::addColumn<espchrono::DateTime>("expected");
|
||||
|
||||
QTest::addRow("random") << espchrono::utc_clock::time_point{espchrono::seconds{123456}} << espchrono::DateTime{
|
||||
QTest::addRow("random") << espchrono::utc_clock::time_point{123456s} << espchrono::DateTime{
|
||||
2_d/January/1970,
|
||||
.hour=10, .minute=17, .second=36,
|
||||
.dayOfWeek=espchrono::DateTime::DayOfWeek::Friday
|
||||
};
|
||||
|
||||
QTest::addRow("leap_year") << espchrono::utc_clock::time_point{espchrono::seconds{1582934400}}
|
||||
QTest::addRow("leap_year") << espchrono::utc_clock::time_point{1582934400s}
|
||||
<< espchrono::DateTime{
|
||||
29_d/February/2020,
|
||||
.hour=0, .minute=0, .second=0,
|
||||
.dayOfWeek=espchrono::DateTime::DayOfWeek::Saturday
|
||||
};
|
||||
|
||||
QTest::addRow("normal_year") << espchrono::utc_clock::time_point{espchrono::seconds{1614556800}}
|
||||
QTest::addRow("normal_year") << espchrono::utc_clock::time_point{1614556800s}
|
||||
<< espchrono::DateTime{
|
||||
1_d/March/2021,
|
||||
.hour=0, .minute=0, .second=0,
|
||||
@ -173,7 +173,7 @@ private slots:
|
||||
QTest::addColumn<espchrono::local_clock::time_point>("time_point");
|
||||
QTest::addColumn<espchrono::LocalDateTime>("expected");
|
||||
|
||||
QTest::addRow("no_dst") << espchrono::local_clock::time_point(espchrono::seconds{123456}, testTimeZone, false)
|
||||
QTest::addRow("no_dst") << espchrono::local_clock::time_point(123456s, testTimeZone, false)
|
||||
<< espchrono::LocalDateTime{
|
||||
espchrono::DateTime{
|
||||
2_d/January/1970,
|
||||
@ -183,7 +183,7 @@ private slots:
|
||||
.timezone = testTimeZone,
|
||||
.dst = false
|
||||
};
|
||||
QTest::addRow("with_dst") << espchrono::local_clock::time_point(espchrono::seconds{123456}, testTimeZone, true)
|
||||
QTest::addRow("with_dst") << espchrono::local_clock::time_point(123456s, testTimeZone, true)
|
||||
<< espchrono::LocalDateTime{
|
||||
espchrono::DateTime{
|
||||
2_d/January/1970,
|
||||
@ -205,22 +205,22 @@ private slots:
|
||||
|
||||
void test_toDaypointString_data()
|
||||
{
|
||||
QTest::addColumn<espchrono::seconds>("input");
|
||||
QTest::addColumn<espchrono::seconds32>("input");
|
||||
QTest::addColumn<std::string>("expected");
|
||||
|
||||
QTest::addRow("00:00:00") << espchrono::seconds{} << "00:00:00"s;
|
||||
QTest::addRow("05:00:00") << espchrono::seconds{5h} << "05:00:00"s;
|
||||
QTest::addRow("05:04:00") << espchrono::seconds{5h+4min} << "05:04:00"s;
|
||||
QTest::addRow("05:04:03") << espchrono::seconds{5h+4min+3s} << "05:04:03"s;
|
||||
QTest::addRow("05:00:03") << espchrono::seconds{5h+3s} << "05:00:03"s;
|
||||
QTest::addRow("23:59:59") << espchrono::seconds{23h+59min+59s} << "23:59:59"s;
|
||||
QTest::addRow("-23:59:59") << espchrono::seconds{-23h-59min-59s} << "-23:59:59"s;
|
||||
QTest::addRow("-00:59:59") << espchrono::seconds{-59min-59s} << "-00:59:59"s;
|
||||
QTest::addRow("00:00:00") << espchrono::seconds32{} << "00:00:00"s;
|
||||
QTest::addRow("05:00:00") << espchrono::seconds32{5h} << "05:00:00"s;
|
||||
QTest::addRow("05:04:00") << espchrono::seconds32{5h+4min} << "05:04:00"s;
|
||||
QTest::addRow("05:04:03") << espchrono::seconds32{5h+4min+3s} << "05:04:03"s;
|
||||
QTest::addRow("05:00:03") << espchrono::seconds32{5h+3s} << "05:00:03"s;
|
||||
QTest::addRow("23:59:59") << espchrono::seconds32{23h+59min+59s} << "23:59:59"s;
|
||||
QTest::addRow("-23:59:59") << espchrono::seconds32{-23h-59min-59s} << "-23:59:59"s;
|
||||
QTest::addRow("-00:59:59") << espchrono::seconds32{-59min-59s} << "-00:59:59"s;
|
||||
}
|
||||
|
||||
void test_toDaypointString()
|
||||
{
|
||||
QFETCH(espchrono::seconds, input);
|
||||
QFETCH(espchrono::seconds32, input);
|
||||
QFETCH(std::string, expected);
|
||||
FIXEDCOMPARE(espchrono::toDaypointString(input), expected);
|
||||
}
|
||||
@ -228,22 +228,22 @@ private slots:
|
||||
void test_parseDaypoint_data()
|
||||
{
|
||||
QTest::addColumn<std::string>("input");
|
||||
QTest::addColumn<std::optional<espchrono::seconds>>("expected");
|
||||
QTest::addColumn<std::optional<espchrono::seconds32>>("expected");
|
||||
|
||||
QTest::addRow("bullshit") << "bullshit"s << std::optional<espchrono::seconds>{};
|
||||
QTest::addRow("missing_minute") << "00:"s << std::optional<espchrono::seconds>{};
|
||||
QTest::addRow("zero") << "00:00"s << std::optional<espchrono::seconds>{0s};
|
||||
QTest::addRow("zero3") << "00:00:00"s << std::optional<espchrono::seconds>{0s};
|
||||
QTest::addRow("random") << "12:34:56"s << std::optional<espchrono::seconds>{12h+34min+56s};
|
||||
QTest::addRow("random2") << "12:34"s << std::optional<espchrono::seconds>{12h+34min};
|
||||
// QTest::addRow("negative") << "-12:34:56"s << std::optional<espchrono::seconds>{-12h-34min-56s};
|
||||
// QTest::addRow("negative_leading_zero") << "-00:34:56"s << std::optional<espchrono::seconds>{-34min-56s};
|
||||
QTest::addRow("bullshit") << "bullshit"s << std::optional<espchrono::seconds32>{};
|
||||
QTest::addRow("missing_minute") << "00:"s << std::optional<espchrono::seconds32>{};
|
||||
QTest::addRow("zero") << "00:00"s << std::optional<espchrono::seconds32>{0s};
|
||||
QTest::addRow("zero3") << "00:00:00"s << std::optional<espchrono::seconds32>{0s};
|
||||
QTest::addRow("random") << "12:34:56"s << std::optional<espchrono::seconds32>{12h+34min+56s};
|
||||
QTest::addRow("random2") << "12:34"s << std::optional<espchrono::seconds32>{12h+34min};
|
||||
// QTest::addRow("negative") << "-12:34:56"s << std::optional<espchrono::seconds32>{-12h-34min-56s};
|
||||
// QTest::addRow("negative_leading_zero") << "-00:34:56"s << std::optional<espchrono::seconds32>{-34min-56s};
|
||||
}
|
||||
|
||||
void test_parseDaypoint()
|
||||
{
|
||||
QFETCH(std::string, input);
|
||||
QFETCH(std::optional<espchrono::seconds>, expected);
|
||||
QFETCH(std::optional<espchrono::seconds32>, expected);
|
||||
|
||||
FIXEDCOMPARE(espchrono::parseDaypoint(input), expected);
|
||||
}
|
||||
@ -286,7 +286,7 @@ private slots:
|
||||
void test_compareLocalTimepoints()
|
||||
{
|
||||
espchrono::local_clock::time_point a {
|
||||
espchrono::seconds{10},
|
||||
10s,
|
||||
espchrono::time_zone{
|
||||
.offset = 1h,
|
||||
.dayLightSavingMode = espchrono::DayLightSavingMode::EuropeanSummerTime
|
||||
@ -294,7 +294,7 @@ private slots:
|
||||
false
|
||||
};
|
||||
espchrono::local_clock::time_point b {
|
||||
espchrono::seconds{10},
|
||||
10s,
|
||||
espchrono::time_zone{
|
||||
.offset = 1h,
|
||||
.dayLightSavingMode = espchrono::DayLightSavingMode::EuropeanSummerTime
|
||||
|
Reference in New Issue
Block a user