diff --git a/.idea/runConfigurations/All.xml b/.idea/runConfigurations/All.xml
new file mode 100644
index 0000000..19c75ae
--- /dev/null
+++ b/.idea/runConfigurations/All.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6b181a..d0bb848 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.9)
+cmake_minimum_required(VERSION 3.6)
add_subdirectory(libcron)
add_subdirectory(test)
diff --git a/libcron/CMakeLists.txt b/libcron/CMakeLists.txt
index 9fdd111..66ac343 100644
--- a/libcron/CMakeLists.txt
+++ b/libcron/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.9)
+cmake_minimum_required(VERSION 3.6)
project(libcron)
set(CMAKE_CXX_STANDARD 14)
diff --git a/libcron/CronSchedule.cpp b/libcron/CronSchedule.cpp
index a4ec362..a91f1b1 100644
--- a/libcron/CronSchedule.cpp
+++ b/libcron/CronSchedule.cpp
@@ -9,9 +9,12 @@ namespace libcron
std::chrono::system_clock::time_point
CronSchedule::calculate_from(const std::chrono::system_clock::time_point& from)
{
- auto curr = from;
+ //auto time_part = from - date::floor(from);
+ auto curr = from;// - time_part;
+ //auto dt = to_calendar_time(curr);
bool done = false;
+
while (!done)
{
year_month_day ymd = date::floor(curr);
@@ -19,23 +22,24 @@ namespace libcron
// Add months until one of the allowed days are found, or stay at the current one.
if (data.get_months().find(static_cast(unsigned(ymd.month()))) == data.get_months().end())
{
- curr += months{1};
- ymd = date::floor(curr);
+ auto next_month = ymd + months{1};
+ sys_days s = next_month.year() / next_month.month() / 1;
+ curr = s;
continue;
}
-
- // If all days are allowed, then the 'day of week' takes precedence, which also means that
- // day of week only is ignored when specific days of months are specified.
- if (data.get_day_of_month().size() != CronData::value_of(DayOfMonth::Last))
+ // If all days are allowed, then the 'day of week' takes precedence, which also means that
+ // day of week only is ignored when specific days of months are specified.
+ else if (data.get_day_of_month().size() != CronData::value_of(DayOfMonth::Last))
{
// Add days until one of the allowed days are found, or stay at the current one.
- if(data.get_day_of_month().find(static_cast(unsigned(ymd.day()))) ==
- data.get_day_of_month().end())
+ if (data.get_day_of_month().find(static_cast(unsigned(ymd.day()))) ==
+ data.get_day_of_month().end())
{
+ sys_days s = ymd;
+ curr = s;
curr += days{1};
- ymd = date::floor(curr);
continue;
- };
+ }
}
else
{
@@ -43,32 +47,29 @@ namespace libcron
year_month_weekday ymw = date::floor(curr);
if (data.get_day_of_week().find(static_cast(unsigned(ymw.weekday()))) ==
- data.get_day_of_week().end())
+ data.get_day_of_week().end())
{
+ sys_days s = ymd;
+ curr = s;
curr += days{1};
- ymw = date::floor(curr);
continue;
- };
+ }
}
- // Add hours until the current hour is one of the allowed
+ //curr += time_part;
auto date_time = to_calendar_time(curr);
if (data.get_hours().find(static_cast(date_time.hour)) == data.get_hours().end())
{
curr += hours{1};
- continue;
+ curr -= minutes{date_time.min};
+ curr -= seconds{date_time.sec};
}
else if (data.get_minutes().find(static_cast(date_time.min)) == data.get_minutes().end())
{
curr += minutes{1};
- continue;
+ curr -= seconds{date_time.sec};
}
else if (data.get_seconds().find(static_cast(date_time.sec)) == data.get_seconds().end())
- {
- curr += seconds{1};
- continue;
- }
- else if( curr <= from )
{
curr += seconds{1};
}
@@ -78,7 +79,6 @@ namespace libcron
}
}
-
return curr;
}
}
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index dda57bf..65387b1 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -13,6 +13,6 @@ include_directories(
add_executable(
${PROJECT_NAME}
test.cpp
-)
+ CronScheduleTest.cpp)
target_link_libraries(${PROJECT_NAME} libcron)
\ No newline at end of file
diff --git a/test/CronScheduleTest.cpp b/test/CronScheduleTest.cpp
new file mode 100644
index 0000000..091f6c8
--- /dev/null
+++ b/test/CronScheduleTest.cpp
@@ -0,0 +1,66 @@
+#include
+#include
+#include
+#include
+#include
+
+using namespace libcron;
+using namespace date;
+using namespace std::chrono;
+
+system_clock::time_point DT(year_month_day ymd, hours h = hours{0}, minutes m = minutes{0}, seconds s = seconds{0})
+{
+ sys_days t = ymd;
+ auto sum = t + h + m + s;
+ return sum;
+}
+
+bool test(const std::string& schedule, system_clock::time_point from, system_clock::time_point expected_next)
+{
+ auto c = CronData::create(schedule);
+ bool res = c.is_valid();
+ if (res)
+ {
+ CronSchedule sched(c);
+ auto run_time = sched.calculate_from(from);
+ res &= expected_next == run_time;
+
+ if (!res)
+ {
+ std::cout
+ << "From: " << from << "\n"
+ << "Expected: " << expected_next << "\n"
+ << "Calculated: " << run_time;
+
+ }
+ }
+
+ return res;
+}
+
+
+SCENARIO("Calculating next runtime")
+{
+ REQUIRE(test("0 0 * * * *", DT(2010_y / 1 / 1), DT(2010_y / 1 / 1, hours{0})));
+ REQUIRE(test("0 0 * * * *", DT(2010_y / 1 / 1, hours{0}, minutes{0}, seconds{1}), DT(2010_y / 1 / 1, hours{1})));
+ REQUIRE(test("0 0 * * * *", DT(2010_y / 1 / 1, hours{5}), DT(2010_y / 1 / 1, hours{5})));
+ REQUIRE(test("0 0 * * * *", DT(2010_y / 1 / 1, hours{5}, minutes{1}), DT(2010_y / 1 / 1, hours{6})));
+ REQUIRE(test("0 0 * * * *", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(2018_y / 1 / 1, hours{0})));
+ REQUIRE(test("0 0 10 * * *", DT(2017_y / 12 / 31, hours{9}, minutes{59}, seconds{58}), DT(2017_y / 12 / 31, hours{10})));
+ REQUIRE(test("0 0 10 * * *", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(2018_y / 1 / 1, hours{10})));
+ REQUIRE(test("0 0 10 * FEB *", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(2018_y / 2 / 1, hours{10})));
+ REQUIRE(test("0 0 10 25 FEB *", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(2018_y / 2 / 25, hours{10})));
+ REQUIRE(test("0 0 10 * FEB 1", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(year_month_day{2018_y/2/mon[1]}, hours{10})));
+ REQUIRE(test("0 0 10 * FEB 6", DT(2017_y / 12 / 31, hours{23}, minutes{59}, seconds{58}), DT(year_month_day{2018_y/2/sat[1]}, hours{10})));
+ REQUIRE(test("* * * 10-12 NOV *", DT(2018_y / 11 / 11, hours{10}, minutes{11}, seconds{12}), DT(year_month_day{2018_y/11/11}, hours{10}, minutes{11}, seconds{12})));
+}
+
+SCENARIO("Leap year")
+{
+ REQUIRE(test("0 0 * 29 FEB *", DT(2018_y / 1 / 1), DT(2020_y / 2 / 29)));
+}
+
+SCENARIO("Date that does not exist")
+{
+ //REQUIRE_FALSE(test("0 0 * 30 FEB *", DT(2018_y / 1 / 1), DT(2020_y / 2 / 29)));
+}
\ No newline at end of file
diff --git a/test/test.cpp b/test/test.cpp
index d9129e6..53cd06c 100644
--- a/test/test.cpp
+++ b/test/test.cpp
@@ -227,53 +227,3 @@ SCENARIO("Using step syntax")
}
}
-SCENARIO("Calculating next runtime")
-{
- GIVEN("An item schedule for the top of every hour")
- {
- auto c = CronData::create("0 0 * * * *");
- REQUIRE(c.is_valid());
- CronSchedule sched(c);
-
- WHEN("Start time is midnight")
- {
- sys_days midnight = 2010_y/1/1;
- std::chrono::system_clock::time_point run_time = sched.calculate_from(midnight);
-
- THEN("Next runtime is 01:00 of the same date")
- {
- auto t = CronSchedule::to_calendar_time(run_time);
- REQUIRE(t.year == 2010);
- REQUIRE(t.month == 1);
- REQUIRE(t.day == 1);
- REQUIRE(t.hour == 1);
- REQUIRE(t.min == 0);
- REQUIRE(t.sec == 0);
- }
- }
- AND_WHEN("Start time 05:00:00")
- {
- sys_days midnight = 2010_y/1/1;
- system_clock::time_point five = midnight;
- five += hours{5};
-
- auto t2 = CronSchedule::to_calendar_time(five);
-
- std::chrono::system_clock::time_point run_time = sched.calculate_from(five);
-
- THEN("Next runtime is 06:00 of the same date")
- {
- auto t = CronSchedule::to_calendar_time(run_time);
- REQUIRE(t.year == 2010);
- REQUIRE(t.month == 1);
- REQUIRE(t.day == 1);
- REQUIRE(t.hour == 6);
- REQUIRE(t.min == 0);
- REQUIRE(t.sec == 0);
- }
- }
-
-
-
- }
-}
\ No newline at end of file