So, I figure there would be different ways to approach this. If I had to do it, I probably would go for some variation of the strategy pattern and divide & conquer.
Divide & Conquer:
Separate switching / time checking from the actual job. So, I'd find some way to exchange a "do the job" strategy to a "do nothing" or "drop job" strategy.
That could be done using Quartz or a similar scheduling framework inside the app, which would trigger "switch off" and "switch on" jobs at the appropriate times.
Same could be done with cron or windows task scheduler which could trigger an api in your app. This opens up an attack vector, though.
Strategy pattern
That's relatively simple here: You'd have an interface with two implementations. The "switch on/off" jobs then simply "plug in" the appropriate implementation.
Example:
interface IWorker{
void DoWork(); // maybe with an argument
}
class ActiveWorker : IWorker
{
public void DoWork()
{
workerService.DoWork(); // replace with whatever is appropriate for you.
}
}
class InactiveWorker : IWorker
{
public void DoWork()
{
// Maybe just do nothing?
// Maybe actively drop a request?
}
}
In your consumer, you'd then have
IWorker worker; // Setup initially based on DateTime.Now
void ConsumingLooper()
{
//...
worker.DoWork(); // Based on which impl. is set to 'worker' will
// either handle or drop
}
Don't forget to add measures to handle the case where the looper wants to call worker.DoWork()
while it is switched out. I left it out for brevity and also there are many different ways to achieve it. You may want to pick your favorite.