renamed 32bit durations, added ESP32 implementations in separate .cpp file

This commit is contained in:
2021-02-24 17:11:42 +01:00
parent 5ec358b30e
commit d3547a3323
7 changed files with 121 additions and 65 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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
View 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

View File

@ -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;
}

View File

@ -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

View File

@ -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