你可以做几件事来解决这个问题。
一种是将 UTC 用于所有计划的作业。这为您提供了一个强大且可预测的系统,没有很多复杂性或测试负担。但夏季周一 03:00 运行的作业将在冬季 02:00 运行。如果没问题,那么 UTC 策略是一个很好的策略。
(测试时区切换用例是一件很痛苦的事情,如果你对所有事情都使用 UTC,你的测试负担就会减轻。)
另一个是认真对待你的日期算术,并且要非常小心。即使在转换日期,C# 的 DateTime 类也能很好地完成日期算术。
因此,假设您需要在周日的 01:30 每周运行一次进程。那是在美国的噩梦时刻......它不会发生在春季转换中,它会在秋季转换中发生两次。但是您仍然希望该过程运行一次。
您所做的是:保持“下一个预定时间”值。每次完成运行作业时,计算下一次运行的“下一次计划时间”值。这可能像这样工作:
var today = DateTime.Today.AddDays(7); /* midnight a week from now */
TimeSpan runTime = TimeSpan.Parse("01:30");
var nextRun = today + runTime;
然后,保存 nextRun DateTime 值。稍后您可以计算出距离下一次运行还有多长时间。这是一个很好的方法。还有其他的。
var msUntilNextRun = (nextRun.Ticks - DateTime.Now.Ticks) / 10000;
如果 msUntilNextRun 值相当小且为正值,则您可以休眠直到运行时间。如果它变得小而消极,你睡过头了——立即跑(睡过头很常见)。
将天数添加到当前的午夜值,然后将时间添加到该值,然后计算等待多长时间,即使在转换日也是一种获得合理运行时间的方法。