diff --git a/libcron/CMakeLists.txt b/libcron/CMakeLists.txt index 3bc82cc..7623cf1 100644 --- a/libcron/CMakeLists.txt +++ b/libcron/CMakeLists.txt @@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 3.6) project(libcron) set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + +if( MSVC ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") +endif() include_directories(${CMAKE_CURRENT_LIST_DIR}/externals/date/include) @@ -16,7 +21,8 @@ add_library(${PROJECT_NAME} CronSchedule.h DateTime.h Task.cpp - CronClock.h) + CronClock.h + CronClock.cpp) set_target_properties(${PROJECT_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_LOCATION}" diff --git a/libcron/Cron.h b/libcron/Cron.h index 0c2e54b..e2a07b3 100644 --- a/libcron/Cron.h +++ b/libcron/Cron.h @@ -45,6 +45,8 @@ namespace libcron return clock; } + void get_time_until_expiry_for_tasks(std::vector>& status) const; + friend std::ostream& operator<<<>(std::ostream& stream, const Cron& c); private: @@ -78,7 +80,6 @@ namespace libcron bool res = cron.is_valid(); if (res) { - Task t{std::move(name), CronSchedule{cron}, std::move(work)}; if (t.calculate_next(clock.now())) { @@ -106,7 +107,7 @@ namespace libcron } template - size_t Cron::tick(system_clock::time_point now) + size_t Cron::tick(std::chrono::system_clock::time_point now) { size_t res = 0; @@ -160,6 +161,19 @@ namespace libcron return res; } + template + void Cron::get_time_until_expiry_for_tasks(std::vector>& status) const + { + auto now = clock.now(); + status.clear(); + + std::for_each(tasks.get_tasks().cbegin(), tasks.get_tasks().cend(), + [&status, &now](const Task& t) + { + status.emplace_back(t.get_name(), t.time_until_expiry(now)); + }); + } + template std::ostream& operator<<(std::ostream& stream, const Cron& c) { diff --git a/libcron/CronClock.cpp b/libcron/CronClock.cpp new file mode 100644 index 0000000..2933777 --- /dev/null +++ b/libcron/CronClock.cpp @@ -0,0 +1,39 @@ +#include "CronClock.h" + +#ifdef WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#include +#endif + +using namespace std::chrono; + +namespace libcron +{ + + std::chrono::seconds LocalClock::utc_offset(std::chrono::system_clock::time_point now) const + { +#ifdef WIN32 + (void)now; + + TIME_ZONE_INFORMATION tz_info{}; + seconds offset{ 0 }; + + auto res = GetTimeZoneInformation(&tz_info); + if (res != TIME_ZONE_ID_INVALID) + { + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx + // UTC = local time + bias => local_time = utc - bias, so UTC offset is -bias + offset = minutes{ -tz_info.Bias }; + } +#else + auto t = system_clock::to_time_t(now); + tm tm{}; + localtime_r(&t, &tm); + seconds offset{ tm.tm_gmtoff }; +#endif + return offset; + } +} \ No newline at end of file diff --git a/libcron/CronClock.h b/libcron/CronClock.h index f261e92..9d89b3b 100644 --- a/libcron/CronClock.h +++ b/libcron/CronClock.h @@ -2,9 +2,6 @@ #include -using namespace std::chrono; -using namespace date; - namespace libcron { class ICronClock @@ -25,6 +22,7 @@ namespace libcron std::chrono::seconds utc_offset(std::chrono::system_clock::time_point) const override { + using namespace std::chrono; return 0s; } }; @@ -35,20 +33,10 @@ namespace libcron public: std::chrono::system_clock::time_point now() const override { - auto now = system_clock::now(); + auto now = std::chrono::system_clock::now(); return now + utc_offset(now); } - std::chrono::seconds utc_offset(std::chrono::system_clock::time_point now) const 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}; - } + std::chrono::seconds utc_offset(std::chrono::system_clock::time_point now) const override; }; } \ No newline at end of file diff --git a/libcron/CronSchedule.cpp b/libcron/CronSchedule.cpp index 6e181c0..f2a5971 100644 --- a/libcron/CronSchedule.cpp +++ b/libcron/CronSchedule.cpp @@ -1,4 +1,5 @@ #include "CronSchedule.h" +#include using namespace std::chrono; using namespace date; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6ef7147..4dbdcda 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 3.6) project(cron_test) set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wpedantic -Wextra") + +if( MSVC ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") +endif() include_directories( ${CMAKE_CURRENT_LIST_DIR}/externals/Catch2/single_include/ diff --git a/test/CronTest.cpp b/test/CronTest.cpp index d354944..ec54f51 100644 --- a/test/CronTest.cpp +++ b/test/CronTest.cpp @@ -5,6 +5,7 @@ using namespace libcron; using namespace std::chrono; +using namespace date; std::string create_schedule_expiring_in(std::chrono::system_clock::time_point now, hours h, minutes m, seconds s) { @@ -221,7 +222,7 @@ class TestClock SCENARIO("Clock changes") { - GIVEN("A Cron instance with a single task expiring in 4h") + GIVEN("A Cron instance with a single task expiring every hour") { Cron c{}; auto& clock = c.get_clock(); @@ -239,11 +240,11 @@ SCENARIO("Clock changes") WHEN("Clock changes <3h forward") { - THEN("Task expires accordingly") - { - REQUIRE(c.tick() == 1); - clock.add(minutes{30}); // 00:30 - REQUIRE(c.tick() == 0); + THEN("Task expires accordingly") + { + REQUIRE(c.tick() == 1); + clock.add(minutes{ 30 }); // 00:30 + REQUIRE(c.tick() == 0); clock.add(minutes{30}); // 01:00 REQUIRE(c.tick() == 1); REQUIRE(c.tick() == 0); @@ -294,6 +295,5 @@ SCENARIO("Clock changes") REQUIRE(c.tick() == 1); } } - } } \ No newline at end of file