公司有个嵌入式低功耗项目,项目需求中有一项是仿照Linux cron task的定时设置,作为设备定时唤醒时间。于是就自己琢磨写了C语言的Crontab表达式执行时间,各种调试结果与crontab执行时间在线工具一致。用到了基姆拉尔森计算公式计算星期,Linux源码中的Crond.c文件的ParseField函数。希望能对同行有帮助。
crontab表达式的知识请自行百度。
先讲讲实现思路:
1、参考Linux源码中的Crond.c文件的static char *ParseField(char *user, char *ary, int modvalue, int off,const char *const *names, char *ptr);函数,将crontab表达式解析成结构体CronLine中的分钟数组,小时数组,日期数组,月份数组和星期数组,并对其对应项赋值为1.
typedef struct CronLine
{
char cl_Mins[60]; /* 0-59 */
char cl_Hrs[24]; /* 0-23 */
char cl_Days[32]; /* 0-31 */
char cl_Mons[12]; /* 0-11 */
char cl_Dow[7]; /* 0-6, beginning sunday */
} CronLine;
static char *ParseField(char *user, char *ary, int modvalue, int off,const char *const *names, char *ptr);
2、写一个函数,函数功能:调用一次,时间加1分钟。
3、从当前时间(先输入设置时间,当然可以改成获取系统时间)向后一分钟一分钟的遍历,满足条件后把满足条件的时间打印出来。
//寻找满足crond条件的时间点
uint8_t GetWakeUpTimePoint(CronLine *pline,struct data_time_str *p_data)
{
if((pline->cl_Mins[p_data->min] == 1)
&& (pline->cl_Hrs[p_data->hour] == 1)
&& (pline->cl_Days[p_data->day] == 1)
&& (pline->cl_Mons[p_data->month] == 1)
&& (pline->cl_Dow[p_data->week] == 1))
{
printf("%04d年%02d月%02d日 %02d:%02d:00 星期%d\r\n",
p_data->year,p_data->month,p_data->day,
p_data->hour,p_data->min,p_data->week);
return 1;
}
return 0;
}
int main()
{
CronLine line = {0};
char *ptr;
/*buf:Crontab表达式*/
char buf[] = "0 0 1,20 * * "; //0 18 * * * //10 5 */5 * *
ptr = ParseField("Mins", line.cl_Mins, 60, 0, NULL, buf);
ptr = ParseField("Hrs", line.cl_Hrs, 24, 0, NULL, ptr);
ptr = ParseField("Days", line.cl_Days, 32, 0, NULL, ptr);
ptr = ParseField("Mons", line.cl_Mons, 12, -1, MonAry, ptr);
ptr = ParseField("Week", line.cl_Dow, 7, 0, DowAry, ptr);
if (ptr == NULL)
{
printf("It's over\r\n");
}
/*
uint8_t min;
uint8_t hour;
uint8_t day;
uint8_t month;
uint16_t year;
*/
//先定义个时间初始值
//struct data_time_str CalcDataTime = {34,9,30,8,2019,4};
//获取当前时间
SYSTEMTIME st;
GetLocalTime(&st);
struct data_time_str CalcDataTime = {0};
CalcDataTime.year = st.wYear;
CalcDataTime.month = st.wMonth;
CalcDataTime.day = st.wDay;
CalcDataTime.hour = st.wHour;
CalcDataTime.min = st.wMinute;
uint32_t cnt = 0; //做个循环限制
uint8_t getcnt = 0; //记录找到唤醒时间的次数
while((cnt < 0xFFFFFFFF) && (getcnt <= 10))
{
cnt++;
UpdateTimeBuf(&CalcDataTime);
if(GetWakeUpTimePoint(&line,&CalcDataTime))
{
getcnt++;
}
}
system("pause");
return 0;
}
有任何问题联系低调奢华猿QQ:2573507779
源码:https://download.csdn.net/download/qq_33901011/11643934
工程用VS2010打开直接编译运行就可以,也可以用DevC++直接打开main,cpp编译运行看结果。