涉及各种定时任务时,常常不满足于只能指定间隔时间,Cron表达式隆重登场。Cron表达式是Linux系统标配,用于系统定时任务,只是Linux的Cron标准最小仅支持分钟,不支持秒。而我们的Cron表达式最小支持秒。

Nuget包:NewLife.Core

源码:https://github.com/NewLifeX/X/blob/master/NewLife.Core/Threading/Cron.cs

Cron简介

基本构成:秒+分+时+天+月+星期+年
每段构成:
*全部,该类型片段全部可选
?跳过
数字,具体某个数值可选
-区间,横杠表示的一个区间可选
逗号多选,逗号分隔的多个数字或区间可选
/步进,在上述可选数字内,间隔多少选一个

例如:
*/2 每两秒一次
0,1,2 每分钟的0秒1秒2秒各一次
5/20 每分钟的5秒25秒45秒各一次

*1-10,13,25/3 每小时的1分4分7分10分13分25分,每一秒各一次
0 0 0 1 每个月1日的0点整
0 0 2 * * 1-5 每个工作日的凌晨2点


星期部分采用Linux和.NET风格,0表示周日,1表示周一。
可设置Sunday为1,1表示周日,2表示周一。

用法

Cron类支持通过构造函数指定表达式字符串,也可以Parse方法分析表达式

/// <summary>实例化Cron表达式</summary>
/// <param name="expression"></param>
public Cron(String expression) => Parse(expression);

/// <summary>分析表达式</summary>
/// <param name="expression"></param>
/// <returns></returns>
public Boolean Parse(String expression);

/// <summary>指定时间是否位于表达式之内</summary>
/// <param name="time"></param>
/// <returns></returns>
public Boolean IsTime(DateTime time);

/// <summary>获得指定时间之后的下一次执行时间,不含指定时间</summary>
/// <param name="time"></param>
/// <returns></returns>
public DateTime GetNext(DateTime time);

Cron类实现得轻量级,本质上是穷举了每一个时间段。IsTime方法正是判断目标时间是否落入这些时间段之中,也就是是否匹配该表达式。

GetNext 用于获取指定时间之后的下一次匹配时间,常用于判断定时任务的下一次执行时间。

示例如下:

var cron = new Cron("0 * * * *");
Assert.True(cron.IsTime(DateTime.Parse("8:00:00")));
Assert.False(cron.IsTime(DateTime.Parse("8:00:01")));
Assert.Single(cron.Seconds);
Assert.Equal(0, cron.Seconds[0]);

cron = new Cron("0-10 * * * *");
Assert.True(cron.IsTime(DateTime.Parse("8:00:00")));
Assert.True(cron.IsTime(DateTime.Parse("8:00:03")));
Assert.Equal(11, cron.Seconds.Length);
Assert.Equal(0, cron.Seconds[0]);
Assert.Equal(10, cron.Seconds[10]);

cron = new Cron("*/2 * * * *");
Assert.True(cron.IsTime(DateTime.Parse("8:00:00")));
Assert.True(cron.IsTime(DateTime.Parse("8:00:02")));
Assert.False(cron.IsTime(DateTime.Parse("8:00:03")));
Assert.Equal(30, cron.Seconds.Length);

cron = new Cron("5/20 * * * *");
Assert.True(cron.IsTime(DateTime.Parse("8:00:05")));
Assert.True(cron.IsTime(DateTime.Parse("8:00:25")));
Assert.False(cron.IsTime(DateTime.Parse("8:00:20")));
Assert.Equal(3, cron.Seconds.Length);

// 下一次,5秒后
var dt = DateTime.Today;
var dt2 = cron.GetNext(dt);
Assert.Equal(dt.AddSeconds(5), dt2);

// 后续每次间隔20秒
dt2 = cron.GetNext(dt2);
Assert.Equal(dt.AddSeconds(25), dt2);

dt2 = cron.GetNext(dt2);
Assert.Equal(dt.AddSeconds(45), dt2);

总结

Cron表达式在某些场合非常重要,在魔方中作为标准定时任务实现,基础类库TimerX也支持Cron表达式。

此处为内容卡片,点击链接查看:https://newlifex.com/core/timerx

作者:大石头 发布:2022-05-24 16:37:14 浏览:1,430)