using System; namespace Neo.Afx.Services { /// /// The poll time is specified as d.hh:mm:ss where seconds are always ignored. /// Hours and minutes are used to specify the time of day for all frequencies. /// If the poll frequency is then /// days refers to the day of week and must be a number between zero (Sun) and 6 (Sat). /// If the poll frequency is then /// days refers to the day of month. Otherwise days are ignored. /// public class ServiceSchedule { readonly int _pollDays; readonly int _pollHours; readonly int _pollMinutes; readonly int _pollSeconds; #region Initialization /// /// Initializes a new instance of the class. /// /// The poll frequency. /// The poll time specified as d.hh:mm:ss public ServiceSchedule(PollFrequencyEnum pollFrequency, TimeSpan pollTime) { PollFrequency = pollFrequency; _pollDays = pollTime.Days; _pollHours = pollTime.Hours; _pollMinutes = pollTime.Minutes; _pollSeconds = pollTime.Seconds; switch (pollFrequency) { case PollFrequencyEnum.Weekly: if(_pollDays < (int)DayOfWeek.Sunday) { _pollDays = (int)DayOfWeek.Sunday; } else if(_pollDays > (int)DayOfWeek.Saturday) { _pollDays = (int)DayOfWeek.Saturday; } break; case PollFrequencyEnum.Monthly: if(_pollDays < 1) { _pollDays = 1; } else if(_pollDays > 31) { _pollDays = 31; } break; } } #endregion #region PollFrequency /// /// Gets the poll frequency. /// public PollFrequencyEnum PollFrequency { get; private set; } #endregion #region LastRunTime /// /// Gets or sets the last run time. /// public DateTime LastRunTime { get; set; } #endregion #region NextRunTime /// /// Calculates the next run time based on the . /// /// The signal time. /// The next run time. public DateTime NextRunTime(DateTime signalTime) { double offset; var nextTime = signalTime; switch(PollFrequency) { case PollFrequencyEnum.Seconds: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, LastRunTime.Day, LastRunTime.Hour, LastRunTime.Minute, LastRunTime.Second); break; case PollFrequencyEnum.Minutes: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, LastRunTime.Day, LastRunTime.Hour, LastRunTime.Minute, 0); break; case PollFrequencyEnum.Hourly: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, LastRunTime.Day, LastRunTime.Hour, _pollMinutes, 0); break; case PollFrequencyEnum.Daily: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, LastRunTime.Day, _pollHours, _pollMinutes, 0); break; case PollFrequencyEnum.Weekly: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, LastRunTime.Day, _pollHours, _pollMinutes, 0); offset = (int)nextTime.DayOfWeek - _pollDays; nextTime = nextTime.AddDays(-offset); break; case PollFrequencyEnum.Monthly: nextTime = new DateTime(LastRunTime.Year, LastRunTime.Month, 1, _pollHours, _pollMinutes, 0); var maxDays = DateTime.DaysInMonth(nextTime.Year, nextTime.Month); offset = Math.Min(_pollDays, maxDays); nextTime = nextTime.AddDays(offset - 1); break; } if(nextTime == signalTime) { return signalTime; } if(nextTime > signalTime) { return nextTime; } // next < signalTime i.e. // next run time has already elapsed // so increment to the next interval switch(PollFrequency) { case PollFrequencyEnum.Seconds: return nextTime.AddSeconds(_pollSeconds); case PollFrequencyEnum.Minutes: return nextTime.AddMinutes(_pollMinutes); case PollFrequencyEnum.Hourly: return nextTime.AddHours(1); case PollFrequencyEnum.Daily: return nextTime.AddDays(1); case PollFrequencyEnum.Weekly: return nextTime.AddDays(7); case PollFrequencyEnum.Monthly: return nextTime.AddMonths(1); } return signalTime; } #endregion #region IsDue /// /// Determines if the schedule is due in the given time frame. /// /// The begin time. /// The end time. /// true if the schedule is due; false otherwise. public bool IsDue(DateTime begin, DateTime end) { var next = NextRunTime(begin); return next <= end; } #endregion } }