根据基本日期时间获取"now"后的下一个日期时间间隔



我有一个作业调度程序,我正在将其更改为更精确的时间安排。

它应根据开始时间以给定的 x 分钟间隔运行。

解决我的问题的一个简单但效率低下的解决方案是:

var scheduledOn = new DateTime(2017, 01, 3, 9, 5, 0);
var minutesBetweenJob = 5;
while (scheduledOn < DateTime.Now)
{
    scheduledOn = scheduledOn + TimeSpan.FromMinutes(minutesBetweenJob);
}
Console.WriteLine("Correct Answer: " + scheduledOn);

但是,如果工作没有运行,那就说一年。它需要运行大量 5 分钟的迭代才能正确,这是非常低效的!

我已经尝试了几种方法,但由于浮点错误,它们最终非常不准确。

这是我自己问题的解决方案。它的性能似乎比我之前的尝试至少快 10-20 倍,并且精确到毫秒。

我发现在处理纳秒时会出现浮点错误,因此将日期时间修剪为秒甚至毫秒,解决了这个问题。

/// <summary>
/// This function calculates the next datetime interval for a given datetime, based on a scheduled time.
/// Eg. Job is scheduled to run at 15:00 and every 5 minutes, the next scheduled time will be 15.05, then 15.10 and so forth.
/// The calculated time will always be after the "afterDateTime".
/// </summary>
/// <param name="baseDatetime">The time that scheduled time is based on</param>
/// <param name="interval">The interval in minutes</param>
/// <param name="afterDateTime">Usually datetime now, but the date it should be "after".</param>
/// <param name="tickPrecision">[Optional (Default = TimeSpan.TicksPerSecond)] Determine the tick precision, the lowest possible value is TicksPerMillisecond</param>
/// <returns>The next scheduled time</returns>
public static DateTime CalculateNextScheduledTime(DateTime baseDatetime, int interval, DateTime afterDateTime, long tickPrecision = TimeSpan.TicksPerSecond)
{
    // Reset afterDateTime to tick precision.
    afterDateTime = new DateTime(((long)afterDateTime.Ticks / tickPrecision) * tickPrecision);
    // (Subtract Difference in modulus time intervals between aftertime base time) + the interval.
    return afterDateTime - TimeSpan.FromMinutes((afterDateTime - baseDatetime).TotalMinutes % interval) + TimeSpan.FromMinutes(interval);
}

最新更新