/// <summary> /// Checks the frist occurrence. /// </summary> /// <param name="pattern">The pattern.</param> /// <param name="recurrenceStartTime">The recurrence start time.</param> /// <param name="now">The now.</param> /// <returns></returns> public static bool CheckFristOccurrence(string pattern, DateTime recurrenceStartTime, DateTime now) { AsyncServiceException.ThrowIfNull(pattern, "RecurrencePattern"); TimeSpan zero = TimeSpan.Zero; // 首次执行检查忽略秒、毫秒 recurrenceStartTime = recurrenceStartTime - TimeSpan.FromMilliseconds(recurrenceStartTime.Millisecond) - TimeSpan.FromSeconds(recurrenceStartTime.Second); now = now - TimeSpan.FromMilliseconds(now.Millisecond) - TimeSpan.FromSeconds(now.Second); IRecurrencePattern recurrencePattern = Create(pattern, recurrenceStartTime, TimeZone.CurrentTimeZone, zero); switch (recurrencePattern.Frequency) { case RecurrenceFrequency.None: return false; case RecurrenceFrequency.Secondly: // 按秒重复,不需前移 break; case RecurrenceFrequency.Minutely: // 按分钟重复先将开始日期前移间隔分钟,以判断是否需执行 recurrencePattern = Create(pattern, recurrenceStartTime.AddMinutes(-1 * recurrencePattern.Interval), TimeZone.CurrentTimeZone, zero); break; case RecurrenceFrequency.Hourly: // 按小时重复先将开始日期前移间隔小时,以判断是否需执行 recurrencePattern = Create(pattern, recurrenceStartTime.AddHours(-1 * recurrencePattern.Interval), TimeZone.CurrentTimeZone, zero); break; case RecurrenceFrequency.Daily: // 按日重复先将开始日期前移间隔天,以判断是否需执行 recurrencePattern = Create(pattern, recurrenceStartTime.AddDays(-1 * recurrencePattern.Interval), TimeZone.CurrentTimeZone, zero); break; case RecurrenceFrequency.Weekly: // 按周重复先将开始日期前移间隔周,以判断是否需执行 recurrencePattern = Create(pattern, recurrenceStartTime.AddDays(-7 * recurrencePattern.Interval), TimeZone.CurrentTimeZone, zero); break; case RecurrenceFrequency.Yearly: // 按年重复先将开始日期前移间隔年,以判断是否需执行 recurrencePattern = Create(pattern, recurrenceStartTime.AddYears(-1 * recurrencePattern.Interval), TimeZone.CurrentTimeZone, zero); break; default: return false; } TimeSpan duration = TimeSpan.FromDays(4000.0); TimeInterval scope = new TimeInterval(recurrenceStartTime, duration); IEnumerable instances = recurrencePattern.GetInstances(scope, 4000); IEnumerator enumerator = instances.GetEnumerator(); while (enumerator != null && enumerator.MoveNext()) { TimeInterval timeInterval = (TimeInterval)enumerator.Current; if (timeInterval.Start > now) { return false; } if (timeInterval.Start == now) { return true; } } return false; }
/// <summary> /// Initializes a new instance of the <see cref="RecurrenceInstances"/> class. /// </summary> /// <param name="pattern">The pattern.</param> /// <param name="scope">The scope.</param> /// <param name="maxInstances">The maximum instances.</param> public RecurrenceInstances(IRecurrencePattern pattern, TimeInterval scope, int maxInstances) { AsyncServiceException.ThrowIfNull(pattern, "pattern"); AsyncServiceException.ThrowIfNotPositive(maxInstances, "maxInstances"); this._pattern = pattern; this._scope = scope; this._maxInstances = maxInstances; }
/// <summary> /// Initializes a new instance of the <see cref="RecurrenceExpander"/> class. /// </summary> /// <param name="pattern">The pattern.</param> /// <param name="scope">The scope.</param> /// <param name="maxInstances">The maximum instances.</param> public RecurrenceExpander(IRecurrencePattern pattern, TimeInterval scope, int maxInstances) { AsyncServiceException.ThrowIfNull(pattern, "pattern"); AsyncServiceException.ThrowIfNegative(maxInstances, "maxInstances"); this._pattern = pattern; // 取消多时区支持 //this._scope = new TimeInterval(pattern.TimeZone.ToLocalTime(scope.Start), scope.IsStartInclusive, pattern.TimeZone.ToLocalTime(scope.End), scope.IsEndInclusive); this._scope = new TimeInterval(scope.Start, scope.IsStartInclusive, scope.End, scope.IsEndInclusive); this._maxInstances = maxInstances; DateTime windowStart = this._pattern.PatternStart; if (this._pattern.Count == 0 && this._scope.Start - this._pattern.Duration > this._pattern.PatternStart) { windowStart = this._scope.Start - this._pattern.Duration; } this._generator = RecurrenceFactory.Create(this._pattern, windowStart); this._expandedInstances = 0; }
/// <summary> /// Orders the intervals. /// </summary> /// <param name="first">The first.</param> /// <param name="second">The second.</param> private static void OrderIntervals(ref TimeInterval first, ref TimeInterval second) { if (first.Start > second.Start || (first.Start == second.Start && !first.IsStartInclusive)) { TimeInterval timeInterval = first; first = second; second = timeInterval; } }
/// <summary> /// Intersectses the with implied order. /// </summary> /// <param name="first">The first.</param> /// <param name="second">The second.</param> /// <returns></returns> internal static bool IntersectsWithImpliedOrder(TimeInterval first, TimeInterval second) { Trace.Assert(first.Start <= second.Start, "first.Start必须小于等于second.Start"); return second.Start < first.End || (second.Start == first.End && first.IsEndInclusive && second.IsStartInclusive); }
/// <summary> /// Intersects the specified first. /// </summary> /// <param name="first">The first.</param> /// <param name="second">The second.</param> /// <returns></returns> public static TimeInterval Intersect(TimeInterval first, TimeInterval second) { TimeInterval.OrderIntervals(ref first, ref second); if (TimeInterval.IntersectsWithImpliedOrder(first, second)) { return new TimeInterval( TimeInterval.QualifiedDateTime.Later(first.QualifiedStart, second.QualifiedStart, false), TimeInterval.QualifiedDateTime.Earlier(first.QualifiedEnd, second.QualifiedEnd, false)); } return TimeInterval.Empty; }
/// <summary> /// Nexts the occurrence. /// </summary> /// <param name="pattern">The pattern.</param> /// <param name="recurrenceStartTime">The recurrence start time.</param> /// <returns></returns> internal static DateTime NextOccurrence(string pattern, DateTime recurrenceStartTime) { AsyncServiceException.ThrowIfNull(pattern, "RecurrencePattern"); TimeSpan zero = TimeSpan.Zero; IRecurrencePattern recurrencePattern = Create(pattern, recurrenceStartTime, TimeZone.CurrentTimeZone, zero); TimeSpan duration = TimeSpan.FromDays(4000.0); TimeInterval scope = new TimeInterval(DateTime.Now, duration); IEnumerable instances = recurrencePattern.GetInstances(scope, 1); IEnumerator enumerator = instances.GetEnumerator(); if (enumerator != null && enumerator.MoveNext()) { TimeInterval timeInterval = (TimeInterval)enumerator.Current; return timeInterval.Start; } return DateTime.MinValue; }
/// <summary> /// Prevents a default instance of the <see cref="TimeInterval"/> struct from being created. /// </summary> /// <param name="start">The start.</param> /// <param name="end">The end.</param> private TimeInterval(TimeInterval.QualifiedDateTime start, TimeInterval.QualifiedDateTime end) { this = new TimeInterval(start.DateTime, start.Inclusive, end.DateTime, end.Inclusive); }
/// <summary> /// Compares the specified left. /// </summary> /// <param name="left">The left.</param> /// <param name="right">The right.</param> /// <returns></returns> public override int Compare(TimeInterval left, TimeInterval right) { int num = left.End.CompareTo(right.End); if (num == 0 && left.IsEndInclusive != right.IsEndInclusive) { num = (left.IsEndInclusive ? 1 : -1); } return num; }
/// <summary> /// Tests the flags. /// </summary> /// <param name="flags">The flags.</param> /// <returns></returns> private bool TestFlags(TimeInterval.TimeIntervalFlags flags) { return (this._flags & flags) != TimeInterval.TimeIntervalFlags.None; }
/// <summary> /// Equalses the specified utility. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool Equals(TimeInterval ti) { return this.Start == ti.Start && this.End == ti.End && this.IsStartInclusive == ti.IsStartInclusive && this.IsEndInclusive == ti.IsEndInclusive; }
/// <summary> /// Initializes a new instance of the <see cref="TimeInterval"/> struct. /// </summary> /// <param name="startTime">The start time.</param> /// <param name="duration">The duration.</param> public TimeInterval(DateTime startTime, TimeSpan duration) { this = new TimeInterval(startTime, startTime + duration); }
/// <summary> /// Endses the attribute. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool EndsAt(TimeInterval ti) { return this.End == ti.End && this.IsEndInclusive == ti.IsEndInclusive; }
/// <summary> /// Determines whether [contains] [the specified utility]. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool Contains(TimeInterval ti) { return ti.Start >= this.Start && ti.End <= this.End && (!(ti.Start == this.Start) || this.IsStartInclusive || !ti.IsStartInclusive) && (!(ti.End == this.End) || this.IsEndInclusive || !ti.IsEndInclusive); }
/// <summary> /// Befores the specified utility. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool Before(TimeInterval ti) { return this.End < ti.Start || (this.End == ti.Start && (!this.IsEndInclusive || !ti.IsStartInclusive)); }
/// <summary> /// Afters the specified utility. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool After(TimeInterval ti) { return this.Start > ti.End || (this.Start == ti.End && (!this.IsStartInclusive || !ti.IsEndInclusive)); }
/// <summary> /// Adjacents the automatic. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool AdjacentTo(TimeInterval ti) { return this.Precedes(ti) || this.Follows(ti); }
/// <summary> /// Initializes a new instance of the <see cref="TimeInterval"/> struct. /// </summary> /// <param name="moment">The moment.</param> public TimeInterval(DateTime moment) { this = new TimeInterval(moment, true, moment, true); }
private void SetFlags(TimeInterval.TimeIntervalFlags flags, bool on) { if (on) { this._flags |= flags; return; } this._flags &= ~flags; }
/// <summary> /// Followses the specified utility. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool Follows(TimeInterval ti) { return this.Start == ti.End && (ti.IsEndInclusive ^ this.IsStartInclusive); }
/// <summary> /// Get Later of two QualifiedDateTime /// </summary> /// <param name="moment0">The moment0.</param> /// <param name="moment1">The moment1.</param> /// <param name="preferInclusive">if set to <c>true</c> [prefer inclusive].</param> /// <returns></returns> public static TimeInterval.QualifiedDateTime Later(TimeInterval.QualifiedDateTime moment0, TimeInterval.QualifiedDateTime moment1, bool preferInclusive) { if (moment0.DateTime > moment1.DateTime) { return moment0; } if (moment0.DateTime == moment1.DateTime && preferInclusive == moment0.Inclusive) { return moment0; } return moment1; }
/// <summary> /// Intersectses the with. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool IntersectsWith(TimeInterval ti) { TimeInterval first = this; TimeInterval.OrderIntervals(ref first, ref ti); return TimeInterval.IntersectsWithImpliedOrder(first, ti); }
/// <summary> /// Compares the specified left. /// </summary> /// <param name="left">The left.</param> /// <param name="right">The right.</param> /// <returns></returns> public override int Compare(TimeInterval left, TimeInterval right) { int num = left.Start.CompareTo(right.Start); if (num == 0 && left.IsStartInclusive != right.IsStartInclusive) { num = (left.IsStartInclusive ? -1 : 1); } return num; }
/// <summary> /// Precedeses the specified utility. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool Precedes(TimeInterval ti) { return this.End == ti.Start && (this.IsEndInclusive ^ ti.IsStartInclusive); }
/// <summary> /// Compares the specified left. /// </summary> /// <param name="left">The left.</param> /// <param name="right">The right.</param> /// <returns></returns> public abstract int Compare(TimeInterval left, TimeInterval right);
/// <summary> /// Gets the instances. /// </summary> /// <param name="scope">The scope.</param> /// <param name="maxInstances">The maximum instances.</param> /// <returns></returns> public IEnumerable GetInstances(TimeInterval scope, int maxInstances) { return new RecurrenceInstances(this, scope, maxInstances); }
/// <summary> /// Startses the attribute. /// </summary> /// <param name="ti">The utility.</param> /// <returns></returns> public bool StartsAt(TimeInterval ti) { return this.Start == ti.Start && this.IsStartInclusive == ti.IsStartInclusive; }
/// <summary> /// Creates the comparer. /// </summary> /// <param name="comparer">The comparer.</param> /// <returns></returns> /// <exception cref="ArgumentOutOfRangeException">comparer;TimeInterval.CreateComparer被传入错误的参数,请确保参数是TimeInterval.Comparer枚举值。</exception> public static ITimeIntervalComparer CreateComparer(TimeInterval.ComparerType comparer) { switch (comparer) { case TimeInterval.ComparerType.StartTime: return new TimeInterval.StartTimeComparer(); case TimeInterval.ComparerType.EndTime: return new TimeInterval.EndTimeComparer(); default: throw new ArgumentOutOfRangeException("comparer", comparer, "TimeInterval.CreateComparer被传入错误的参数,请确保参数是TimeInterval.Comparer枚举值。"); } }
/// <summary> /// Initializes a new instance of the <see cref="TimeInterval"/> struct. /// </summary> /// <param name="startTime">The start time.</param> /// <param name="endTime">The end time.</param> public TimeInterval(DateTime startTime, DateTime endTime) { this = new TimeInterval(startTime, startTime != DateTime.MinValue, endTime, startTime == endTime); }
/// <summary> /// Documents the move next. /// </summary> /// <returns></returns> /// <exception cref="System.InvalidOperationException"></exception> protected override bool DoMoveNext() { while (this._pattern.Count <= 0 || this._expandedInstances < this._pattern.Count) { if (!this._generator.MoveNext()) { return false; } if (this._maxInstances > 0) { this._expandedInstances++; if (this._expandedInstances > this._maxInstances) { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "重复扩展超出最大限制的实例数。扩展实例数: {0}, 最大允许实例数: {1}", this._expandedInstances, this._maxInstances)); } } TimeInterval ti = new TimeInterval(this._generator.Current, this._pattern.Duration); if (!this._scope.After(ti)) { return !this._scope.Before(ti); } } return false; }