随着目前企业的业务越来越深入,很多业务场景会用到调度任务,例如:某公司需要每天在凌晨的1点生成昨日的数据生产报表,实现的方式有很多,目前运用到最多的则是调度任务,通俗讲就是定时任务,只需要设定好时间,到达该时间点就会自动执行任务,那么这种方式实现的具体原理是怎么样的呢,下面我会分几个层面给大家讲下实现的过程,当然也会把我最近使用的比较好的方式代码贴出来,供大家参考,若大家有更好的方式,也可以下方讨论(^_^)
定时任务的设定,需要用到Cron表达式,他可以灵活的配置任务的执行时间,具体配置规则大家可以去参考官方Cron的使用规则,也可以尝试在线配置,地址:https://qqe2.com/cron
这个是整合后的帮助类,里面涵盖了每日 每周 每月等相关定时任务的生成,同时会把执行的时间以集合的形式输出出来。下面我把需要用到的Cron帮助类代码贴出来,供大家参考:
using Newtonsoft.Json.Linq;using NPOI.SS.Util;using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace CronHelper{public class Cron{private int[] seconds = new int[60];private int[] minutes = new int[60];private int[] hours = new int[24];private int[] days = new int[31];private int[] month = new int[12];private int[] weeks = new int[7];//2019-2099年private int[] year = new int[80];public int[] Seconds { get => seconds; set => seconds = value; }public int[] Minutes { get => minutes; set => minutes = value; }public int[] Hours { get => hours; set => hours = value; }public int[] Days { get => days; set => days = value; }public int[] Month { get => month; set => month = value; }public int[] Weeks { get => weeks; set => weeks = value; }public int[] Year { get => year; set => year = value; }public Cron(){for (int i = 0; i < 60; i++){seconds[i] = 0;minutes[i] = 0;}for (int i = 0; i < 24; i++){hours[i] = 0;}for (int i = 0; i < 31; i++){days[i] = 0;}for (int i = 0; i < 12; i++){month[i] = 0;}for (int i = 0; i < 7; i++){weeks[i] = 0;}for (int i = 0; i < 80; i++){year[i] = 0;}}public void Init(){for (int i = 0; i < 7; i++){weeks[i] = 0;}for (int i = 0; i < 31; i++){days[i] = 0;}}}/// <summary>/// 在week上使用 5L表示本月最后一个星期五/// 7L表示本月最后一个星期天////// 在week上使用 7#3表示每月的第三个星期天/// 2#4表示每月的第四个星期二/// </summary>public class CronHelper{/// <summary>/// Cron表达式转换(默认开始时间为当前)/// </summary>/// <param name="cron">表达式</param>/// <returns>最近5次要执行的时间</returns>public static List<DateTime> CronToDateTime(string cron){try{List<DateTime> lits = new List<DateTime>();Cron c = new Cron();string[] arr = cron.Split(' ');Seconds(c, arr[0]);Minutes(c, arr[1]);Hours(c, arr[2]);Month(c, arr[4]);if (arr.Length < 7){Year(c, null);}else{Year(c, arr[6]);}DateTime now = DateTime.Now;int addtime = 1;while (true){if (c.Seconds[now.Second] == 1 && c.Minutes[now.Minute] == 1 && c.Hours[now.Hour] == 1 && c.Month[now.Month - 1] == 1 && c.Year[now.Year - 2019] == 1){if (arr[3] != "?"){Days(c, arr[3], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}else{Weeks(c, arr[5], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}}if (lits.Count >= 5){break;}c.Init();if (!arr[1].Contains('-') && !arr[1].Contains(',') && !arr[1].Contains('*') && !arr[1].Contains('/')){if (now.Minute == int.Parse(arr[1])){addtime = 3600;}}else if (arr[0] == "0" && now.Second == 0){addtime = 60;}now = now.AddSeconds(addtime);}return lits;}catch{return null;}}/// <summary>/// Cron表达式转换(自定义开始时间)/// </summary>/// <param name="cron">表达式</param>/// <param name="now">开始时间</param>/// <returns>最近5次要执行的时间</returns>public static List<DateTime> CronToDateTime(string cron, DateTime now){try{List<DateTime> lits = new List<DateTime>();Cron c = new Cron();string[] arr = cron.Split(' ');Seconds(c, arr[0]);Minutes(c, arr[1]);Hours(c, arr[2]);Month(c, arr[4]);if (arr.Length < 7){Year(c, null);}else{Year(c, arr[6]);}int addtime = 1;while (true){if (c.Seconds[now.Second] == 1 && c.Minutes[now.Minute] == 1 && c.Hours[now.Hour] == 1 && c.Month[now.Month - 1] == 1 && c.Year[now.Year - 2019] == 1){if (arr[3] != "?"){Days(c, arr[3], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}else{Weeks(c, arr[5], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}}if (lits.Count >= 5){break;}c.Init();if (!arr[1].Contains('-') && !arr[1].Contains(',') && !arr[1].Contains('*') && !arr[1].Contains('/')){if (now.Minute == int.Parse(arr[1])){addtime = 3600;}}else if (arr[0] == "0" && now.Second == 0){addtime = 60;}now = now.AddSeconds(addtime);}return lits;}catch{return null;}}/// <summary>/// Cron表达式转换(根据开始时间和结束时间),张鑫/// </summary>/// <param name="cron">表达式</param>/// <param name="now">开始时间</param>/// <returns>判断开始时间和结束时间截止需要执行的时间</returns>public static List<DateTime> CronToDateTime(string cron, DateTime now, DateTime endTime){try{List<DateTime> lits = new List<DateTime>();Cron c = new Cron();string[] arr = cron.Split(' ');Seconds(c, arr[0]);Minutes(c, arr[1]);Hours(c, arr[2]);Month(c, arr[4]);if (arr.Length < 7){Year(c, null);}else{Year(c, arr[6]);}int addtime = 1;while (true){if (c.Seconds[now.Second] == 1 && c.Minutes[now.Minute] == 1 && c.Hours[now.Hour] == 1 && c.Month[now.Month - 1] == 1 && c.Year[now.Year - 2019] == 1){if (arr[3] != "?"){Days(c, arr[3], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}else{Weeks(c, arr[5], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){lits.Add(now);}}}if (now > endTime){break;}c.Init();if (!arr[1].Contains('-') && !arr[1].Contains(',') && !arr[1].Contains('*') && !arr[1].Contains('/')){if (now.Minute == int.Parse(arr[1])){addtime = 3600;}}else if (arr[0] == "0" && now.Second == 0){addtime = 60;}now = now.AddSeconds(addtime);}return lits;}catch{return null;}}/// <summary>/// Cron表达式转换(默认开始时间为当前)/// </summary>/// <param name="cron">表达式</param>/// <returns>最近要执行的时间字符串</returns>public static string GetNextDateTime(string cron){try{DateTime now = DateTime.Now;string[] arr = cron.Split(' ');if (IsOrNoOne(cron)){string date = arr[6] + "/" + arr[4] + "/" + arr[3] + " " + arr[2] + ":" + arr[1] + ":" + arr[0];if (DateTime.Compare(Convert.ToDateTime(date), now) >= 0){return date;}else{return null;}}Cron c = new Cron();Seconds(c, arr[0]);Minutes(c, arr[1]);Hours(c, arr[2]);Month(c, arr[4]);if (arr.Length < 7){Year(c, null);}else{Year(c, arr[6]);}int addtime = 1;while (true){if (c.Seconds[now.Second] == 1 && c.Minutes[now.Minute] == 1 && c.Hours[now.Hour] == 1 && c.Month[now.Month - 1] == 1 && c.Year[now.Year - 2019] == 1){if (arr[3] != "?"){Days(c, arr[3], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){return now.ToString("yyyy/MM/dd HH:mm:ss");}}else{Weeks(c, arr[5], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){return now.ToString("yyyy/MM/dd HH:mm:ss");}}}c.Init();if (!arr[1].Contains('-') && !arr[1].Contains(',') && !arr[1].Contains('*') && !arr[1].Contains('/')){if (now.Minute == int.Parse(arr[1])){addtime = 3600;}}else if (arr[0] == "0" && now.Second == 0){addtime = 60;}now = now.AddSeconds(addtime);}}catch{return null;}}/// <summary>/// Cron表达式转换(自定义开始时间)/// </summary>/// <param name="cron">表达式</param>/// <param name="now">开始时间</param>/// <returns>最近要执行的时间字符串</returns>public static string GetNextDateTime(string cron, DateTime now){try{string[] arr = cron.Split(' ');if (IsOrNoOne(cron)){string date = arr[6] + "/" + arr[4] + "/" + arr[3] + " " + arr[2] + ":" + arr[1] + ":" + arr[0];if (DateTime.Compare(Convert.ToDateTime(date), now) > 0){return date;}else{return null;}}Cron c = new Cron();Seconds(c, arr[0]);Minutes(c, arr[1]);Hours(c, arr[2]);Month(c, arr[4]);if (arr.Length < 7){Year(c, null);}else{Year(c, arr[6]);}int addtime = 1;while (true){if (c.Seconds[now.Second] == 1 && c.Minutes[now.Minute] == 1 && c.Hours[now.Hour] == 1 && c.Month[now.Month - 1] == 1 && c.Year[now.Year - 2019] == 1){if (arr[3] != "?"){Days(c, arr[3], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){return now.ToString("yyyy/MM/dd HH:mm:ss");}}else{Weeks(c, arr[5], DateTime.DaysInMonth(now.Year, now.Month), now);int DayOfWeek = (((int)now.DayOfWeek) + 6) % 7;if (c.Days[now.Day - 1] == 1 && c.Weeks[DayOfWeek] == 1){return now.ToString("yyyy/MM/dd HH:mm:ss");}}}c.Init();if (!arr[1].Contains('-') && !arr[1].Contains(',') && !arr[1].Contains('*') && !arr[1].Contains('/')){if (now.Minute == int.Parse(arr[1])){addtime = 3600;}}else if (arr[0] == "0" && now.Second == 0){addtime = 60;}now = now.AddSeconds(addtime);}}catch{return null;}}/// <summary>/// 返回周计划中间隔周所有的时间集合/// </summary>/// <param name="cron"></param>/// <param name="startTime"></param>/// <param name="endTime"></param>/// <param name="weekNum"></param>/// <returns></returns>public static List<DateTime> CheckWeekIsExcute(string cron, DateTime startTime, DateTime endTime, int weekNum){string[] cronArr = cron.Split(' ');List<DateTime> returnList = new List<DateTime>();// List<DateTime> newDateList = CronHelper.CronToDateTime(cron, startTime, endTime);string[] weekDayArr = cronArr[5].Split(',');foreach (string item in weekDayArr){//间隔周期int jgIndex = 0;for (int k = startTime.Month; k <= endTime.Month; k++){//判断默认从开始月份的第一天 获取本月多少天int allDay = Convert.ToDateTime(startTime.Year + "-" + k + "-01").AddMonths(1).AddDays(-1).Day;for (int i = 1; i < allDay; i++){//获取默认是几月string Monthindex = k.ToString().PadLeft(2, '0');// 获取当前是周几int dayOfweek = (int)Convert.ToDateTime(startTime.ToString("yyyy-" + Monthindex + "-") + i.ToString().PadLeft(2, '0')).DayOfWeek;// 获取当前日期DateTime nowDate = Convert.ToDateTime(startTime.ToString("yyyy-" + Monthindex + "-") + i.ToString().PadLeft(2, '0'));if (nowDate < startTime.Date){continue;}if (nowDate > endTime.Date){break;}//表示该日期就可以执行 如果表达式的 周几等于当前周几 或者 表达式的周是周日并且 现在周是0 ’//获取当前周默认是从周日开始 0-6if (item == dayOfweek.ToString() || (item == "7" && dayOfweek == 0)){if (jgIndex == 0 || jgIndex % weekNum == 0){returnList.Add(nowDate);}jgIndex++;}}}}//.OrderBy(x => x.Date) .Where(x => x.Date >= startTime.Date).ToList()return returnList;}/// <summary>/// 返回周计划中间隔周所有的时间集合【跨年】/// </summary>/// <param name="cron"></param>/// <param name="startTime"></param>/// <param name="endTime"></param>/// <param name="weekNum"></param>/// <returns></returns>public static List<DateTime> CheckWeekIsExcuteNew(string cron, DateTime startTime, DateTime endTime, int weekNum){int weeknum = weekNum;string[] cronArr = cron.Split(' ');//存储原来的开始时间DateTime oldstartTime = startTime;string[] weekDayArr = cronArr[5].Split(',');List<DateTime> resList = new List<DateTime>();int jgIndex = 0;DateTime startExcuteDate = new DateTime(1899, 01, 01);foreach (var item in weekDayArr){//重新获取星期几初始化开始日期为传入的日期startTime = oldstartTime;while (true){//获取开始时间的月份有多少天int monthDay = Convert.ToDateTime(startTime.ToString("yyyy-MM-01")).AddMonths(1).AddDays(-1).Day;for (int i = startTime.Day; i <= monthDay; i++){//判断间隔索引如果大于0则不需要执行循环函数计算执行的开始日期if (jgIndex > 0){break;}//获取当前日期DateTime nowdate = Convert.ToDateTime(startTime.ToString("yyyy-MM-" + i.ToString().PadLeft(2, '0')));//获取当前日期是周几 第一天是从周日开始执行的int week = (int)(nowdate.DayOfWeek);//判断当前周几和传入的周几比较if (item == week.ToString() || (item == "7" && week == 0)){jgIndex++;startExcuteDate = nowdate;resList.Add(startExcuteDate);break;}else if (i == monthDay)//判断是本月的最后一天则还未匹配到需要执行的日期则加一天{startTime = startTime.AddDays(1);}}if (jgIndex > 0){//获取到下次需要执行的日期DateTime nextdate = startExcuteDate.AddDays(jgIndex * weeknum * 7);//判断执行的日期大于结束日期则终止if (nextdate > endTime){jgIndex = 0;startExcuteDate = new DateTime(1899, 01, 01);break;}resList.Add(nextdate);jgIndex++;}}}return resList;}/// <summary>/// 根据制定的计划转换成cron表达式,张鑫/// </summary>/// <param name="dateJson"></param>/// <returns></returns>public static string ConvertToCron(CronModel dateJson){string cron = string.Empty;string excuteType = dateJson.excuteType;if (excuteType.IsNotNullOrEmpty()){DateTime stDate = Convert.ToDateTime(dateJson.startTime);//结束日期为空if (dateJson.endTime.IsNullOrEmpty()){dateJson.endTime = "1899-01-01 00:00:00";}DateTime enDate = Convert.ToDateTime(dateJson.endTime);int excuteTimes = Convert.ToInt32(dateJson.excuteTimes);string excuteMonth = dateJson.excuteMonth;string excuteMonth_Day = dateJson.excuteMonth_Day;int excuteWeek = Convert.ToInt32(dateJson.excuteWeek);string excuteWeek_Day = dateJson.excuteWeek_Day;switch (excuteType){case "Day":cron = ConvertToCron(stDate, enDate, excuteTimes);break;case "Month":cron = ConvertToCron(stDate, enDate, excuteMonth, excuteMonth_Day);break;case "Week":cron = ConvertToCron(stDate, enDate, excuteWeek, excuteWeek_Day);break;default:cron = $"0 0 0 {stDate.Day} {stDate.Month} ? {stDate.Year}";break;}}return cron;}/// <summary>/// 转换为cron表达式日/// </summary>/// <param name="startTime"></param>/// <param name="endTime"></param>/// <param name=""></param>/// <returns></returns>public static string ConvertToCron(DateTime startTime, DateTime endTime, int excuteTimes){Console.WriteLine("调用日生成表达式开始");string yearCron = "*";if (endTime.Year != 1899){yearCron = $"{startTime.Year}-{endTime.Year}";}string cron = $"{startTime.Second} {startTime.Minute} {startTime.Hour} {startTime.Day}/{excuteTimes} * ? {yearCron}";Console.WriteLine("调用日生成表达式结束");return cron;}/// <summary>/// 转换为cron表达式月/// </summary>/// <param name="startTime"></param>/// <param name="endTime"></param>/// <param name=""></param>/// <returns></returns>public static string ConvertToCron(DateTime startTime, DateTime endTime, string excuteMonth, string excuteMonth_Day){Console.WriteLine("调用月生成表达式开始");string yearCron = "*";if (endTime.Year != 1899){yearCron = $"{startTime.Year}-{endTime.Year}";}string cron = string.Empty;string monthNum = GetMonthByChinese(excuteMonth);if (monthNum.Contains("A")){cron = $"{startTime.Second} {startTime.Minute} {startTime.Hour} {excuteMonth_Day} * ? {yearCron}";}else{cron = $"{startTime.Second} {startTime.Minute} {startTime.Hour} {excuteMonth_Day} {monthNum} ? {yearCron}";}Console.WriteLine("调用月生成表达式结束");return cron;}/// <summary>/// 转换为cron表达式周/// </summary>/// <param name="startTime"></param>/// <param name="endTime"></param>/// <param name=""></param>/// <returns></returns>public static string ConvertToCron(DateTime startTime, DateTime endTime, int excuteWeek, string excuteWeek_Day){Console.WriteLine("调用周生成表达式开始");string yearCron = "*";if (endTime.Year != 1899){yearCron = $"{startTime.Year}-{endTime.Year}";}string weekNum = GetWeekByChinese(excuteWeek_Day);string cron = $"{startTime.Second} {startTime.Minute} {startTime.Hour} ? * {weekNum} {yearCron}";Console.WriteLine("调用周生成表达式结束");return cron;}/// <summary>/// Cron表达式转换成中文描述/// </summary>/// <param name="cronExp"></param>/// <returns></returns>public static string TranslateToChinese(string cronExp){if (cronExp == null || cronExp.Length < 1){return "cron表达式为空";}string[] tmpCorns = cronExp.Split(" ");StringBuilder sBuffer = new StringBuilder();if (tmpCorns.Length == 6){//解析月if (!tmpCorns[4].Equals("*")){sBuffer.Append(tmpCorns[4]).Append("月");}else{sBuffer.Append("每月");}//解析周if (!tmpCorns[5].Equals("*") && !tmpCorns[5].Equals("?")){char[] tmpArray = tmpCorns[5].ToCharArray();foreach (char tmp in tmpArray){switch (tmp){case '1':sBuffer.Append("星期天");break;case '2':sBuffer.Append("星期一");break;case '3':sBuffer.Append("星期二");break;case '4':sBuffer.Append("星期三");break;case '5':sBuffer.Append("星期四");break;case '6':sBuffer.Append("星期五");break;case '7':sBuffer.Append("星期六");break;case '-':sBuffer.Append("至");break;default:sBuffer.Append(tmp);break;}}}//解析日if (!tmpCorns[3].Equals("?")){if (!tmpCorns[3].Equals("*")){sBuffer.Append(tmpCorns[3]).Append("日");}else{sBuffer.Append("每日");}}//解析时if (!tmpCorns[2].Equals("*")){sBuffer.Append(tmpCorns[2]).Append("时");}else{sBuffer.Append("每时");}//解析分if (!tmpCorns[1].Equals("*")){sBuffer.Append(tmpCorns[1]).Append("分");}else{sBuffer.Append("每分");}//解析秒if (!tmpCorns[0].Equals("*")){sBuffer.Append(tmpCorns[0]).Append("秒");}else{sBuffer.Append("每秒");}}return sBuffer.ToString();}#region 初始化Cron对象private static void Seconds(Cron c, string str){if (str == "*"){for (int i = 0; i < 60; i++){c.Seconds[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Seconds[i] = 1;}}else if (str.Contains('/')){int begin = int.Parse(str.Split('/')[0]);int interval = int.Parse(str.Split('/')[1]);while (true){c.Seconds[begin] = 1;if ((begin + interval) >= 60)break;begin += interval;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){c.Seconds[int.Parse(str.Split(',')[i])] = 1;}}else{c.Seconds[int.Parse(str)] = 1;}}private static void Minutes(Cron c, string str){if (str == "*"){for (int i = 0; i < 60; i++){c.Minutes[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Minutes[i] = 1;}}else if (str.Contains('/')){int begin = int.Parse(str.Split('/')[0]);int interval = int.Parse(str.Split('/')[1]);while (true){c.Minutes[begin] = 1;if ((begin + interval) >= 60)break;begin += interval;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){c.Minutes[int.Parse(str.Split(',')[i])] = 1;}}else{c.Minutes[int.Parse(str)] = 1;}}private static void Hours(Cron c, string str){if (str == "*"){for (int i = 0; i < 24; i++){c.Hours[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Hours[i] = 1;}}else if (str.Contains('/')){int begin = int.Parse(str.Split('/')[0]);int interval = int.Parse(str.Split('/')[1]);while (true){c.Hours[begin] = 1;if ((begin + interval) >= 24)break;begin += interval;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){c.Hours[int.Parse(str.Split(',')[i])] = 1;}}else{c.Hours[int.Parse(str)] = 1;}}private static void Month(Cron c, string str){if (str == "*"){for (int i = 0; i < 12; i++){c.Month[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Month[i - 1] = 1;}}else if (str.Contains('/')){int begin = int.Parse(str.Split('/')[0]);int interval = int.Parse(str.Split('/')[1]);while (true){c.Month[begin - 1] = 1;if ((begin + interval) >= 12)break;begin += interval;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){c.Month[int.Parse(str.Split(',')[i]) - 1] = 1;}}else{c.Month[int.Parse(str) - 1] = 1;}}private static void Year(Cron c, string str){if (str == null || str == "*"){for (int i = 0; i < 80; i++){c.Year[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin - 2019; i <= end - 2019; i++){c.Year[i] = 1;}}else{c.Year[int.Parse(str) - 2019] = 1;}}private static void Days(Cron c, string str, int len, DateTime now){for (int i = 0; i < 7; i++){c.Weeks[i] = 1;}if (str == "*" || str == "?"){for (int i = 0; i < len; i++){c.Days[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Days[i - 1] = 1;}}else if (str.Contains('/')){int begin = int.Parse(str.Split('/')[0]);int interval = int.Parse(str.Split('/')[1]);while (true){c.Days[begin - 1] = 1;if ((begin + interval) > len)break;begin += interval;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){c.Days[int.Parse(str.Split(',')[i]) - 1] = 1;}}else if (str.Contains('L')){int i = str.Replace("L", "") == "" ? 0 : int.Parse(str.Replace("L", ""));c.Days[len - 1 - i] = 1;}else if (str.Contains('W')){c.Days[len - 1] = 1;}else{c.Days[int.Parse(str) - 1] = 1;}}private static void Weeks(Cron c, string str, int len, DateTime now){if (str == "*" || str == "?"){for (int i = 0; i < 7; i++){c.Weeks[i] = 1;}}else if (str.Contains('-')){int begin = int.Parse(str.Split('-')[0]);int end = int.Parse(str.Split('-')[1]);for (int i = begin; i <= end; i++){c.Weeks[i - 1] = 1;}}else if (str.Contains(',')){for (int i = 0; i < str.Split(',').Length; i++){string num = str.Split(',')[i];//if (num == "0")//{// num = "1";//}c.Weeks[int.Parse(num) - 1] = 1;}}else if (str.Contains('L')){int i = str.Replace("L", "") == "" ? 0 : int.Parse(str.Replace("L", ""));if (i == 0){c.Weeks[6] = 1;}else{c.Weeks[i - 1] = 1;c.Days[GetLastWeek(i, now) - 1] = 1;return;}}else if (str.Contains('#')){int i = int.Parse(str.Split('#')[0]);int j = int.Parse(str.Split('#')[1]);c.Weeks[i - 1] = 1;c.Days[GetWeek(i - 1, j, now)] = 1;return;}else{c.Weeks[int.Parse(str) - 1] = 1;}//week中初始化day,则说明day没要求for (int i = 0; i < len; i++){c.Days[i] = 1;}}/// <summary>/// 中文月份转化为数字/// </summary>/// <param name="chineseMonth"></param>/// <returns></returns>public static string GetMonthByChinese(string chineseMonth){string[] monthArr = chineseMonth.Split(',');string monthNum = string.Empty;foreach (var item in monthArr){switch (item){case "一月": monthNum = monthNum + "," + 1; break;case "二月": monthNum = monthNum + "," + 2; break;case "三月": monthNum = monthNum + "," + 3; break;case "四月": monthNum = monthNum + "," + 4; break;case "五月": monthNum = monthNum + "," + 5; break;case "六月": monthNum = monthNum + "," + 6; break;case "七月": monthNum = monthNum + "," + 7; break;case "八月": monthNum = monthNum + "," + 8; break;case "九月": monthNum = monthNum + "," + 9; break;case "十月": monthNum = monthNum + "," + 10; break;case "十一月": monthNum = monthNum + "," + 11; break;case "十二月": monthNum = monthNum + "," + 12; break;default: monthNum = "A"; break;}}return monthNum.Trim(',');}public static string GetWeekByChinese(string chineseWeek){string[] weekArr = chineseWeek.Split(',');string weekNum = string.Empty;foreach (var item in weekArr){switch (item){case "星期一": weekNum = weekNum + "," + 1; break;case "星期二": weekNum = weekNum + "," + 2; break;case "星期三": weekNum = weekNum + "," + 3; break;case "星期四": weekNum = weekNum + "," + 4; break;case "星期五": weekNum = weekNum + "," + 5; break;case "星期六": weekNum = weekNum + "," + 6; break;case "星期日": weekNum = weekNum + "," + 7; break;}}return weekNum.Trim(',');}#endregion/// <summary>/// 是否执行一次/// </summary>/// <param name="cron"></param>/// <returns></returns>public static bool IsOrNoOne(string cron){if (cron.Contains('-') || cron.Contains(',') || cron.Contains('/') || cron.Contains('*')){return false;}else{return true;}}/// <summary>/// 获取最后一个星期几的day/// </summary>/// <param name="i">星期几</param>/// <param name="now"></param>/// <returns></returns>public static int GetLastWeek(int i, DateTime now){DateTime d = now.AddDays(1 - now.Day).Date.AddMonths(1).AddSeconds(-1);int DayOfWeek = ((((int)d.DayOfWeek) + 6) % 7) + 1;int a = DayOfWeek >= i ? DayOfWeek - i : 7 + DayOfWeek - i;return DateTime.DaysInMonth(now.Year, now.Month) - a;}/// <summary>/// 获取当月第几个星期几的day/// </summary>/// <param name="i">星期几</param>/// <param name="j">第几周</param>/// <param name="now"></param>/// <returns></returns>public static int GetWeek(int i, int j, DateTime now){int day = 0;DateTime d = new DateTime(now.Year, now.Month, 1);int DayOfWeek = ((((int)d.DayOfWeek) + 6) % 7) + 1;if (i >= DayOfWeek){day = (7 - DayOfWeek + 1) + 7 * (j - 2) + i;}else{day = (7 - DayOfWeek + 1) + 7 * (j - 1) + i;}return day;}}}
