Implementing an on-the-minute timer

On-the-minute timers can be very useful for executing recurring tasks that are tied to specific times of day. For example, if you’re developing a monitoring tool for a website that updates its content every hour, you’d want to have a timer in the application that commands to pull the new data on an one-hour interval. Standard .NET timers will start raising events as soon as they are enabled, so, depending on when they were started, they can trigger at 1:27, then at 2:27, then at 3:27 and so on. This is not ideal, because then the data will not be pulled as soon as it’s updated in the source, which happens right on the hour, at 1:00, 2:00, etc. In our case, we can set the initial interval of the timer to whatever time is left until the next hour and then, after the first tick, set it back to one hour. That does the job, and it's also possible to apply the same approach for making the timer trigger on-the-minute or on-the-second. But what happens if we need it to trigger every hour, exactly on the :15 minute mark?

Thinking of a way to generalize it, I came up with the following interface. Meet the SyncedTimer.

To use this type of timer, you will need to set the Interval like normal, but there’s also a new property – FirstTickDateTime. It pretty much acts like an offset, the timer will work as if it was (or is going to be) started in that given time. That property defaults to DateTime.Today, which is 00:00 of the current day.

For simple cases, like on-the-minute and on-the-hour timers, you don’t have to set the FirstTickDateTime property, instead just create the object like you would create a normal timer.

You will notice that, no matter when the program is started, the timer ticks exactly on the minute (disregarding small error for execution time).

For the other case, which is a bit more complex, we can set the first tick time to 00:15 of today, with an interval of one hour.

This example will output the current time to console every hour, but on the :15 minute mark instead (1:15, 2:15, 3:15, etc).