计时器内的日期比较
本文关键字:比较 日期 计时器 | 更新日期: 2023-09-27 17:49:46
我有一个每秒运行一次的计时器,代码如下:
public MainWindow()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(1000);
timer.Tick += new EventHandler(someEventHandler);
timer.Start();
}
private void someEventHandler(Object sender, EventArgs args)
{
TVMonitor TVMonitor = new TVMonitor();
if (TVMonitor.NeedsTurningOn())
{
Console.WriteLine("on");
TVCOM.SendCommand(SettingManager.GetTVCode("on") + Environment.NewLine);
}
}
在函数NeedsTurningOn()
中,我有以下内容:
public bool NeedsTurningOn()
{
var turnon = (from settings in context.SystemSettings
where settings.SystemSettingName == "TVOnTime"
select settings).First();
if (turnon.SystemSettingValue == String.Empty)
{
return false;
}
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
Console.WriteLine("Turnontime: " + date);
Console.WriteLine("currenttim: " + DateTime.Now);
if (date != DateTime.Now)
{
Console.WriteLine("false");
return false;
}
else
{
Console.WriteLine("true");
return true;
}
}
现在,在我用于调试的控制台中,我有以下输出:
...
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:07
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:08
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:09
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:10
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:11
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:12
false
...
为什么在日期相同的情况下仍然会触发假而不是真?
这是因为DateTime变量的分辨率为1毫秒…你是在比较,好像它的分辨率是1秒。
试题:
if (Math.Abs(date.Subtract(DateTime.Now).Milliseconds) < 1000) { ... }
您可以通过将1000更改为不同的数字来调整匹配的分辨率…500将检查date
是否在当前日期/时间的半秒内。
您只比较每秒钟的时间-毫秒仍然是不同的(特别是假设您比较的打开时间很可能不使用毫秒)。要在第二个分辨率下进行比较,可以这样做:
DateTime currentTime = DateTime.Now;
currentTime = currentTime.AddMilliseconds(-currentTime.Millisecond);
这里的其他答案指出了为什么你会看到你的行为;即两个DateTime变量的毫秒数不同。
我建议你的条件灵活一点。您依赖于这样一个事实,即您的NeedsTurningOn
方法将在您在打开时间设置中配置的那一秒钟内执行。如果系统挂起一秒钟怎么办?您的代码可能会间歇性地错过打开的窗口。如果您决定将计时器的间隔从1000更改为5000呢?在这种情况下,你的代码只有1/5的机会在正确的时间内执行。
我建议你这样写:
if (this.IsTurnedOn)
{
Console.WriteLine("false - already on");
return false;
}
else
{
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
Console.WriteLine("Turnontime: " + date);
Console.WriteLine("currenttim: " + DateTime.Now);
if (date > DateTime.Now)
{
Console.WriteLine("false");
return false;
}
else
{
Console.WriteLine("true");
return true;
}
}
基本上,将IsTurnedOn
属性添加到您的TVMonitor类中以充当标志,以便您知道是否真的需要打开它。另外,将date != DateTime.Now
更改为date > DateTime.Now
,因为我假设您真正想要确定的是配置的开启时间已经过了。
也许你应该比较一下总时间或类似的东西?我可以想象毫秒的差别
试着把你的时间写成date.Ticks
和DateTime.Now.Ticks
,你就会明白为什么了。分辨率远小于一秒。
如果你想要第二个分辨率,你必须比较日,月,年,小时,分钟和秒。
一个滴答声代表一百纳秒或千万分之一秒。一毫秒有10,000个滴答,所以你需要一台非常快的计算机来匹配相同的滴答:)
因为Date和TimeSpan包含比秒更细的组件,即毫秒和滴答。
我建议比较TotalSeconds属性
解决我的问题:
感谢上面所有的帮助,我在日期比较之前将这个添加到我的函数中:
DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
DateTime current = DateTime.Now;
current = current.AddMilliseconds(-current.Millisecond);
date = date.AddMilliseconds(-date.Millisecond);