- Vsak dan med 6:00 in 7:30
- Od petka 20:00 do ponedeljka 07:00, periodično, ne glede na leto ali mesec
- Vsako uro od 0 - 15 minut
- Vsako drugo uro med 15 in 30 minut znotraj ure (torej je veljaven range med 00:15-00:30, 02:15-02:30, etc)
Konceptualno je mix med crontab unix-like time definicijo in pa direktni time compare večje ali manjše, ker moram definirati range med dvema časoma (ampak range ni nujno absoluten, lahko je samo od-do minute-sekunde, ali mesec, ali karkoli).
Izvedba z crontab je lepa in enostavna, narediš bitno polje, ki je 1 kadar je match in 0 kadar ni. Problem je, da ni mogoče narediti range sistema.
Cron omogoča:
- Zadeva je vedno veljavna, ko je minuta med 0 in 15, ne glede na uro. Postavimo prvih 16 bitov na 1 in potem primerjamo (bitfield & (1 << trenutna_minuta))
- Zadeva je vedno veljavna, ko je minuta med 0 in 15 in ura soda
- Zadeva je veljavna vsak dan med 01:00 in 02:00
Z cron opisom ni mogoče narediti efektivnega range-a, recimo
- Zadeva je veljavna vsak dan med 07:00 in 08:30, predvsem zato, ker če damo cronu 0-30 pri minutah, bo zadeva veljavna 07:00-07:30 in 08:00-08:30), torej zgubimo 30 min

Jaz bi rad naredil mix obojega.
Igram se na razne načine kako bi to najbolj efektivno implementiral. Kakšna ideja?
Recimo cron bit-field implementacija je fairly simple in check deluje lepo.
- Koda: Izberi vse
#include <time.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* Flags for valid entries in structure */
#define FLAG_VALID_SEC ((uint16_t)0x0001)
#define FLAG_VALID_MIN ((uint16_t)0x0002)
#define FLAG_VALID_HOUR ((uint16_t)0x0004)
#define FLAG_VALID_WDAY ((uint16_t)0x0008)
#define FLAG_VALID_MDAY ((uint16_t)0x0010)
#define FLAG_VALID_YDAY ((uint16_t)0x0020)
#define FLAG_VALID_MON ((uint16_t)0x0040)
#define FLAG_VALID_WEEK ((uint16_t)0x0080)
#define FLAG_VALID_YEAR ((uint16_t)0x0100)
static inline void
prv_set_bit_field(uint8_t* obj, uint8_t startindex, uint8_t endindex, uint8_t step) {
if (step == 0) {
step = 1;
}
for (; startindex < endindex; startindex += step) {
obj[startindex / 8] |= 1 << (startindex % 8);
}
}
static inline uint8_t
prv_check_bit(const uint8_t* obj, uint8_t bitpos) {
return (obj[bitpos / 8] & (1 << (bitpos % 8))) > 0;
}
/**
* \brief Bit-field set when specific date is a valid cron range
*/
typedef struct {
uint16_t flags; /*!< Flags for fields to be part of comparison.
If flag is not set, any value is valid (do not compare) */
uint8_t sec[8]; /*!< Seconds in a minute, from 0 to 59 */
uint8_t min[8]; /*!< Minutes past full hour, from 0 to 59 */
uint8_t hour[3]; /*!< Minutes past full day, from 0 to 23 */
uint8_t wday[1]; /*!< Day in a week, from 0 (Sunday) to 6 (Saturday) */
uint8_t mday[4]; /*!< Day in month, from 1 to 31 */
uint8_t yday[46]; /*!< Day in year since January 1st, from 0 to 365 */
uint8_t mon[2]; /*!< Month since January, from 0 to 11 */
uint8_t week[7]; /*!< Week in a year, from 1 to 53 */
uint8_t year[13]; /*!< Year since 2000, up to 2100 is allowed (0 - 100) */
} time_cron_t;
#define DT_RESET(dt) memset((dt), 0x00, sizeof(*dt))
/*
* Setters
*
* dt: Date time object
* startindex: Range start
* stopindex: Range stop
* step: Step in range
*
* For example, to set valid cron each even hour, use
* DT_SET_HOUR(&dt, 0, 24, 2)
*/
#define DT_SET_SEC(dt, startindex, stopindex, step) prv_set_bit_field((dt)->sec, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_SEC
#define DT_SET_MIN(dt, startindex, stopindex, step) prv_set_bit_field((dt)->min, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_MIN
#define DT_SET_HOUR(dt, startindex, stopindex, step) prv_set_bit_field((dt)->hour, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_HOUR
#define DT_SET_WDAY(dt, startindex, stopindex, step) prv_set_bit_field((dt)->wday, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_WDAY
#define DT_SET_MDAY(dt, startindex, stopindex, step) prv_set_bit_field((dt)->mday, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_MDAY
#define DT_SET_YDAY(dt, startindex, stopindex, step) prv_set_bit_field((dt)->yday, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_YDAY
#define DT_SET_MON(dt, startindex, stopindex, step) prv_set_bit_field((dt)->mon, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_MON
#define DT_SET_WEEK(dt, startindex, stopindex, step) prv_set_bit_field((dt)->week, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_WEEK
#define DT_SET_YEAR(dt, startindex, stopindex, step) prv_set_bit_field((dt)->year, (startindex), (stopindex), (step)); (dt)->flags |= FLAG_VALID_YEAR
#define ERR(message) printf("[LINE %d] %s\r\n", (int)__LINE__, (message))
static uint8_t
prv_check_inside_range(const struct tm* curr_dt, const time_cron_t* range) {
/*
* Comparion starts with flag check.
*
* If flag is NOT set, check doesn't need to be done
* as any value for particular field is valid
*/
if ((range->flags & FLAG_VALID_SEC) && !prv_check_bit(range->sec, curr_dt->tm_sec)) {
ERR("Seconds failed");
return 0;
}
if ((range->flags & FLAG_VALID_MIN) && !prv_check_bit(range->min, curr_dt->tm_min)) {
ERR("Minutes failed");
return 0;
}
if ((range->flags & FLAG_VALID_HOUR) && !prv_check_bit(range->hour, curr_dt->tm_hour)) {
ERR("Hours failed");
return 0;
}
if ((range->flags & FLAG_VALID_WDAY) && !prv_check_bit(range->wday, curr_dt->tm_wday)) {
ERR("Week day failed");
return 0;
}
if ((range->flags & FLAG_VALID_MDAY) && !prv_check_bit(range->mday, curr_dt->tm_mday)) {
ERR("Month day failed");
return 0;
}
if ((range->flags & FLAG_VALID_YDAY) && !prv_check_bit(range->yday, curr_dt->tm_yday)) {
ERR("Year day failed");
return 0;
}
if ((range->flags & FLAG_VALID_MON) && !prv_check_bit(range->mon, curr_dt->tm_mon)) {
ERR("Month failed");
return 0;
}
if ((range->flags & FLAG_VALID_YEAR) && !prv_check_bit(range->year, curr_dt->tm_year)) {
ERR("Year failed");
return 0;
}
ERR("All good, current time is inside range");
return 1;
}
int
cron_demo_single_var(void) {
time_cron_t dt_range;
time_t curr_time;
struct tm *tm;
/* Set range start datetime */
DT_RESET(&dt_range);
DT_SET_HOUR(&dt_range, 10, 12, 0); /* Range is valid any day between 10:00 to 12:00 */
/* Get current system time */
time(&curr_time);
tm = localtime(&curr_time);
tm->tm_year -= 100; /* Start from 2000 for particular test */
printf("Time is in the range: %u\r\n", prv_check_inside_range(tm, &dt_range));
return 0;
}
Kakšna pametna ideja kako najbolj pametno implementirat?
Trenutno razmišljam o setu flagov, ki bi določal kako določeno spremenljivko primerjam, večje/manjše, ali bitfield.
To dodatno poveča velikost strukture, ker poleg bit-field rabiš še 2x time spremenljivki za range
Možgani so mi tokrat ultra zaribali