2017-02-15 122 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(); 
     } 
    } 
}