System.Timers.Timer和夏令时

时间:2015-11-02 22:06:36

标签: c# date datetime timezone system.timers.timer

我有一些计时器从表中读取HH:MM:SS以确定何时每天运行。

例如:
定时器A需要每周一13:00:00运行 计时器B需要每周二02:00:00运行 定时器C需要每小时运行

所以在我的代码中,我弄清楚当前时间是多少,然后计算从DateTime.Now()到计时器应该运行的下一次出现的毫秒数。当计时器的Elapsed事件完成后,它会重新计算它应该在下一次运行的时间。由于时间的变化,这在本周末造成了问题。

有更好的方法吗? DateTime.UtcNow会更好吗?也许将数据库中的时间字符串转换为UTC时间,然后找出DateTime.UtcNow()而不是DateTime.Now()之间的差异?

1 个答案:

答案 0 :(得分:-1)

你可以做几件事来解决这个问题。

一种是将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值合理地小而且积极,那么您可以睡觉直到它运行的时间。如果它出现小而负,你睡过头 - 立即跑(睡过头非常常见)。

将天数添加到当前的午夜值,然后将时间添加到该值,然后计算等待的时间,即使在转换日也能获得合理的运行时间。

相关问题