计时器内的日期比较

本文关键字:比较 日期 计时器 | 更新日期: 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.TicksDateTime.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);