// // JobScheduleDescription.cs // // Author: // Carsten Sonne Larsen // // Copyright (c) 2013 Carsten Sonne Larsen // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; namespace Ntp.Process { /// /// A description of job schedule rules. /// public sealed class JobScheduleDescription { /// /// Initializes a new instance of the class. /// /// If set to true initial run. /// If set to true fixed run. /// Frequency in minutes. public JobScheduleDescription (bool initialRun, bool fixedRun, int frequency) { this.initialRun = initialRun || (frequency == 0); this.fixedRun = fixedRun; this.frequency = frequency; initialRunDone = false; } private readonly bool initialRun; private readonly bool fixedRun; private readonly int frequency; private bool initialRunDone; /// /// Gets a value indicating whether this /// should do an initial run upon first call. /// /// true if initial run; otherwise, false. public bool InitialRun { get { return initialRun; } } /// /// Gets a value indicating whether this has /// a fixed schedule frequence, eg. cannot be moved. /// /// true if fixed run; otherwise, false. public bool FixedRun { get { return fixedRun; } } /// /// Gets the schedule frequency in minutes. /// /// The frequency. public int Frequency { get { return frequency; } } /// /// Gets a value indicating whether this description allow schedules to be moved. /// /// true if this instance can move; otherwise, false. public bool CanMove { get { return !(initialRun && !initialRunDone) && !fixedRun; } } /// /// Creates a new scheduled job based on description and parameters. /// /// The new. /// Job. /// Start. /// Offset. public ScheduledJob CreateNew (Job job, DateTime start, double offset) { if (initialRun && !initialRunDone) { initialRunDone = true; return new ScheduledJob (job, start); } return new ScheduledJob (job, CalculateNextRun (start).AddMinutes (offset)); } /// /// Creates a postponed job schedule. /// /// The postponed. /// Job. public ScheduledJob CreatePostponed (Job job) { double offset = frequency / 100; if (offset > 2) { offset = 2; } else if (offset < 0.5) { offset = 0.5; } return new ScheduledJob (job, DateTime.Now.AddMinutes (offset)); } /// /// Calculates the time of next run according to description parameters. /// /// The next run. /// Start. public DateTime CalculateNextRun (DateTime start) { if (frequency == -1) return DateTime.MaxValue; else if (frequency == 0 || (initialRun && !initialRunDone)) return start; int multiplier = Convert.ToInt32 (System.Math.Truncate ((double)(start.Hour * 60 + start.Minute) / frequency)); int startMinuttes = multiplier * frequency; int hour = (startMinuttes + frequency) / 60; int minute = (startMinuttes + frequency) % 60; if (hour >= 24) { hour -= 24; start = start.AddDays (1); } if (minute >= 60) { minute -= 60; start = start.AddHours (1); } DateTime next = new DateTime (start.Year, start.Month, start.Day, hour, minute, 0); return next; } } }