正在计算任务的下一个 运行 时间
Calculating the next run time for the task
我有以下任务数据结构:
Task{
Start: 17:00:00
End: 20:00:00
Interval: 5
Days: [1, 2, 3, 6, 7]
}
所以这有点像某些任务的时间表设置。我有一个 windows 服务,它每 5 秒滴答一次,并在需要 运行 任务时进行一些计算。检查它很简单。例如,我正在检查当前时间的日期是否在 Days
数组中,当前时间是否在 Start
和 End
之间等等。所以这个任务将在 [=15= 执行], 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
。当您意识到 Start 可以类似于 Start: 17:03:00
并且 运行ning 时间现在被转移 17:08
、17:13
等
时,困难就来了
/// <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();
}
}
}
我有以下任务数据结构:
Task{
Start: 17:00:00
End: 20:00:00
Interval: 5
Days: [1, 2, 3, 6, 7]
}
所以这有点像某些任务的时间表设置。我有一个 windows 服务,它每 5 秒滴答一次,并在需要 运行 任务时进行一些计算。检查它很简单。例如,我正在检查当前时间的日期是否在 Days
数组中,当前时间是否在 Start
和 End
之间等等。所以这个任务将在 [=15= 执行], 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
。当您意识到 Start 可以类似于 Start: 17:03:00
并且 运行ning 时间现在被转移 17:08
、17:13
等
/// <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();
}
}
}