2017-02-15 95 views
0

我有任务的以下数据结构:计算下一运行时间任务

Task{ 
    Start: 17:00:00 
    End: 20:00:00 
    Interval: 5 
    Days: [1, 2, 3, 6, 7] 
} 

所以这有点像一个时间表设置一些任务。我有一个windows服务,每5秒钟进行一次滴答,如果是时候运行任务,它会进行一些计算。这很容易检查。例如,我正在检查当前时间的当天是否在Days阵列中,如果当前时间在StartEnd之间等。因此,此任务将在17:05:04,17:10:01等(接近5秒)执行。所以它现在的时间接近17:00 + N*5 seconds它执行一些代码。这是正常工作。

我现在正努力研究计算未来这项任务的执行时间。例如,如果现在是Monday 16:58:30,则下次它将被执行时是Monday 17:05。如果是Friday 18:00它将在Saturday 17:05执行。如果是Monday 18:33,则下一次运行是Monday 18:35。困难来当你意识到,开始可以是这样的开始:17:03:00等运行时间现在这支17:0817:13

回答

0
/// <summary> 
/// Calculates the next run for the task. 
/// </summary> 
/// <param name="task"></param> 
/// <returns></returns> 
public static string GetNextRun(TaskBase task) 
{ 
    var now = DateTime.Now; 
    var currentDay = now.DayOfWeek == DayOfWeek.Sunday ? 7.ToString() : ((int)now.DayOfWeek).ToString(); 
    var currentTime = now.TimeOfDay; 

    var startAt = task.StartAt; 

    //If Days is empty the task will never execute. 
    if (task.Days.Length == 0) 
    { 
     return "Never"; 
    } 
    //If the current day is allowed. 
    else if (task.Days.Contains(currentDay)) 
    { 
     //If current time is allowed 
     if (currentTime >= task.StartAt && currentTime <= task.StopAt) 
     { 
      //Start from beginning and add interval till we get a time greater than current day. 
      while (startAt < currentTime) 
      { 
       startAt = startAt.Add(TimeSpan.FromMinutes(task.IntervalInMinutes)); 
      } 

      //If we are still in the allowed range return this time. 
      if (startAt >= task.StartAt && startAt <= task.StopAt) 
      { 
       return now.Date.Add(startAt).ToString(); 
      } 
     } 
     //If we are before starting point just return the first tick. 
     else if (currentTime < task.StartAt) 
     { 
      startAt = startAt.Add(TimeSpan.FromMinutes(task.IntervalInMinutes)); 

      return now.Date.Add(startAt).ToString(); 
     } 
    } 

    startAt = task.StartAt; 

    //If the current day is not allowed or the day is allowed but currentTime > task.StopAt. 
    //Add days until we get next allowed day and return the first tick. 
    while (true) 
    { 
     now = now.AddDays(1); 
     currentDay = now.DayOfWeek == DayOfWeek.Sunday ? 7.ToString() : ((int)now.DayOfWeek).ToString(); 

     if (task.Days.Contains(currentDay)) 
     { 
      startAt = startAt.Add(TimeSpan.FromMinutes(task.IntervalInMinutes)); 

      return now.Date.Add(startAt).ToString(); 
     } 
    } 
}