4 Commits

Author SHA1 Message Date
Philemon Benner
8c144b0ddb fixed convenience scheduling (#47) 2025-10-10 16:14:27 +02:00
Dr. Nicholas J. Kinar
de143e8b8e Added code to ensure that code snippets in Readme compile. (#46)
* Update README.md

Added missing stream insertion operator to example.   Also, header files for chrono and thread as well as a missing namespace for literals added.

---------

Co-authored-by: Per Malmberg <PerMalmberg@users.noreply.github.com>
2025-06-01 10:51:30 +02:00
Dr. Nicholas J. Kinar
aa3d4368d5 Update CronScheduleTest.cpp (#38)
* Update CronScheduleTest.cpp

* Update CronScheduleTest.cpp

Edited code that was causing test to fail.

---------

Co-authored-by: Per Malmberg <PerMalmberg@users.noreply.github.com>
2024-08-02 18:49:19 +02:00
Dr. Nicholas J. Kinar
7c7d290792 Update README.md (#37)
In the Examples section, added an expression for every minute and a note providing a comment on the expression formatting.
2024-07-31 10:57:29 +02:00
4 changed files with 44 additions and 15 deletions

View File

@@ -6,10 +6,16 @@ A C++ scheduling library using cron formatting.
Libcron offers an easy to use API to add callbacks with corresponding cron-formatted strings: Libcron offers an easy to use API to add callbacks with corresponding cron-formatted strings:
``` ```
#include <libcron/Cron.h>
#include <libcron/CronData.h>
#include <chrono>
#include <thread>
using namespace std::chrono_literals;
libcron::Cron cron; libcron::Cron cron;
cron.add_schedule("Hello from Cron", "* * * * * ?", [=](auto&) { cron.add_schedule("Hello from Cron", "* * * * * ?", [=](auto&) {
std::cout << "Hello from libcron!" std::endl; std::cout << "Hello from libcron!" << std::endl;
}); });
``` ```
@@ -19,7 +25,7 @@ To trigger the execution of callbacks, one must call `libcron::Cron::tick` at le
while(true) while(true)
{ {
cron.tick(); cron.tick();
std::this_thread::sleep_for(500mS); std::this_thread::sleep_for(500ms);
} }
``` ```
@@ -188,23 +194,28 @@ the '?'-character to ensure that it is not possible to specify a statement which
|Expression | Meaning |Expression | Meaning
| --- | --- | | --- | --- |
| * * * * * ? | Every second | * * * * * ? | Every second
| 0 * * * * ? | Every minute
| 0 0 12 * * MON-FRI | Every Weekday at noon | 0 0 12 * * MON-FRI | Every Weekday at noon
| 0 0 12 1/2 * ? | Every 2 days, starting on the 1st at noon | 0 0 12 1/2 * ? | Every 2 days, starting on the 1st at noon
| 0 0 */12 ? * * | Every twelve hours | 0 0 */12 ? * * | Every twelve hours
| @hourly | Every hour | @hourly | Every hour
Note that the expression formatting has a part for seconds and the day of week.
For the day of week part, a question mark ? is utilized. This format
may not be parsed by all online crontab calculators or expression generators.
## Convenience scheduling ## Convenience scheduling
These special time specification tokens which replace the 5 initial time and date fields, and are prefixed with the '@' character, are supported: These special time specification tokens which replace the 5 initial time and date fields, and are prefixed with the '@' character, are supported:
|Token|Meaning |Token|Meaning
| --- | --- | | --- | --- |
| @yearly | Run once a year, ie. "0 0 1 1 *". | @yearly | Run once a year, ie. "0 0 0 1 1 *".
| @annually | Run once a year, ie. "0 0 1 1 *". | @annually | Run once a year, ie. "0 0 0 1 1 *"".
| @monthly | Run once a month, ie. "0 0 1 * *". | @monthly | Run once a month, ie. "0 0 0 1 * *".
| @weekly | Run once a week, ie. "0 0 * * 0". | @weekly | Run once a week, ie. "0 0 0 * * 0".
| @daily | Run once a day, ie. "0 0 * * *". | @daily | Run once a day, ie. "0 0 0 * * ?".
| @hourly | Run once an hour, ie. "0 * * * *". | @hourly | Run once an hour, ie. "0 0 * * * ?".
# Randomization # Randomization

View File

@@ -39,12 +39,12 @@ namespace libcron
{ {
// First, check for "convenience scheduling" using @yearly, @annually, // First, check for "convenience scheduling" using @yearly, @annually,
// @monthly, @weekly, @daily or @hourly. // @monthly, @weekly, @daily or @hourly.
std::string tmp = std::regex_replace(cron_expression, std::regex("@yearly"), "0 0 1 1 *"); std::string tmp = std::regex_replace(cron_expression, std::regex("@yearly"), "0 0 0 1 1 *");
tmp = std::regex_replace(tmp, std::regex("@annually"), "0 0 1 1 *"); tmp = std::regex_replace(tmp, std::regex("@annually"), "0 0 0 1 1 *");
tmp = std::regex_replace(tmp, std::regex("@monthly"), "0 0 1 * *"); tmp = std::regex_replace(tmp, std::regex("@monthly"), "0 0 0 1 * *");
tmp = std::regex_replace(tmp, std::regex("@weekly"), "0 0 * * 0"); tmp = std::regex_replace(tmp, std::regex("@weekly"), "0 0 0 * * 0");
tmp = std::regex_replace(tmp, std::regex("@daily"), "0 0 * * *"); tmp = std::regex_replace(tmp, std::regex("@daily"), "0 0 0 * * ?");
const std::string expression = std::regex_replace(tmp, std::regex("@hourly"), "0 * * * *"); const std::string expression = std::regex_replace(tmp, std::regex("@hourly"), "0 0 * * * ?");
// Second, split on white-space. We expect six parts. // Second, split on white-space. We expect six parts.
std::regex split{ R"#(^\s*(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s*$)#", std::regex split{ R"#(^\s*(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s*$)#",

View File

@@ -237,4 +237,13 @@ SCENARIO("Replacing text with numbers")
std::string s = "JAN-DEC"; std::string s = "JAN-DEC";
REQUIRE(CronData::replace_string_name_with_numeric<libcron::Months>(s) == "1-12"); REQUIRE(CronData::replace_string_name_with_numeric<libcron::Months>(s) == "1-12");
} }
}
SCENARIO("Parsing @ expressions works") {
REQUIRE(CronData::create("@yearly").is_valid());
REQUIRE(CronData::create("@annually").is_valid());
REQUIRE(CronData::create("@monthly").is_valid());
REQUIRE(CronData::create("@weekly").is_valid());
REQUIRE(CronData::create("@daily").is_valid());
REQUIRE(CronData::create("@hourly").is_valid());
} }

View File

@@ -184,6 +184,15 @@ SCENARIO("Examples from README.md")
DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{48}) DT(2018_y / 03 / 1, hours{12}, minutes{13}, seconds{48})
})); }));
REQUIRE(test("0 * * * * ?", DT(2018_y / 03 / 1, hours{ 12 }, minutes{ 0 }, seconds{ 10 }),
{
DT(2018_y / 03 / 1, hours{12}, minutes{1}, seconds{0}),
DT(2018_y / 03 / 1, hours{12}, minutes{2}, seconds{0}),
DT(2018_y / 03 / 1, hours{12}, minutes{3}, seconds{0}),
DT(2018_y / 03 / 1, hours{12}, minutes{4}, seconds{0})
}));
REQUIRE(test("0 0 12 * * MON-FRI", DT(2018_y / 03 / 10, hours{12}, minutes{13}, seconds{45}), REQUIRE(test("0 0 12 * * MON-FRI", DT(2018_y / 03 / 10, hours{12}, minutes{13}, seconds{45}),
{ {
DT(2018_y / 03 / 12, hours{12}), DT(2018_y / 03 / 12, hours{12}),
@@ -212,4 +221,4 @@ SCENARIO("Examples from README.md")
SCENARIO("Unable to calculate time point") SCENARIO("Unable to calculate time point")
{ {
REQUIRE_FALSE(test( "0 0 * 31 FEB *", DT(2021_y / 1 / 1), DT(2022_y / 1 / 1))); REQUIRE_FALSE(test( "0 0 * 31 FEB *", DT(2021_y / 1 / 1), DT(2022_y / 1 / 1)));
} }