C语言自研定时器计划任务语法详解

目录
  • 为啥要自研
  • 语法格式
  • 执行计划
  • 符号
  • 模式
  • 语法演示
    • 基本操作
    • 符号操作
    • 模式操作
  • 头文件
  • 实现文件

为啥要自研

市面主流定时器计划任务语法: cron ,但是使用起来非常难受,设计的比较非人性话语法,我想一般人都没几个记住的,都是靠在线生成工具进行使用的,而且只能持续执行不是有限执行,下面举几个cron的案例:

具体想了解的可以自行百度,我试图记住语法,但是因为太混乱了,时间一长就忘了,没法只能到网上工具里生成,而且很多有限的场景没法生成因为cron不支持只执行几次或者有规律的执行,为了解决以上的问题,我自己研究了一套(free time)定时器计划任务语法

语法格式

语法: 0,0,7,0,0,0,0,- 长度为8

对应时间: 秒,分,时,天,星期,月,年,执行计划

执行计划

数值: 执行几次

n: 循环执行

^n: 时间乘阶 2*2,4*2,8*2....

^数值: 时间乘阶几次 ^2 那么就是2*2,4*2

符号

~: 区间 1~4 那么就会执行1,2,3,4

/: 间隔 2/5 那么从2开始下次之后就从5开始执行

[]: 分段 [1,5,10,12] 分别在这几个时间点执行

模式

模式就是可以: 月底,月初,每周几,星期末,年末,节假日等,(可以支持自定义扩张需要对外提供生成器)

执行计划: m(循环执行) ,m数值(有限执行)

begin: 时间底(天底,周末,月底,年底)

end: 时间初(天初,周初,月初,年初)

point(?): 指定时间点,指定每月5号,每周3,每2天

以上是基础模式,其他模式需要自定义(节假日,特殊日期等)

注意: 在模式的基础上还可以配合时间比如: (每天2点1分10秒执行)

语法演示

基本操作

都是以当前时间为基准进行添加时间

当前时间+1分钟后执行(执行2次)

0,1,0,0,0,0,0,2
(2022-09-24 16:22:59,2022-09-24 16:23:59)

当前时间+5小时后执行(循环执行)

0,0,5,0,0,0,0,n
(2022-09-24 21:23:09,2022-09-25 02:23:09)

当前时间+1天后执行

0,0,0,1,0,0,0,n
(2022-09-25 16:24:07,2022-09-26 16:24:07)

当前时间+1星期(7天)后执行

0,0,0,0,1,0,0,n
(2022-10-01 16:25:19,2022-10-08 16:25:19)

当前时间加1天1小时1分1秒后执行

1,1,1,1,0,0,0,2
(2022-09-25 17:38:57,2022-09-26 18:39:58)

当前时间分钟递增执行(循环)

0,1,0,0,0,0,0,^n

当前时间分钟递增执行(次数)

0,1,0,0,0,0,0,^2

符号操作

符号操作有~和[]以及/ 可以配合有限和循环n,不能使用递增

区间执行(循环)

0,2~5,0,0,0,0,0,n(每2分钟3分钟…5分钟各执行一次,然后反复)

间隔执行

0,0,3/0,1,0,0,0,n (3小时后,每天执行一次)

分段执行

0,0,[2,5,8],0,0,0,0,n (当前时间每2,5,8小时执行一次,然后反复)

符号操作还可以和基本操作组合,原理就是相加

0,10,[2,5,8],0,0,0,0,n(当前时间每2,5,8小时加10分钟执行一次,然后反复)

模式操作

在[年,月,星期,天,小时,分支,秒]底执行

年底执行5次

0,0,0,0,0,0,end,mode5
(2023-12-31 23:59:59 ,2024-12-31 23:59:59)

月底执行,一共执行两次

0,0,0,0,0,end,0,mode2
(2022-10-31 23:59:59,2022-11-31 23:59:59)

每个星期日底执行(循环)

0,0,0,0,end,0,0,mode
(2022-10-02 23:59:59,2022-10-09 23:59:59)

每天底执行

0,0,0,end,0,0,0,mode
(2022-09-24 23:59:59 , 2022-09-25 23:59:59)

每小时底执行

0,0,end,0,0,0,0,mode
(2022-09-23 15:59:59,2022-09-23 16:59:59)

每分钟底执行

0,end,0,0,0,0,0,mode
(2022-09-23 14:20:59,2022-09-23 14:21:59)

每秒底执行

end,0,0,0,0,0,0,mode (可能看不出来,所以当做每秒执行就行)
(2022-09-23 14:21:26,2022-09-23 14:22:25)

在[年,月,星期,天,小时,分支,秒]初执行

每年初执行(2次)

0,0,0,0,0,0,begin,mode2
(2023-01-01 00:00:00, 2024-01-01 00:00:00)

没月初执行

0,0,0,0,0,begin,0,mode2
(2022-10-01 00:00:00, 2022-11-01 00:00:00)

每星期初执行

0,0,0,0,begin,0,0,mode
(2022-09-26 00:00:00,2022-10-03 00:00:00)

每天初执行

0,0,0,begin,0,0,0,mode
(2022-09-25 00:00:00,2022-09-26 00:00:00)

每小时初执行

0,0,begin,0,0,0,0,mode
(2022-09-24 16:00:00,2022-09-24 17:00:00)

每分钟初执行

0,begin,0,0,0,0,0,mode
(2022-09-24 15:35:00,2022-09-24 15:36:00)

每秒钟初执行

begin,0,0,0,0,0,0,mode (可能看不出来,所以当做每秒执行就行)
(2022-09-24 15:35:17,2022-09-24 15:35:18)

指定时间执行

我们可以使用模式中的point(?) 来完成,而point除了在星期占位特殊可以指定下个星期几执行,在其他占位也是可以指定时间

每个星期2晚上11点执行

0,0,point(23),0,point(2),0,0,mode
(2022-09-27 22:00:00,2022-10-04 22:00:00)

每天凌晨2点执行

0,0,point(2),point(1),0,0,0,mode
(2022-09-25 02:00:00,2022-09-26 02:00:00)

模式组合

注意: end ,begin 和point 不能同时出现,但是我们可以和基本模式作进行混合

-59,1,-2,end,0,0,0,mode (每天晚上10点执行)

0,0,8,begin,0,0,0,mode (每天早上8点执行)

0,0,8,point(2),0,0,0,mode (每2天8点执行)

头文件

#ifndef STUDY_TIMER_RESOLVER_H
#define STUDY_TIMER_RESOLVER_H
#include "time_util.h"
#include "../util/str_util.h"
#include "assertmy.h"
#include <stdio.h>
#include <stdlib.h>
//秒,分钟,小时,天,星期,月,年,执行计划      -,-,-,-,-,-,-,-      代表0秒,0分,0小时,0天,星期,0月,0年,不执行
typedef struct timer_resolver {
    char *second;//秒 0-59
    char *minute;//分钟 0-59
    char *hour; //小时0-23
    char *day;  //天 1-31
    char *week;//星期 0-6
    char *month;//月份 1-12
    char *year;//年
    char *plan;//执行计划 -代表不执行,n 循环执行,数字代表执行次数 , ^n 阶级执行(^1 表示一阶执行,^2 表示二阶执行,^3 表示三阶执行...^n表示n阶执行)  mode 代表执行模式 mode2 代表模式执行2次....
    long timestamp;//时间戳 用于计算下次执行时间
    char *help;//协助计算的字段
    CharHashMap *mode;//模式

} TimerResolver;

typedef  int  (*ModeMethod)(char *item,int seat,TimerResolver *timerResolver); //自定义模式方法
TimerResolver *create_timer_resolver(char *time);
void print_timer_resolver(TimerResolver *timerResolver);
long resolver(TimerResolver *timerResolver);
void switchStructure(TimerResolver *timerResolver);
void add_timer_mode(TimerResolver *timerResolver, char *key, ModeMethod method);
void print_format_resolver(TimerResolver *timerResolver, int n);
#endif //STUDY_TIMER_RESOLVER_H

实现文件

#include "timer_resolver.h"
char *get_return_data(char **data1);

//获取以当前时间后指定年月日时分秒
long time_point_mode(char *item, int seat, TimerResolver *timerResolver) {
    //解析point(?)模式,取出?的值
    int i = str_find(item, "(");
    item = str_substring(item, i + 1, str_length(item) - 2);
    if (seat == 0) { //加秒数
        return get_next_time_by_timestamp(timerResolver->timestamp, 0, 0, 0, 0, 0, str_to_int(item));
    } else if (seat == 1) { //分钟数
        return get_next_time_by_timestamp(timerResolver->timestamp, 0, 0, 0, 0, str_to_int(item), 0);
    } else if (seat == 2) { //小时数
        return  get_next_time_by_timestamp(timerResolver->timestamp, 0, 0, 0, str_to_int(item), 0, 0);
    } else if (seat == 3) { //天数
        return get_next_time_by_timestamp(timerResolver->timestamp, 0, 0, str_to_int(item), 0, 0, 0);
    } else if (seat == 4) { //周n的日期
        return get_next_week_of_day(timerResolver->timestamp, str_to_int(item));
    } else if (seat == 5) { //月数
        return get_next_time_by_timestamp(timerResolver->timestamp, 0, str_to_int(item), 0, 0, 0, 0);
    } else if (seat == 6) { //年数
        return get_next_time_by_timestamp(timerResolver->timestamp, str_to_int(item), 0, 0, 0, 0, 0);
    }
}

// 判断指定时间,初的时间
long time_begin_mode(char *item, int seat, TimerResolver *timerResolver) {
    if (seat == 0) { //秒数
        return get_start_time_of_next_second(timerResolver->timestamp);
    } else if (seat == 1) { //分钟数
        return get_start_time_of_next_minute(timerResolver->timestamp);
    } else if (seat == 2) { //小时数
        return get_start_time_of_next_hour(timerResolver->timestamp);
    } else if (seat == 3) {// 天数
        return get_start_time_of_next_day(timerResolver->timestamp);
    } else if (seat == 4) {// 星期数
        return get_time_next_week_start(timerResolver->timestamp);
    } else if (seat == 5) {// 月数
        return get_start_time_of_next_month(timerResolver->timestamp);
    } else if (seat == 6) {// 年数
        return get_start_time_of_next_year(timerResolver->timestamp);
    }
}

// 判断指定时间,末的时间
long time_end_mode(char *item, int seat, TimerResolver *timerResolver) {
    if (seat == 0) { //秒数
        return timerResolver->timestamp+59;
    } else if (seat == 1) { //分钟数(如果当前时间是59秒,则返回下一分钟的59秒)
        return get_end_time_of_next_minute(timerResolver->timestamp) ;
    } else if (seat == 2) { //小时数
        return get_end_time_of_next_hour(timerResolver->timestamp) ;
    } else if (seat == 3) { //天数
        return get_end_time_of_next_day(timerResolver->timestamp) ;
    } else if (seat == 4) { //星期数(周末开始时间)
        return get_end_time_of_next_week(timerResolver->timestamp);
    } else if (seat == 5) { //月数
        return get_end_time_of_next_month(timerResolver->timestamp) ;
    } else if (seat == 6) { //年数
        return get_end_time_of_next_year(timerResolver->timestamp) ;
    }
}

// 判断是否有此模式
BOOL mode_exist(char *item, TimerResolver *timerResolver) {
    if(!str_contains(timerResolver->plan,"mode")){
        return FALSE;
    }
    CharHashMapIterator *pIterator = createCharHashMapIterator(timerResolver->mode);
    while (hasNextCharHashMapIterator(pIterator)) {
        CharKvLinkedNode *pNode = nextCharHashMapIterator(pIterator);
        if (str_start_with(item,pNode->key )) {//如果匹配到模式,那么就转换为统一结构化格式
            return TRUE;
        }
    }
    return FALSE;
}

//模式解析
long mode_timer(char *item, int seat, TimerResolver *timerResolver) {
    if (str_contains(timerResolver->plan, "mode")) {
        CharHashMapIterator *pIterator = createCharHashMapIterator(timerResolver->mode);
        while (hasNextCharHashMapIterator(pIterator)) {
            CharKvLinkedNode *pNode = nextCharHashMapIterator(pIterator);
            if (str_start_with(item,pNode->key)) {//如果匹配到模式
                ModeMethod pVoid = (ModeMethod) pNode->value;
                return pVoid(item, seat, timerResolver);//执行模式方法
            }
        }
    }
    return 0;// 没有匹配到模式
}

//添加模式方法(如果执行计划为mode,则支持)
void add_timer_mode(TimerResolver *timerResolver, char *key, ModeMethod method) {
    if (str_contains(timerResolver->plan, "mode")) {
        putCharHashMap(timerResolver->mode, key, method);//添加模式方法
    }
}

void inside_add_timer_mode(TimerResolver *timerResolver) {
    if (str_contains(timerResolver->plan, "mode")) {
        add_timer_mode(timerResolver, "begin", time_begin_mode);
        add_timer_mode(timerResolver, "end", time_end_mode);
        add_timer_mode(timerResolver, "point", time_point_mode);
    }
}

//获取下一次执行时间,返回时间戳
long get_next_time(TimerResolver *timerResolver) {
    if (!timerResolver->plan) {
        return 0;
    }

    if (str_contains(timerResolver->plan, "mode")) {
        long mode_timer1 = mode_timer(get_return_data(&timerResolver->second), 0, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp, mode_timer1);
        long mode_timer2 = mode_timer(get_return_data(&timerResolver->minute), 1, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp,mode_timer2 );
        long mode_timer3= mode_timer(get_return_data(&timerResolver->hour), 2, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp,mode_timer3 );
        long  mode_timer4 = mode_timer(get_return_data(&timerResolver->day), 3, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp, mode_timer4);
        long mode_timer5 = mode_timer(get_return_data(&timerResolver->week), 4, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp, mode_timer5);
        long mode_timer6 = mode_timer(get_return_data(&timerResolver->month), 5, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp, mode_timer6);
        long mode_timer7 = mode_timer(get_return_data(&timerResolver->year), 6, timerResolver);
        timerResolver->timestamp+=get_time_difference_second(timerResolver->timestamp, mode_timer7);
    }
    long current = timerResolver->timestamp;
    //获取当前时间
    int second = str_to_int(get_return_data(&timerResolver->second));
    int minute = str_to_int(get_return_data(&timerResolver->minute));
    int hour = str_to_int(get_return_data(&timerResolver->hour));
    int day = str_to_int(get_return_data(&timerResolver->day));
    int week = str_to_int(get_return_data(&timerResolver->week));
    int month = str_to_int(get_return_data(&timerResolver->month));
    int year = str_to_int(get_return_data(&timerResolver->year));
    long newTime = add_time_one(current,
                                second,
                                minute,
                                hour,
                                day,
                                month,
                                year,
                                week
    );
    timerResolver->timestamp = newTime;
    if(str_contains(timerResolver->plan,"mode")){
        return newTime;
    }else{
        return current;
    }
}

//解析字符串-,-,-,-,-,-,-,-并创建TimerResolver
TimerResolver *create_timer_resolver(char *time) {

    if (time == NULL && strlen(time) == 0) {
        return NULL;
    }
    //去空
    time = str_trim(time);
    //排除[]内的,号
    int start = 0;
    while ((start = str_find_n(time, "[", start, str_length(time))) != -1) {
        int end = str_find_n(time, "]", start, str_length(time));
        time = str_replace_all_n(time, ",", "@", start, end);
        start++;
    }

    TimerResolver *timerResolver = (TimerResolver *) malloc(sizeof(TimerResolver));
    if (timerResolver == NULL) {
        return NULL;
    }
    CharList *pCharlist = str_split(time, ",");
    int str_len = pCharlist->len;
    if (str_len != 8) {
        char message[100];
        sprintf(message, "create_timer_resolver语法错误: %s ", time);
        assertError(message);
    }
    timerResolver->second = pCharlist->str[0];
    timerResolver->minute = pCharlist->str[1];
    timerResolver->hour = pCharlist->str[2];
    timerResolver->day = pCharlist->str[3];
    timerResolver->week = pCharlist->str[4];
    timerResolver->month = pCharlist->str[5];
    timerResolver->year = pCharlist->str[6];
    timerResolver->timestamp = get_current_timestamp();//获取当前时间戳
    //执行计划 -代表不执行,n 循环执行,数字代表执行次数 , ^n 阶级执行(^1 表示一阶执行,^2 表示二阶执行,^3 表示三阶执行...^n表示n阶执行)
    timerResolver->plan = str_compare(pCharlist->str[7], "-") ? "0" : pCharlist->str[7];
    timerResolver->help = "{}";
    timerResolver->mode = createCharHashMap(10);

    //添加模式方法
    inside_add_timer_mode(timerResolver);

    //转换为结构化格式
    switchStructure(timerResolver);

    //计算本次执行时间
    if(!str_contains(timerResolver->plan,"mode")){
        get_next_time(timerResolver);
    }

    return timerResolver;
}

//打印TimerResolver,格式为-,-,-,-,-,-,-,-
void print_timer_resolver(TimerResolver *timerResolver) {
    printf("%s,%s,%s,%s,%s,%s,%s,%s\n", timerResolver->second, timerResolver->minute, timerResolver->hour,
           timerResolver->day, timerResolver->week, timerResolver->month, timerResolver->year,
           timerResolver->plan);
}
//执行n次定时器并且打印效果
void print_format_resolver(TimerResolver *timerResolver, int n) {
    for (int i = 0; i < n; ++i){
        long i1 = resolver(timerResolver);
        char *string = format_time(i1, "%Y-%m-%d %H:%M:%S");
        printf("%ld---%s\n",i1,string);
    }
}

//解析定时器语法,并且生成下次执行时间,如果返回0,则此语法已经执行结束了,可以删除对应的定时器了
long resolver(TimerResolver *timerResolver) {
    //判断是否可执行
    if (str_equals(timerResolver->plan,"0") ) {//不执行
        return 0;
    }

    if (str_compare(timerResolver->plan, "n")) {//循环执行
        return get_next_time(timerResolver);
    }
    //阶级执行
    if (str_start_with(timerResolver->plan, "^")) {
        CharHashMap *pMapSecond = str_to_json_map(timerResolver->second);
        putCharHashMap(pMapSecond, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->second)) * 2));
        timerResolver->second = map_to_json_str(pMapSecond);

        CharHashMap *pMapMinute = str_to_json_map(timerResolver->minute);
        putCharHashMap(pMapMinute, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->minute)) * 2));
        timerResolver->minute = map_to_json_str(pMapMinute);

        CharHashMap *pMapHour = str_to_json_map(timerResolver->hour);
        putCharHashMap(pMapHour, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->hour)) * 2));
        timerResolver->hour = map_to_json_str(pMapHour);

        CharHashMap *pMapDay = str_to_json_map(timerResolver->day);
        putCharHashMap(pMapDay, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->day)) * 2));
        timerResolver->hour = map_to_json_str(pMapDay);

        CharHashMap *pMapWeek = str_to_json_map(timerResolver->week);
        putCharHashMap(pMapWeek, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->week)) * 2));
        timerResolver->week = map_to_json_str(pMapWeek);

        CharHashMap *pMapMonth = str_to_json_map(timerResolver->month);
        putCharHashMap(pMapMonth, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->month)) * 2));
        timerResolver->month = map_to_json_str(pMapMonth);

        CharHashMap *pMapYear = str_to_json_map(timerResolver->year);
        putCharHashMap(pMapYear, "return",
                       int_to_str(str_to_int(get_return_data(&timerResolver->year)) * 2));
        timerResolver->year = map_to_json_str(pMapYear);

        char *string = str_substring(timerResolver->plan, 1, str_length(timerResolver->plan));
        if (str_compare(string, "n")) { //如果是n那么就是循环执行
            return get_next_time(timerResolver);
        }
        if (str_is_number(string)) {//如果是数字,那么就是有限阶级执行
            if (str_compare(string, "0")) {
                return 0;
            }
            char *one = str_calculate_one(string, "--");
            timerResolver->plan = str_concat(2, "^", one);
            return get_next_time(timerResolver);
        }
    }
    //模式执行
    if (str_start_with(timerResolver->plan, "mode")) {
        timerResolver->timestamp= get_start_time_of_day(timerResolver->timestamp );// 初始化为当天的开始时间 ,然后在后面的计算中,加上指定的时间
        if (str_length(timerResolver->plan) == 4) { //循环执行
            return get_next_time(timerResolver);
        } else {
            char *string = str_substring(timerResolver->plan, 4, str_length(timerResolver->plan));
            if (str_is_number(string)) {//如果是数字,那么就是有限阶级执行
                if (str_compare(string, "0")) {
                    return 0;
                }
                char *one = str_calculate_one(string, "--");
                timerResolver->plan = str_concat(2, "mode", one);
                return get_next_time(timerResolver);
            } else {
                assertError(formatStr("mode解析错误非法字符(必须是mode+数字):%s\n", timerResolver->plan));
            }
        }
    }
    //有限执行
    if (str_is_number(timerResolver->plan)) {
        int plan = str_to_int(timerResolver->plan);
        if (plan > 0) {
            timerResolver->plan = int_to_str(plan - 1);
            return get_next_time(timerResolver);
        }

    }

}

//分段[]解析
char *section_analysis(char *item, TimerResolver *timerResolver) {
    //在帮助里存储当前的次数
    CharHashMap *pMap = str_to_json_map(timerResolver->help);
    if (!containsKeyCharHashMap(pMap, "basicsPlan")) {
        putCharHashMap(pMap, "basicsPlan", timerResolver->plan);
        timerResolver->help = map_to_json_str(pMap);
    }
    //将[]里面的@转换为,号
    item = str_replace_all_n(item, "@", ",", 0, str_length(item));
    CharList *pCharlist = str_to_json_array(item);
    //验证是否都是数字
    for (int i = 0; i < pCharlist->len; ++i) {
        if (!str_is_number(pCharlist->str[i])) {
            assertError(formatStr("[]解析错误非法字符(必须是数字):%s\n", pCharlist->str[i]));
        }
    }
    char *string = str_concat(11, "{", "type:[]", ",", "data:", item, ",", "index:0", ",", "return:",
                              pCharlist->str[0], "}");
    //添加执行的次数
    CharHashMap *pMap1 = str_to_json_map(timerResolver->help);
    char *basicsPlan = getCharHashMap(pMap1, "basicsPlan");
    if(str_equals(basicsPlan,"n")||str_start_with(basicsPlan,"^")){
        timerResolver->plan = timerResolver->plan;
    }else{
        if (str_equals(timerResolver->plan, basicsPlan)) {
            timerResolver->plan = int_to_str(pCharlist->len * str_to_int(basicsPlan));
        } else {
            timerResolver->plan = int_to_str(
                    str_to_int(timerResolver->plan) + (pCharlist->len * str_to_int(basicsPlan)));
        }
    }
    return string;
}

//区间解析 符号为~ ,位置1表示秒,2表示分支,3表示小时,4表示天,5表示星期,6表示月,7表示年
char *range_analysis(char *item, TimerResolver *timerResolver) {
    //在帮助里存储当前的次数
    CharHashMap *pMap = str_to_json_map(timerResolver->help);
    if (!containsKeyCharHashMap(pMap, "basicsPlan")) {
        putCharHashMap(pMap, "basicsPlan", timerResolver->plan);
        timerResolver->help = map_to_json_str(pMap);
    }

    CharList *pCharlist = str_split(item, "~");
    //验证是否都是数字
    for (int i = 0; i < pCharlist->len; ++i) {
        if (!str_is_number(pCharlist->str[i])) {
            assertError(formatStr("~解析错误非法字符(必须是数字):%s\n", pCharlist->str[i]));
        }
    }
    CharList *range = get_range(pCharlist->str[0], pCharlist->str[1]);
    char *data = array_to_json_str(range);
    char *string = str_concat(11, "{", "type:~", ",", "data:", data, ",", "index:0", ",", "return:", range->str[0],
                              "}");
    //添加执行的次数
    CharHashMap *pMap1 = str_to_json_map(timerResolver->help);
    char *basicsPlan = getCharHashMap(pMap1, "basicsPlan");
    if(str_equals(basicsPlan,"n")||str_start_with(basicsPlan,"^")){
        timerResolver->plan = timerResolver->plan;
    }else{
        if (str_equals(timerResolver->plan, basicsPlan)) {
            timerResolver->plan = int_to_str(range->len * str_to_int(basicsPlan));
        } else {
            timerResolver->plan = int_to_str(str_to_int(timerResolver->plan) + (range->len * str_to_int(basicsPlan)));
        }
    }

    return string;
}

//间隔/ 解析  (5/2)表示从5开始,每隔2个数 执行一次
char *interval_analysis(char *item, TimerResolver *timerResolver) {
    //在帮助里存储当前的次数
    CharHashMap *pMap = str_to_json_map(timerResolver->help);
    if (!containsKeyCharHashMap(pMap, "basicsPlan")) {
        putCharHashMap(pMap, "basicsPlan", timerResolver->plan);
        timerResolver->help = map_to_json_str(pMap);
    }

    CharList *pCharlist = str_split(item, "/");
    //验证是否都是数字
    for (int i = 0; i < pCharlist->len; ++i) {
        if (!str_is_number(pCharlist->str[i])) {
            assertError(formatStr("/解析错误非法字符(必须是数字):%s\n", pCharlist->str[i]));
        }
    }
    char *data = str_concat(5, "[", pCharlist->str[0], ",", pCharlist->str[1], "]");
    char *string = str_concat(11, "{", "type:/", ",", "data:", data, ",", "index:0", ",", "return:", pCharlist->str[0],
                              "}");
    //添加执行的次数
    CharHashMap *pMap1 = str_to_json_map(timerResolver->help);
    char *basicsPlan = getCharHashMap(pMap1, "basicsPlan");
    if(str_equals(basicsPlan,"n")||str_start_with(basicsPlan,"^")){
        timerResolver->plan = timerResolver->plan;
    }else{
        if (str_equals(timerResolver->plan, basicsPlan)) {
            timerResolver->plan = int_to_str(str_to_int(basicsPlan) + 1);
        }
    }
    return string;
}

char *mode_analysis(char *item, TimerResolver *timerResolver) {
    CharHashMapIterator *pIterator = createCharHashMapIterator(timerResolver->mode);
    while (hasNextCharHashMapIterator(pIterator)) {
        CharKvLinkedNode *pNode = nextCharHashMapIterator(pIterator);
        if (str_start_with(item,pNode->key)) {//如果匹配到模式,那么就转换为统一结构化格式
            char *string = str_concat(6, "{", "type:mode", ",", "return:", item, "}");
            return string;
        }
    }
    assertError(formatStr("mode模式解析错误没有找到对应的模式-请检查模式是否自定义-并且添加到模式集中:%s\n", item));
}

//普通解析
char *normal_analysis(char *item) {
    if (str_is_number(item)) {
        char *string = str_concat(6, "{", "type:number", ",", "return:", item, "}");
        return string;
    }
    assertError(formatStr("解析错误,无法解析的表达式:%s\n", item));
}

//获取结构化数据的返回数据
char *get_return_data(char **data1) {

    char *data = *data1;
    //判断是否是字典格式
    if (str_is_map(data)) {
        //解析字典
        CharHashMap *pMap = str_to_json_map(data);
        //获取类型
        char *type = getCharHashMap(pMap, "type");
        //如果类型是[]
        if (str_compare(type,
                        "[]")) { //如果是[]类型 那么就是分段  例如 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]
            //获取data
            char *data = getCharHashMap(pMap, "data");
            //获取index
            char *index = getCharHashMap(pMap, "index");
            //获取返回数据
            char *returnData = getCharHashMap(pMap, "return");
            //获取数组
            //将[]里面的@转换为,号
            CharList *pCharlist = str_to_json_array(data);
            //获取下一个值
            int nextIndex = str_to_int(index) + 1;
            //判断是否超出数组长度,如果超出长度,从头开始
            if (nextIndex >= pCharlist->len) {
                //超出长度,返回空
                nextIndex = 0;
            }
            //获取下一个值
            char *nextValue = pCharlist->str[nextIndex];
            //设置返回数据
            putCharHashMap(pMap, "return", nextValue);
            //设置index
            putCharHashMap(pMap, "index", int_to_str(nextIndex));
            //修改原数据
            *data1 = map_to_json_str(pMap);
            //返回数据
            return returnData;
        } else if (str_compare(type, "~")) { //如果类型是~ 那么就是区间 1~5 表示1,2,3,4,5
            //如果类型是~
            //获取data
            char *data = getCharHashMap(pMap, "data");
            //获取index
            char *index = getCharHashMap(pMap, "index");
            //获取返回数据
            char *returnData = getCharHashMap(pMap, "return");
            //获取数组
            CharList *pCharlist = str_to_json_array(data);
            //获取下一个值
            int nextIndex = str_to_int(index) + 1;
            //判断是否超出数组长度,如果超出长度,从头开始
            if (nextIndex >= pCharlist->len) {
                nextIndex = 0;
            }
            //获取下一个值
            char *nextValue = pCharlist->str[nextIndex];
            //设置返回数据
            putCharHashMap(pMap, "return", nextValue);
            //设置index
            putCharHashMap(pMap, "index", int_to_str(nextIndex));
            //修改原数据
            *data1 = map_to_json_str(pMap);
            //返回数据
            return returnData;

        } else if (str_compare(type, "/")) { // 如果类型是/ (5/2)表示从5开始,每隔2个数 执行一次
            //如果类型是/
            //获取data
            char *data = getCharHashMap(pMap, "data");
            //获取index
            char *index = getCharHashMap(pMap, "index");
            //获取返回数据
            char *returnData = getCharHashMap(pMap, "return");
            int nextIndex = str_to_int(index) + 1;
            if (nextIndex == 1) {
                //获取数组
                CharList *pCharlist = str_to_json_array(data);
                //判断index是否是1,如果是1,取第二个值,并且转换为普通结构
                char *string = str_concat(6, "{", "type:number", ",", "return:", pCharlist->str[nextIndex], "}");
                *data1 = string;
            }
            return returnData;
        } else if (str_compare(type, "number")) {
            //如果类型是number,那么获取return
            char *returnData = getCharHashMap(pMap, "return");
            return returnData;
        }else if (str_compare(type, "mode")) {
            //如果类型是mode,那么获取return
            char *returnData = getCharHashMap(pMap, "return");
            return returnData;
        }
    }
    assertError(formatStr("解析错误不是结构化数据: %s\n", data));

}

//定时器语法转换为结构化格式
void switchStructure(TimerResolver *timerResolver) {
    //秒
    if (str_contains(timerResolver->second, "[")) {
        timerResolver->second = section_analysis(timerResolver->second, timerResolver);
    } else if (str_contains(timerResolver->second, "~")) {
        timerResolver->second = range_analysis(timerResolver->second, timerResolver);
    } else if (str_contains(timerResolver->second, "/")) {
        timerResolver->second = interval_analysis(timerResolver->second, timerResolver);
    } else if (mode_exist(timerResolver->second, timerResolver)) {
        timerResolver->second = mode_analysis(timerResolver->second, timerResolver);
    } else {
        timerResolver->second = normal_analysis(timerResolver->second);
    }
    //分
    if (str_contains(timerResolver->minute, "[")) {
        timerResolver->minute = section_analysis(timerResolver->minute, timerResolver);
    } else if (str_contains(timerResolver->minute, "~")) {
        timerResolver->minute = range_analysis(timerResolver->minute, timerResolver);
    } else if (str_contains(timerResolver->minute, "/")) {
        timerResolver->minute = interval_analysis(timerResolver->minute, timerResolver);
    } else if (mode_exist(timerResolver->minute, timerResolver)) {
        timerResolver->minute = mode_analysis(timerResolver->minute, timerResolver);
    } else {
        timerResolver->minute = normal_analysis(timerResolver->minute);
    }
    //时
    if (str_contains(timerResolver->hour, "[")) {
        timerResolver->hour = section_analysis(timerResolver->hour, timerResolver);
    } else if (str_contains(timerResolver->hour, "~")) {
        timerResolver->hour = range_analysis(timerResolver->hour, timerResolver);
    } else if (str_contains(timerResolver->hour, "/")) {
        timerResolver->hour = interval_analysis(timerResolver->hour, timerResolver);
    } else if (mode_exist(timerResolver->hour, timerResolver)) {
        timerResolver->hour = mode_analysis(timerResolver->hour, timerResolver);
    } else {
        timerResolver->hour = normal_analysis(timerResolver->hour);
    }
    //日
    if (str_contains(timerResolver->day, "[")) {
        timerResolver->day = section_analysis(timerResolver->day, timerResolver);
    } else if (str_contains(timerResolver->day, "~")) {
        timerResolver->day = range_analysis(timerResolver->day, timerResolver);
    } else if (str_contains(timerResolver->day, "/")) {
        timerResolver->day = interval_analysis(timerResolver->day, timerResolver);
    } else if (mode_exist(timerResolver->day, timerResolver)) {
        timerResolver->day = mode_analysis(timerResolver->day, timerResolver);
    } else {
        timerResolver->day = normal_analysis(timerResolver->day);
    }
    //周
    if (str_contains(timerResolver->week, "[")) {
        timerResolver->week = section_analysis(timerResolver->week, timerResolver);
    } else if (str_contains(timerResolver->week, "~")) {
        timerResolver->week = range_analysis(timerResolver->week, timerResolver);
    } else if (str_contains(timerResolver->week, "/")) {
        timerResolver->week = interval_analysis(timerResolver->week, timerResolver);
    } else if (mode_exist(timerResolver->week, timerResolver)) {
        timerResolver->week = mode_analysis(timerResolver->week, timerResolver);
    } else {
        timerResolver->week = normal_analysis(timerResolver->week);
    }
    //月
    if (str_contains(timerResolver->month, "[")) {
        timerResolver->month = section_analysis(timerResolver->month, timerResolver);
    } else if (str_contains(timerResolver->month, "~")) {
        timerResolver->month = range_analysis(timerResolver->month, timerResolver);
    } else if (str_contains(timerResolver->month, "/")) {
        timerResolver->month = interval_analysis(timerResolver->month, timerResolver);
    } else if (mode_exist(timerResolver->month, timerResolver)) {
        timerResolver->month = mode_analysis(timerResolver->month, timerResolver);
    } else {
        timerResolver->month = normal_analysis(timerResolver->month);
    }
    //年
    if (str_contains(timerResolver->year, "[")) {
        timerResolver->year = section_analysis(timerResolver->year, timerResolver);
    } else if (str_contains(timerResolver->year, "~")) {
        timerResolver->year = range_analysis(timerResolver->year, timerResolver);
    } else if (str_contains(timerResolver->year, "/")) {
        timerResolver->year = interval_analysis(timerResolver->year, timerResolver);
    } else if (mode_exist(timerResolver->year, timerResolver)) {
        timerResolver->year = mode_analysis(timerResolver->year, timerResolver);
    } else {
        timerResolver->year = normal_analysis(timerResolver->year);
    }

}

//释放TimerResolver
void free_timer_resolver(TimerResolver *timerResolver) {
    free(timerResolver);
}

以上就是C语言自研定时器计划任务语法详解的详细内容,更多关于C语言定时器的资料请关注我们其它相关文章!

(0)

相关推荐

  • c语言定时器示例分享

    在linux下开发,使用的是C语言.适用于需要定时的软件开发,以系统真实的时间来计算,它送出SIGALRM信号.每隔一秒定时一次 c语言定时器 复制代码 代码如下: #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <termios.h>#include <errno.h>#include <ctype.h>#include <stdio.

  • C语言实现多线程定时器实例讲解

    1. 大致功能介绍 实现任务列表,定时器会间隔一段时间遍历列表发现要执行的任务 任务列表中的所有任务并行执行 每个任务都可以有自己的定时器,并且可以选择是否要重复执行 定义方便的任务函数实现接口 定时器可以由用户自定义何时启动和停止 提供等待功能,保证任务列表中的所有任务执行完成 提供任务列表的传参功能 2. API库介绍 void setTick(int val); 设置定时间的间隔时间tick,若设置tick为1000,且任务的定时器时间为1000,则任务会在1秒后执行,默认tick为1秒,

  • 利用C语言实现经典多级时间轮定时器

    目录 1. 序言 2. 多级时间轮实现框架 2.1 多级时间轮对象 2.2 时间轮对象 2.3 定时任务对象 2.4 双向链表 2.5 联结方式 3. 多级时间轮C语言实现 3.1 双向链表头文件: list.h 3.2 调试信息头文件: log.h 3.3 时间轮代码: timewheel.c 3.4 编译运行 总结 1. 序言 最近一直在找时间轮的C语言实现代码,发现很多都是Java或者c++实现的.而我对其他语言不熟悉,看不太懂.关于C实现的,让我如沐春风的实现没找到,github上也只找

  • C语言实现简单的定时器

    本文实例为大家分享了C语言实现简单的定时器的具体代码,供大家参考,具体内容如下 1.代码分析 2.代码 #include <stdio.h> #include <time.h> #include <conio.h> #ifndef CLOCKS_PER_SEC #define CLOCKS_PER_SEC 1000 #endif int main( void ) { clock_t start; long count = 1; start = clock(); whil

  • vc6.0中c语言控制台程序中的定时技术(定时器)

    打开main.c编译运行,注意,打开main.c之后一定要将win32timer.c也加进工程中一起编译,下面有图.在开发单片机.ARM以及Linux系统的程序时,因为硬件定时中断的存在我们很方便构造出定时ISR,然而在VC6.0中,我们如何写一个定时程序呢?其实,就是timeSetEvent()这个函数的调用.这个函数的解释见MSDN.详细原理,请看我代码中的注释,我写得很详细了. main.c 复制代码 代码如下: //======================// main.c//===

  • C语言自研定时器计划任务语法详解

    目录 为啥要自研 语法格式 执行计划 符号 模式 语法演示 基本操作 符号操作 模式操作 头文件 实现文件 为啥要自研 市面主流定时器计划任务语法: cron ,但是使用起来非常难受,设计的比较非人性话语法,我想一般人都没几个记住的,都是靠在线生成工具进行使用的,而且只能持续执行不是有限执行,下面举几个cron的案例: 具体想了解的可以自行百度,我试图记住语法,但是因为太混乱了,时间一长就忘了,没法只能到网上工具里生成,而且很多有限的场景没法生成因为cron不支持只执行几次或者有规律的执行,为了

  • 基于JS脚本语言的基础语法详解

    JS脚本语言的基础语法:输出语法  alert("警告!");  confirm("确定吗?");   prompt("请输入密码");为弱类型语言: 开始时要嵌入JS代码:<script type="text/javascript"></script>: 关于写程序是需注意的基本语法: 1.所有的字符全都是英文半角的: 2.大部分情况下每条语句结束后要加分号: 3.每一块代码结束后加换行:4.程序前呼

  • C语言ASM汇编内嵌语法详解

    3 GCC Inline ASM GCC 支持在C/C++代码中嵌入汇编代码,这些汇编代码被称作GCC Inline ASM--GCC内联汇编.这是一个非常有用的功能,有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中,另外也允许我们直接写 C/C++代码中使用汇编编写简洁高效的代码. 1.基本内联汇编 GCC中基本的内联汇编非常易懂,我们先来看两个简单的例子: __asm__("movl %esp,%eax"); // 看起来很熟悉吧! 或者是 __asm__(&q

  • C语言类的基本语法详解

    目录 1.由C语言的结构体进入到C++中的类 2.C++中如何定义类? 3.C++中实例化一个对象 4.C++类的访问限定及其封装 C++中的访问限定符 5.C++中类的作用域 6.成员变量和方法在类中是如何存储的? 总结 1.由C语言的结构体进入到C++中的类 我们在C语言中当需要定义多个变量的数据集合时,第一时间会想到使用结构体来进行定义,例如我们定义一个学生变量,包含姓名.年龄.性别等信息,代码示例如下: struct Student{ char name[12]; int age; ch

  • Java语言class类用法及泛化(详解)

    这篇文章主要介绍了Java语言class类用法及泛化(详解),大家都知道Java程序在运行过程中,对所有的对象进行类型标识,也就是RTTI.这项信息记录了每个对象所属的类.虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类.Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建,具体内容介绍如下: 说白了就是: Class类也是类的一种,只是名字和class关键字高度相似.Java是大小写敏感的语言. Class类的对象内容是你创

  • Android Kotlin开发实例(Hello World!)及语法详解

    Android Kotlin开发实例及语法详解 前言 Kotlin是一种在 Java虚拟机上执行的静态型别编程语言,它主要是由俄罗斯圣彼得堡的JetBrains开发团队所发展出来的编程语言.该语言有几个优势 1. 简洁 它大大减少你需要写的样板代码的数量. 2. 安全 避免空指针异常等整个类的错误. 3. 通用 构建服务器端程序.Android 应用程序或者在浏览器中运行的前端程序. 4. 互操作性 通过 100% Java 互操作性,利用 JVM 既有框架和库. 配置 在我们的AndroidS

  • C语言文件操作中 fgets与fputs 函数详解

    C语言文件操作中 fgets.fputs 函数详解 先给出api fgets 语法: #include <stdio.h> char *fgets( char *str, int num, FILE *stream ); 函数fgets()从给出的文件流中读取[num - 1]个字符并且把它们转储到str(字符串)中. fgets()在到达行末时停止,在这种情况下,str(字符串)将会被一个新行符结束. 如果fgets()达到[num - 1]个字符或者遇到EOF, str(字符串)将会以nu

  • Python定时器线程池原理详解

    这篇文章主要介绍了Python定时器线程池原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 定时器执行循环任务: 知识储备 Timer(interval, function, args=None, kwargs=None) interval ===> 时间间隔 单位为s function ===> 定制执行的函数 使用threading的 Timer 类 start() 为通用的开始执行方法 cancel ()为取消执行的方法 普通单次

  • C++语法详解之封装、构造函数、析构函数

    大家先了解下什么是构造函数,什么是析构函数,作用是什么? 构造函数(方法)是对象创建完成后第一个被对象自动调用的方法.它存在于每个声明的类中,是一个特殊的成员方法.作用是执行一些初始化的任务.Php中使用__construct()声明构造方法,并且只能声明一个. 析构函数(方法)作用和构造方法正好相反,是对象被销毁之前最后一个被对象自动调用的方法.是PHP5中新添加的内容作用是用于实现在销毁一个对象之前执行一些特定的操作,诸如关闭文件和释放内存等. 下面在通过具体例子看下C++语法详解之封装.构

  • javascript中正则表达式语法详解

    好久都没有写博客了,主要是太懒了,尤其是在阳春三月,风和日丽的日子,太阳暖暖的照在身上,真想美美的睡上一觉.就导致了这篇博客拖到现在才开始动笔,javascript的正则这一块也不是什么新的东西,主要是以前本人一遇到写正则的需求就开始头大,头疼,网上剽窃,东拼西凑,反正就是各种不适应,所以我打算系统的把正则表达式看一遍,一来是自己有所提升,这一块知识点的查漏补缺,二来是给大家分享一下.好了,下面我们直接进入主题: 正则是匹配字符串特定模式的一种表达式,官方是这样说的,但我的理解不外乎就是匹配字符

随机推荐