计算任务的下一个运行时间

时间:2017-02-15 20:55:13

标签: algorithm scheduled-tasks

我有以下任务的数据结构:

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

因此,这类似于某项任务的计划设置。我有一个Windows服务,每5秒钟滴答一次,如果是时候运行任务就做一些计算。检查它很简单。例如,我正在检查当前时间的当天是否在Days数组中,如果当前时间介于StartEnd之间等等,那么此任务将在{{1}执行},17:05:04等(近似为5秒)。所以它当前时间接近17:10:01它执行一些代码。这是正常的。

我正在努力解决将来执行此任务的计算时间。如果现在是17:00 + N*5 seconds,则下次执行时Monday 16:58:30Monday 17:05。如果是Friday 18:00,则会在Saturday 17:05执行。如果是Monday 18:33,则下一次运行为Monday 18:35。当你意识到Start可以像Start:17:03:00之类的时候出现困难,因此现在正在调整运行时间17:0817:13等。

1 个答案:

答案 0 :(得分: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();
        }
    }
}