Added LocalClock.

This commit is contained in:
Per Malmberg 2018-03-11 23:38:12 +01:00
parent 582d0c4369
commit 9f7c5dc2fa
5 changed files with 44 additions and 26 deletions

View File

@ -1,9 +1,11 @@
# libcron # libcron
A C++ scheduling library using cron formatting. A C++ scheduling library using cron formatting.
# Time zones # Local time vs UTC
This library uses `std::chrono::system_clock::timepoint` as its time unit, thus all calculations are in UTC. This library uses `std::chrono::system_clock::timepoint` as its time unit. While that is UTC by default, the Cron-class
uses a `LocalClock` by default which offsets `system_clock::now()` by the current UTC-offset. If you wish to work in
UTC, then construct the Cron instance, passing it a `libcron::UTCClock`.
# Supported formatting # Supported formatting
@ -67,5 +69,5 @@ the '?'-character unless one field already is something other than '*'.
# Third party libraries # Third party libraries
Howard Hinnant's [date.h](https://github.com/HowardHinnant/date/) Howard Hinnant's [date libraries](https://github.com/HowardHinnant/date/)

View File

@ -13,7 +13,7 @@ namespace libcron
{ {
public: public:
explicit Cron(std::unique_ptr<ICronClock> clock = std::make_unique<UTCClock>()) explicit Cron(std::unique_ptr<ICronClock> clock = std::make_unique<LocalClock>())
: clock(std::move(clock)) : clock(std::move(clock))
{ {
} }

View File

@ -2,12 +2,16 @@
#include <chrono> #include <chrono>
using namespace std::chrono;
using namespace date;
namespace libcron namespace libcron
{ {
class ICronClock class ICronClock
{ {
public: public:
virtual std::chrono::system_clock::time_point now() = 0; virtual std::chrono::system_clock::time_point now() = 0;
virtual std::chrono::seconds utc_offset(std::chrono::system_clock::time_point now) = 0;
}; };
class UTCClock class UTCClock
@ -18,5 +22,33 @@ namespace libcron
{ {
return std::chrono::system_clock::now(); return std::chrono::system_clock::now();
} }
std::chrono::seconds utc_offset(std::chrono::system_clock::time_point) override
{
return 0s;
}
};
class LocalClock
: public ICronClock
{
public:
std::chrono::system_clock::time_point now() override
{
auto now = system_clock::now();
return now + utc_offset(now);
}
std::chrono::seconds utc_offset(std::chrono::system_clock::time_point now) override
{
auto t = system_clock::to_time_t(now);
tm tm{};
#ifdef __WIN32
localtime_s(&tm, &t);
#else
localtime_r(&t, &tm);
#endif
return seconds{tm.tm_gmtoff};
}
}; };
} }

View File

@ -16,7 +16,7 @@ system_clock::time_point DT(year_month_day ymd, hours h = hours{0}, minutes m =
} }
bool test(const std::string& schedule, system_clock::time_point from, bool test(const std::string& schedule, system_clock::time_point from,
std::vector<system_clock::time_point> expected_next) const std::vector<system_clock::time_point>& expected_next)
{ {
auto c = CronData::create(schedule); auto c = CronData::create(schedule);
bool res = c.is_valid(); bool res = c.is_valid();
@ -209,22 +209,6 @@ SCENARIO("Examples from README.md")
})); }));
} }
//SCENARIO("Daylight Savings Time")
//{
// // In sweden when local standard time is about to reach
// //Sunday, 25 March 2018, 02:00:00 clocks are turned forward 1 hour to
// //Sunday, 25 March 2018, 03:00:00 local daylight time instead.
//
// REQUIRE(test("0 0 * * * ?", DT(2018_y / 3 / 25, hours{0}),
// {
// DT(2018_y / 3 / 25, hours{0}),
// DT(2018_y / 3 / 25, hours{1}),
// // This hour disappear! DT(2018_y / 3 / 25, hours{2}),
// DT(2018_y / 3 / 25, hours{3}),
// DT(2018_y / 3 / 25, hours{4})
// }));
//}
SCENARIO("Unable to calculate time point") SCENARIO("Unable to calculate time point")
{ {
// TODO: Find a schedule that is unsolvable. // TODO: Find a schedule that is unsolvable.

View File

@ -6,9 +6,9 @@
using namespace libcron; using namespace libcron;
using namespace std::chrono; using namespace std::chrono;
std::string create_schedule_expiring_in(hours h, minutes m, seconds s) std::string create_schedule_expiring_in(std::shared_ptr<ICronClock> clock, hours h, minutes m, seconds s)
{ {
auto now = system_clock::now() + h + m + s; auto now = clock->now() + h + m + s;
auto dt = CronSchedule::to_calendar_time(now); auto dt = CronSchedule::to_calendar_time(now);
std::string res{}; std::string res{};
@ -66,7 +66,7 @@ SCENARIO("Adding a task that expires in the future")
auto expired = false; auto expired = false;
Cron c; Cron c;
REQUIRE(c.add_schedule("A task", create_schedule_expiring_in(hours{0}, minutes{0}, seconds{3}), REQUIRE(c.add_schedule("A task", create_schedule_expiring_in(c.get_clock(), hours{0}, minutes{0}, seconds{3}),
[&expired]() [&expired]()
{ {
expired = true; expired = true;
@ -107,14 +107,14 @@ SCENARIO("Task priority")
Cron c; Cron c;
REQUIRE(c.add_schedule("Five", create_schedule_expiring_in(hours{0}, minutes{0}, seconds{5}), REQUIRE(c.add_schedule("Five", create_schedule_expiring_in(c.get_clock(), hours{0}, minutes{0}, seconds{5}),
[&_5_second_expired]() [&_5_second_expired]()
{ {
_5_second_expired++; _5_second_expired++;
}) })
); );
REQUIRE(c.add_schedule("Three", create_schedule_expiring_in(hours{0}, minutes{0}, seconds{3}), REQUIRE(c.add_schedule("Three", create_schedule_expiring_in(c.get_clock(), hours{0}, minutes{0}, seconds{3}),
[&_3_second_expired]() [&_3_second_expired]()
{ {
_3_second_expired++; _3_second_expired++;