开发者

Date comparison within timer

开发者 https://www.devze.com 2023-02-23 07:39 出处:网络
I have a timer that runs every second, the code is bellow: public MainWindow() { InitializeComponent(); DispatcherTimer timer = new DispatcherTimer();

I have a timer that runs every second, the code is bellow:

    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);
        }
    }

In the function NeedsTurningOn() I have the following:

    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.Writ开发者_JAVA百科eLine("true");
            return true;
        }
    }

Now in the console which I am using for debugging, I have the following output:

...
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
...

Why is this still firing off a false instead of true once the date is the same?


It's because a DateTime variable has a resolution of 1 millisecond... you're comparing as if it has a resolution of 1 second.

Try:

if (Math.Abs(date.Subtract(DateTime.Now).Milliseconds) < 1000) { ... }

You can adjust the resolution of the match by changing 1000 to a different number... 500 will check to see if date is within half a second of the current date/time.


You only compare the times every second - the milliseconds will still be different (especially assuming the turn-on time you compare to most likely doesn't use milliseconds). To compare in a second resolution you could do something like this:

DateTime currentTime = DateTime.Now;
currentTime = currentTime.AddMilliseconds(-currentTime.Millisecond);


The other answers here point out why you're seeing the behavior that you have; namely that the milliseconds of the two DateTime variables are different.

I would recommend that you make your condition a little more flexible. You're relying on the fact that your NeedsTurningOn method will execute during exactly that second that you have configured in your turn-on-time setting. What if the system hangs for a second? Your code may intermittently miss the window for turning on. What if you decide to change the interval of your timer from 1000 to 5000? In that case your code will only have about a 1/5 chance of executing during the correct second.

I'd suggest making your condition something like this:

    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;
        }
    }

Basically, add an IsTurnedOn property to your TVMonitor class to act as a flag so that you know whether or not you really need to turn it on. Also, change date != DateTime.Now to date > DateTime.Now, because I assume what you're really trying to determine is that the configured turn-on-time has elapsed.


Maybe you should compare the total seconds or something like that? I can imagine the milliseconds differ...


Try writing out your time as date.Ticks and DateTime.Now.Ticks and you will see why. The resolution is much smaller than a second.

If you want second resolution you have to compare day, month, year, hour, minute and second only.

A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond, so you would need a really fast computer to match on the same tick :)


Since Date and TimeSpan contains components finer than seconds, i.e Milliseconds and Ticks.

I'd suggest comparing the TotalSeconds property.


Solution to my problem:

Thanks for all the help above, I added this into my function before the date comparison:

DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
DateTime current = DateTime.Now;
current = current.AddMilliseconds(-current.Millisecond);
date = date.AddMilliseconds(-date.Millisecond);
0

精彩评论

暂无评论...
验证码 换一张
取 消