From a3b892a24aaced6b73edcd1aa160e6ca14a42a78 Mon Sep 17 00:00:00 2001 From: Peter Jansson <21022916+peter-jansson@users.noreply.github.com> Date: Mon, 20 Dec 2021 08:16:36 +0100 Subject: [PATCH] Added "convenience scheduling" using @yearly, @annually, @monthly, @weekly, @daily or @hourly. (#24) --- README.md | 12 ++++++++++++ libcron/src/CronData.cpp | 13 +++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e05ba8..a98fcd5 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,17 @@ Each part is separated by one or more whitespaces. It is thus important to keep `Day of month` and `day of week` are mutually exclusive so one of them must at always be ignored using the '?'-character to ensure that it is not possible to specify a statement which results in an impossible mix of these fields. +## Convenience scheduling + +These special time specification "nicknames" which replace the 5 initial time and date fields, and are prefixed with the '@' character, are supported: + +@yearly : Run once a year, ie. "0 0 1 1 *". +@annually : Run once a year, ie. "0 0 1 1 *". +@monthly : Run once a month, ie. "0 0 1 * *". +@weekly : Run once a week, ie. "0 0 * * 0". +@daily : Run once a day, ie. "0 0 * * *". +@hourly : Run once an hour, ie. "0 * * * *". + ## Examples |Expression | Meaning @@ -191,6 +202,7 @@ the '?'-character to ensure that it is not possible to specify a statement which | 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 ? * * | Every twelve hours +| @hourly | Every hour # Randomization diff --git a/libcron/src/CronData.cpp b/libcron/src/CronData.cpp index 3122210..777a2c0 100644 --- a/libcron/src/CronData.cpp +++ b/libcron/src/CronData.cpp @@ -37,13 +37,22 @@ namespace libcron void CronData::parse(const std::string& cron_expression) { - // First, split on white-space. We expect six parts. + // First, check for "convenience scheduling" using @yearly, @annually, + // @monthly, @weekly, @daily or @hourly. + std::string tmp = std::regex_replace(cron_expression, std::regex("@yearly"), "0 0 1 1 *"); + tmp = std::regex_replace(tmp, std::regex("@annually"), "0 0 1 1 *"); + tmp = std::regex_replace(tmp, std::regex("@monthly"), "0 0 1 * *"); + tmp = std::regex_replace(tmp, std::regex("@weekly"), "0 0 * * 0"); + tmp = std::regex_replace(tmp, std::regex("@daily"), "0 0 * * *"); + const std::string expression = std::regex_replace(tmp, std::regex("@hourly"), "0 * * * *"); + + // Second, split on white-space. We expect six parts. std::regex split{ R"#(^\s*(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s*$)#", std::regex_constants::ECMAScript }; std::smatch match; - if (std::regex_match(cron_expression.begin(), cron_expression.end(), match, split)) + if (std::regex_match(expression.begin(), expression.end(), match, split)) { valid = validate_numeric(match[1], seconds); valid &= validate_numeric(match[2], minutes);