123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667 |
- namespace WingServerCommon.Utilities
- {
- public class CronHelper
- {
- /// <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");
- }
- }
- }
- else if(c.Seconds[0] == 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") + ":00");
- }
- }
- 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") + ":00");
- }
- }
- }
- 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>最近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;
- }
- }
- #region 初始化Cron对象
- /// <summary>
- /// 指定秒位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">秒位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定分位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">分位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定小时位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">小时位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定月位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">月位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定年位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">年位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定天位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">天位</param>
- 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;
- }
- }
- /// <summary>
- /// 指定星期位
- /// </summary>
- /// <param name="c">cron表达式</param>
- /// <param name="str">星期位</param>
- 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++)
- {
- c.Weeks[int.Parse(str.Split(',')[i]) - 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;
- }
- }
- #endregion
- /// <summary>
- /// 获取最后一个星期几的day
- /// </summary>
- /// <param name="i">星期几</param>
- /// <param name="now">现在时间</param>
- /// <returns></returns>
- private 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>
- private 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;
- }
- /// <summary>
- /// 是否一个
- /// </summary>
- public static bool IsOrNoOne(string cron)
- {
- if (cron.Contains('-') || cron.Contains(',') || cron.Contains('/') || cron.Contains('*'))
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- }
- public class Cron
- {
- /// <summary>
- /// 秒位,表示1-60秒
- /// </summary>
- private int[] seconds = new int[60];
- /// <summary>
- /// 分位,表示1-60分
- /// </summary>
- private int[] minutes = new int[60];
- /// <summary>
- /// 小时位,表示1-12小时
- /// </summary>
- private int[] hours = new int[24];
- /// <summary>
- /// 天位,表示1-31天
- /// </summary>
- private int[] days = new int[31];
- /// <summary>
- /// 月位,表示1-12月
- /// </summary>
- private int[] month = new int[12];
- /// <summary>
- /// 星期位,表示星期1-星期天
- /// </summary>
- 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;
- }
- }
- /// <summary>
- /// 初始化星期和天
- /// </summary>
- public void Init()
- {
- for (int i = 0; i < 7; i++)
- {
- weeks[i] = 0;
- }
- for (int i = 0; i < 31; i++)
- {
- days[i] = 0;
- }
- }
- }
- }
|