CRON date&time range

Motivation for LwDTC library comes with my home automation project, where I need a simple way to define range of date or time, from and to, in very flexible and field-agnostic way. It should be possible to just define from and to seconds within a minute, or from 2 different minutes and different seconds.

CRON concept doesn’t provide such functionality. To overcome such problem, a simple solution with multiple cron objects can be implemented. Consider a task, that needs to execute each beginning of a minute, between Monday starting at 07:00:00 and Friday ending at 19:30:00.

For CRON-like compatible syntax, defined range needs a split to:

  • Monday: CRON is active every beginning of a minute from 07 to 23 hours. This can be described as: 0 * 7/1 * * 1 *

  • Tue,Wed,Thu: CRON is active at beginning of each minute for all 3 days: 0 * * * * 2-4 *

  • Friday:

    • CRON is active between 0 and 19 hours, at beginning of each minute: 0 * 7-19 * * 5 *

    • CRON is also active at beginning of each minute, when minutes are between 0 and 30 and when hour is 19: 0 0-30 19 * * 5 *

This gives us in total 4 different cron objects, for which:

  • We need to parse all of them

  • To check if particular time is within range, an OR operation between all ranges is performed

CRON date&time range descriptor
 1#include "windows.h"
 2#include <time.h>
 3#include <stdio.h>
 4#include "lwdtc/lwdtc.h"
 5
 6/*
 7 * This is example for docs user manual
 8 *
 9 * Defines time range:
10 * - Starts at Monday at 07:00 morning
11 * - Ends on Friday at 19:30 evening
12 */
13static const char* cron_strings[] = {
14    "0 * 7/1 * * 1 *",
15    "0 * * * * 2-4 *",
16    "0 * 7-19 * * 5 *",
17    "0 0-30 19 * * 5 *"
18};
19
20/* Define context array for all CRON strings */
21static lwdtc_cron_ctx_t cron_ctx[LWDTC_ARRAYSIZE(cron_strings)] = {0};
22
23int
24cron_dt_range(void) {
25    /* Define context for CRON, used to parse data to */
26    struct tm* timeinfo;
27    time_t rawtime, rawtime_old = 0;
28
29    /* Parse all CRON strings */
30    for (size_t i = 0; i < LWDTC_ARRAYSIZE(cron_strings); ++i) {
31        if (lwdtc_cron_parse(&cron_ctx[i], cron_strings[i]) != lwdtcOK) {
32            printf("Could not parse CRON: %s\r\n", cron_strings[i]);
33            while (1) {}
34        }
35    }
36
37    while (1) {
38        /* Get current time and react on changes only */
39        time(&rawtime);
40
41        /* Check if new time has changed versus last read */
42        if (rawtime != rawtime_old) {
43            rawtime_old = rawtime;
44            timeinfo = localtime(&rawtime);
45
46            /* Print time to user */
47            printf("Time: %02d.%02d.%04d %02d:%02d:%02d\r\n",
48                (int)timeinfo->tm_mday, (int)timeinfo->tm_mon, (int)timeinfo->tm_year + 1900,
49                (int)timeinfo->tm_hour, (int)timeinfo->tm_min, (int)timeinfo->tm_sec
50            );
51
52            /* Check if current time fits inside CRON-defined time range */
53            if (lwdtc_cron_is_valid_for_time_multi_or(timeinfo, cron_ctx, LWDTC_ARRAYSIZE(cron_ctx)) == lwdtcOK) {
54                printf("Time is within CRON range\r\n");
55            } else {
56                printf("Time is NOT within CRON range\r\n");
57            }
58        }
59
60        /* This is sleep from windows.h lib */
61        Sleep(100);
62    }
63    return 0;
64}