diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e8bd64c0..a04ee168 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -33,7 +33,7 @@ jobs: - name: Build run: dotnet build --no-restore --configuration Release -p:nowarn=1591 - name: Test - run: dotnet test --no-build --configuration Release --verbosity quiet /p:AltCover=true /p:AltCoverXmlReport="coverage.xml" /p:AltCoverStrongNameKey="../IcalNetStrongnameKey.snk" /p:AltCoverAssemblyExcludeFilter="Ical.Net.Tests|NUnit3.TestAdapter|AltCover" /p:AltCoverAttributeFilter="ExcludeFromCodeCoverage" /p:AltCoverLineCover="false" + run: dotnet test --no-build --configuration Release --verbosity normal /p:AltCover=true /p:AltCoverXmlReport="coverage.xml" /p:AltCoverStrongNameKey="../IcalNetStrongnameKey.snk" /p:AltCoverAssemblyExcludeFilter="Ical.Net.Tests|NUnit3.TestAdapter|AltCover" /p:AltCoverAttributeFilter="ExcludeFromCodeCoverage" /p:AltCoverLineCover="false" - name: Store coverage report as artifact uses: actions/upload-artifact@v4 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 137a393e..c28041f3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,4 +31,4 @@ jobs: - name: Build run: dotnet build --no-restore --configuration Release -p:nowarn=1591 - name: Test - run: dotnet test --no-build --configuration Release --verbosity quiet + run: dotnet test --no-build --configuration Release --verbosity normal diff --git a/Ical.Net.Tests/RecurrenceTests.cs b/Ical.Net.Tests/RecurrenceTests.cs index 03998218..862a5bec 100644 --- a/Ical.Net.Tests/RecurrenceTests.cs +++ b/Ical.Net.Tests/RecurrenceTests.cs @@ -30,6 +30,10 @@ int eventIndex ) { var evt = cal.Events.Skip(eventIndex).First(); + var rule = evt.RecurrenceRules.FirstOrDefault(); +#pragma warning disable 0618 + if (rule != null) rule.RestrictionType = RecurrenceRestrictionType.NoRestriction; +#pragma warning restore 0618 fromDate.AssociatedObject = cal; toDate.AssociatedObject = cal; @@ -37,26 +41,30 @@ int eventIndex .OrderBy(o => o.Period.StartTime) .ToList(); - Assert.That( - occurrences, -Has.Count.EqualTo(dateTimes.Length), - "There should be exactly " + dateTimes.Length + " occurrences; there were " + occurrences.Count); - - if (evt.RecurrenceRules.Count > 0) + Assert.Multiple(() => { - Assert.That(evt.RecurrenceRules, Has.Count.EqualTo(1)); - } + Assert.That( + occurrences, + Has.Count.EqualTo(dateTimes.Length), + "There should have been " + dateTimes.Length + " occurrences; there were " + occurrences.Count); - for (var i = 0; i < dateTimes.Length; i++) - { - // Associate each incoming date/time with the calendar. - dateTimes[i].AssociatedObject = cal; + if (evt.RecurrenceRules.Count > 0) + { + Assert.That(evt.RecurrenceRules, Has.Count.EqualTo(1)); + } + + for (var i = 0; i < dateTimes.Length; i++) + { + // Associate each incoming date/time with the calendar. + dateTimes[i].AssociatedObject = cal; - var dt = dateTimes[i]; - Assert.That(occurrences[i].Period.StartTime, Is.EqualTo(dt), "Event should occur on " + dt); - if (timeZones != null) - Assert.That(dt.TimeZoneName, Is.EqualTo(timeZones[i]), "Event " + dt + " should occur in the " + timeZones[i] + " timezone"); - } + var dt = dateTimes[i]; + Assert.That(occurrences[i].Period.StartTime, Is.EqualTo(dt), "Event should occur on " + dt); + if (timeZones != null) + Assert.That(dt.TimeZoneName, Is.EqualTo(timeZones[i]), + "Event " + dt + " should occur in the " + timeZones[i] + " timezone"); + } + }); } private void EventOccurrenceTest( @@ -1867,134 +1875,55 @@ public void Bug1741093() ); } - /// - /// Ensures that, by default, SECONDLY recurrence rules are not allowed. - /// - [Test, Category("Recurrence")] - public void Secondly1() - { - Assert.That(() => - { - var iCal = Calendar.Load(IcsFiles.Secondly1); - _ = iCal.GetOccurrences(new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), new CalDateTime(2007, 7, 21, 8, 0, 0, _tzid)); - }, Throws.Exception.TypeOf(), "Evaluation engine should have failed."); - } - - /// - /// Ensures that the proper behavior occurs when the evaluation - /// mode is set to adjust automatically for SECONDLY evaluation - /// [Test, Category("Recurrence")] - public void Secondly1_1() + public void Secondly_DefinedNumberOfOccurrences_ShouldSucceed() { var iCal = Calendar.Load(IcsFiles.Secondly1); - iCal.RecurrenceEvaluationMode = RecurrenceEvaluationModeType.AdjustAutomatically; - EventOccurrenceTest( - iCal, - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 10, 1, _tzid), // End period is exclusive, not inclusive. - new[] - { - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 1, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 2, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 3, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 4, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 5, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 6, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 7, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 8, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 9, 0, _tzid), - new CalDateTime(2007, 6, 21, 8, 10, 0, _tzid) - }, - null - ); - } + var start = new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid); + var end = new CalDateTime(2007, 6, 21, 8, 1, 0, _tzid); // End period is exclusive, not inclusive. - /// - /// Ensures that if configured, MINUTELY recurrence rules are not allowed. - /// - [Test, Category("Recurrence")] - public void Minutely1() - { - Assert.That(() => + var dateTimes = new List(); + for (var dt = start; dt.LessThan(end); dt = (CalDateTime) dt.AddSeconds(1)) { - var iCal = Calendar.Load(IcsFiles.Minutely1); - iCal.RecurrenceRestriction = RecurrenceRestrictionType.RestrictMinutely; - var occurrences = iCal.GetOccurrences( - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 21, 8, 0, 0, _tzid)); - }, Throws.Exception.TypeOf()); + dateTimes.Add(new CalDateTime(dt)); + } + + EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); } - /// - /// Ensures that the proper behavior occurs when the evaluation - /// mode is set to adjust automatically for MINUTELY evaluation - /// [Test, Category("Recurrence")] - public void Minutely1_1() + public void Minutely_DefinedNumberOfOccurrences_ShouldSucceed() { var iCal = Calendar.Load(IcsFiles.Minutely1); - iCal.RecurrenceRestriction = RecurrenceRestrictionType.RestrictMinutely; - iCal.RecurrenceEvaluationMode = RecurrenceEvaluationModeType.AdjustAutomatically; - EventOccurrenceTest( - iCal, - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 12, 0, 1, _tzid), // End period is exclusive, not inclusive. - new[] - { - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 9, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 10, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 11, 0, 0, _tzid), - new CalDateTime(2007, 6, 21, 12, 0, 0, _tzid) - }, - null - ); - } + var start = new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid); + var end = new CalDateTime(2007, 6, 21, 12, 0, 1, _tzid); // End period is exclusive, not inclusive. - /// - /// Ensures that if configured, HOURLY recurrence rules are not allowed. - /// - [Test, Category("Recurrence")/*, ExpectedException(typeof(EvaluationEngineException))*/] - public void Hourly1() - { - Assert.That(() => + var dateTimes = new List(); + for (var dt = start; dt.LessThan(end); dt = (CalDateTime)dt.AddMinutes(1)) { - var iCal = Calendar.Load(IcsFiles.Hourly1); - iCal.RecurrenceRestriction = RecurrenceRestrictionType.RestrictHourly; - _ = iCal.GetOccurrences(new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), new CalDateTime(2007, 7, 21, 8, 0, 0, _tzid)); + dateTimes.Add(new CalDateTime(dt)); + } - }, Throws.Exception.TypeOf()); + EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); } - /// - /// Ensures that the proper behavior occurs when the evaluation - /// mode is set to adjust automatically for HOURLY evaluation - /// [Test, Category("Recurrence")] - public void Hourly1_1() + public void Hourly_DefinedNumberOfOccurrences_ShouldSucceed() { var iCal = Calendar.Load(IcsFiles.Hourly1); - iCal.RecurrenceRestriction = RecurrenceRestrictionType.RestrictHourly; - iCal.RecurrenceEvaluationMode = RecurrenceEvaluationModeType.AdjustAutomatically; - EventOccurrenceTest( - iCal, - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 25, 8, 0, 1, _tzid), // End period is exclusive, not inclusive. - new[] - { - new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 22, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 23, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 24, 8, 0, 0, _tzid), - new CalDateTime(2007, 6, 25, 8, 0, 0, _tzid) - }, - null - ); + var start = new CalDateTime(2007, 6, 21, 8, 0, 0, _tzid); + var end = new CalDateTime(2007, 6, 25, 8, 0, 1, _tzid); // End period is exclusive, not inclusive. + + var dateTimes = new List(); + for (var dt = start; dt.LessThan(end); dt = (CalDateTime)dt.AddHours(1)) + { + dateTimes.Add(new CalDateTime(dt)); + } + + EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); } /// @@ -2038,7 +1967,7 @@ public void YearlyInterval1() } /// - /// Ensures that "off-day" calcuation works correctly + /// Ensures that "off-day" calculation works correctly /// [Test, Category("Recurrence")] public void DailyInterval1() @@ -2841,10 +2770,10 @@ public void Evaluate1(string freq, int secsPerInterval, bool hasTime) // This case (DTSTART of type DATE and FREQ=MINUTELY) is undefined in RFC 5545. // ical.net handles the case by pretending DTSTART has the time set to midnight. - evt.RecurrenceRules.Add(new RecurrencePattern($"FREQ={freq};INTERVAL=10;COUNT=5") - { - RestrictionType = RecurrenceRestrictionType.NoRestriction, - }); + evt.RecurrenceRules.Add(new RecurrencePattern($"FREQ={freq};INTERVAL=10;COUNT=5")); +#pragma warning disable 0618 + evt.RecurrenceRules[0].RestrictionType = RecurrenceRestrictionType.NoRestriction; +#pragma warning restore 0618 var occurrences = evt.GetOccurrences(CalDateTime.Today.AddDays(-1), CalDateTime.Today.AddDays(100)) .OrderBy(x => x) @@ -2868,8 +2797,10 @@ public void RecurrencePattern1() { // NOTE: evaluators are not generally meant to be used directly like this. // However, this does make a good test to ensure they behave as they should. - RecurrencePattern pattern = new RecurrencePattern("FREQ=SECONDLY;INTERVAL=10"); + var pattern = new RecurrencePattern("FREQ=SECONDLY;INTERVAL=10"); +#pragma warning disable 0618 pattern.RestrictionType = RecurrenceRestrictionType.NoRestriction; +#pragma warning restore 0618 var us = new CultureInfo("en-US"); @@ -3177,10 +3108,14 @@ public void OccurrenceMustBeCompletelyContainedWithinSearchRange() Assert.That(occurrences.Last().StartTime.Equals(lastExpected), Is.True); } - [Test, Ignore("Turn on in v3")] + /// + /// Evaluate relevancy and validity of the request. + /// Find a solution for issue #120 or close forever + /// + [Test, Ignore("Turn on in v3", Until = "2024-12-31")] public void EventsWithShareUidsShouldGenerateASingleRecurrenceSet() { - //https://github.com/rianjs/ical.net/issues/120 + //https://github.com/rianjs/ical.net/issues/120 dated Sep 5, 2016 const string ical = @"BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN @@ -3757,7 +3692,9 @@ private static IEnumerable TestLibicalTestCasesSource [TestCaseSource(nameof(TestLibicalTestCasesSource))] public void TestLibicalTestCases(RecurrenceTestCase testCase) - => ExecuteRecurrenceTestCase(testCase); + { + ExecuteRecurrenceTestCase(testCase); + } private static IEnumerable TestFileBasedRecurrenceTestCaseSource => ParseTestCaseFile(IcsFiles.RecurrrenceTestCases); @@ -3775,10 +3712,7 @@ public void ExecuteRecurrenceTestCase(RecurrenceTestCase testCase) // Start at midnight, UTC time evt.Start = testCase.DtStart; - evt.RecurrenceRules.Add(new RecurrencePattern(testCase.RRule) - { - RestrictionType = RecurrenceRestrictionType.NoRestriction, - }); + evt.RecurrenceRules.Add(new RecurrencePattern(testCase.RRule)); var occurrences = evt.GetOccurrences(testCase.StartAt?.Value ?? DateTime.MinValue, DateTime.MaxValue) .OrderBy(x => x) diff --git a/Ical.Net/Calendar.cs b/Ical.Net/Calendar.cs index 47248aa6..95623aaf 100644 --- a/Ical.Net/Calendar.cs +++ b/Ical.Net/Calendar.cs @@ -26,7 +26,7 @@ public static Calendar Load(Stream s) => CalendarCollection.Load(new StreamReader(s, Encoding.UTF8)).SingleOrDefault(); public static Calendar Load(TextReader tr) - => CalendarCollection.Load(tr).OfType().SingleOrDefault(); + => CalendarCollection.Load(tr)?.SingleOrDefault(); public static IList Load(Stream s, Encoding e) => Load(new StreamReader(s, e)); @@ -118,7 +118,7 @@ public override int GetHashCode() public virtual IEnumerable RecurringItems => Children.OfType(); /// - /// A collection of components in the iCalendar. + /// A collection of components in the iCalendar. /// public virtual IUniqueComponentList Events => _mEvents; @@ -166,12 +166,14 @@ public virtual string Method set => Properties.Set("METHOD", value); } + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public virtual RecurrenceRestrictionType RecurrenceRestriction { get => Properties.Get("X-DDAY-ICAL-RECURRENCE-RESTRICTION"); set => Properties.Set("X-DDAY-ICAL-RECURRENCE-RESTRICTION", value); } + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public virtual RecurrenceEvaluationModeType RecurrenceEvaluationMode { get => Properties.Get("X-DDAY-ICAL-RECURRENCE-EVALUATION-MODE"); @@ -190,34 +192,6 @@ public VTimeZone AddTimeZone(VTimeZone tz) return tz; } - /// - /// Evaluates component recurrences for the given range of time. - /// - /// For example, if you are displaying a month-view for January 2007, - /// you would want to evaluate recurrences for Jan. 1, 2007 to Jan. 31, 2007 - /// to display relevant information for those dates. - /// - /// - /// The beginning date/time of the range to test. - /// The end date/time of the range to test. - [Obsolete("This method is no longer supported. Use GetOccurrences() instead.")] - public void Evaluate(IDateTime fromDate, IDateTime toDate) - { - throw new NotSupportedException("Evaluate() is no longer supported as a public method. Use GetOccurrences() instead."); - } - - /// - /// Evaluates component recurrences for the given range of time, for - /// the type of recurring component specified. - /// - /// The type of component to be evaluated for recurrences. - /// The beginning date/time of the range to test. - /// The end date/time of the range to test. - [Obsolete("This method is no longer supported. Use GetOccurrences() instead.")] - public void Evaluate(IDateTime fromDate, IDateTime toDate) - { - throw new NotSupportedException("Evaluate() is no longer supported as a public method. Use GetOccurrences() instead."); - } /// /// Clears recurrence evaluations for recurring components. @@ -237,8 +211,9 @@ public void ClearEvaluation() /// The date for which to return occurrences. Time is ignored on this parameter. /// A list of occurrences that occur on the given date (). public virtual HashSet GetOccurrences(IDateTime dt) - => GetOccurrences(new CalDateTime(dt.AsSystemLocal.Date), new CalDateTime(dt.AsSystemLocal.Date.AddDays(1).AddSeconds(-1))); + => GetOccurrences(new CalDateTime(dt.Date), new CalDateTime(dt.Date.AddDays(1).AddSeconds(-1))); + /// public virtual HashSet GetOccurrences(DateTime dt) => GetOccurrences(new CalDateTime(dt.Date), new CalDateTime(dt.Date.AddDays(1).AddSeconds(-1))); @@ -248,10 +223,11 @@ public virtual HashSet GetOccurrences(DateTime dt) /// /// The beginning date/time of the range. /// The end date/time of the range. - /// A list of occurrences that fall between the dates provided. + /// A list of occurrences that fall between the date/time arguments provided. public virtual HashSet GetOccurrences(IDateTime startTime, IDateTime endTime) => GetOccurrences(startTime, endTime); + /// public virtual HashSet GetOccurrences(DateTime startTime, DateTime endTime) => GetOccurrences(new CalDateTime(startTime), new CalDateTime(endTime)); @@ -265,14 +241,19 @@ public virtual HashSet GetOccurrences(DateTime startTime, DateTime e /// the occurrences. /// /// - /// The date for which to return occurrences. + /// The date for which to return occurrences. Time is ignored on this parameter. /// A list of Periods representing the occurrences of this object. public virtual HashSet GetOccurrences(IDateTime dt) where T : IRecurringComponent - => GetOccurrences(new CalDateTime(dt.AsSystemLocal.Date), new CalDateTime(dt.AsSystemLocal.Date.AddDays(1).AddTicks(-1))); + => GetOccurrences(new CalDateTime(dt.Date), new CalDateTime(dt.Date.AddDays(1).AddTicks(-1))); + /// public virtual HashSet GetOccurrences(DateTime dt) where T : IRecurringComponent => GetOccurrences(new CalDateTime(dt.Date), new CalDateTime(dt.Date.AddDays(1).AddTicks(-1))); + /// + public virtual HashSet GetOccurrences(DateTime startTime, DateTime endTime) where T : IRecurringComponent + => GetOccurrences(new CalDateTime(startTime), new CalDateTime(endTime)); + /// /// Returns all occurrences of components of type T that start within the date range provided. /// All components occurring between and @@ -298,9 +279,6 @@ public virtual HashSet GetOccurrences(IDateTime startTime, IDateT return occurrences; } - public virtual HashSet GetOccurrences(DateTime startTime, DateTime endTime) where T : IRecurringComponent - => GetOccurrences(new CalDateTime(startTime), new CalDateTime(endTime)); - /// /// Creates a typed object that is a direct child of the iCalendar itself. Generally, /// you would invoke this method to create an Event, Todo, Journal, VTimeZone, FreeBusy, diff --git a/Ical.Net/Constants.cs b/Ical.Net/Constants.cs index 062b27e8..0485f61e 100644 --- a/Ical.Net/Constants.cs +++ b/Ical.Net/Constants.cs @@ -219,6 +219,7 @@ public enum FrequencyOccurrence Fifth = 5 } + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public enum RecurrenceRestrictionType { /// @@ -247,6 +248,7 @@ public enum RecurrenceRestrictionType RestrictHourly } + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public enum RecurrenceEvaluationModeType { /// diff --git a/Ical.Net/DataTypes/RecurrencePattern.cs b/Ical.Net/DataTypes/RecurrencePattern.cs index bde5ebff..86500cef 100644 --- a/Ical.Net/DataTypes/RecurrencePattern.cs +++ b/Ical.Net/DataTypes/RecurrencePattern.cs @@ -15,9 +15,10 @@ namespace Ical.Net.DataTypes public class RecurrencePattern : EncodableDataType { private int _interval = int.MinValue; +#pragma warning disable 0618 private RecurrenceRestrictionType? _restrictionType; private RecurrenceEvaluationModeType? _evaluationMode; - +#pragma warning restore 0618 public FrequencyType Frequency { get; set; } private DateTime _until = DateTime.MinValue; @@ -84,6 +85,12 @@ public int Interval public DayOfWeek FirstDayOfWeek { get; set; } = DayOfWeek.Monday; +#pragma warning disable 0618 + /// + /// The type of restriction to apply to the evaluation of this recurrence pattern. + /// Returns if not set. + /// + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public RecurrenceRestrictionType RestrictionType { get @@ -98,6 +105,7 @@ public RecurrenceRestrictionType RestrictionType set => _restrictionType = value; } + [Obsolete("Usage may cause undesired results or exceptions. Will be removed.", false)] public RecurrenceEvaluationModeType EvaluationMode { get @@ -111,6 +119,7 @@ public RecurrenceEvaluationModeType EvaluationMode } set => _evaluationMode = value; } +#pragma warning restore 0618 public RecurrencePattern() { @@ -142,8 +151,10 @@ public override string ToString() } protected bool Equals(RecurrencePattern other) => (Interval == other.Interval) +#pragma warning disable 0618 && RestrictionType == other.RestrictionType && EvaluationMode == other.EvaluationMode +#pragma warning restore 0618 && Frequency == other.Frequency && Until.Equals(other.Until) && Count == other.Count @@ -170,8 +181,10 @@ public override int GetHashCode() unchecked { var hashCode = Interval.GetHashCode(); +#pragma warning disable 0618 hashCode = (hashCode * 397) ^ RestrictionType.GetHashCode(); hashCode = (hashCode * 397) ^ EvaluationMode.GetHashCode(); +#pragma warning restore 0618 hashCode = (hashCode * 397) ^ (int)Frequency; hashCode = (hashCode * 397) ^ Until.GetHashCode(); hashCode = (hashCode * 397) ^ Count; @@ -212,8 +225,10 @@ public override void CopyFrom(ICopyable obj) ByMonth = new List(r.ByMonth); BySetPosition = new List(r.BySetPosition); FirstDayOfWeek = r.FirstDayOfWeek; +#pragma warning disable 0618 RestrictionType = r.RestrictionType; EvaluationMode = r.EvaluationMode; +#pragma warning restore 0618 } private static bool CollectionEquals(IEnumerable c1, IEnumerable c2) => c1.SequenceEqual(c2); diff --git a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs index f91a644f..c949f1c8 100644 --- a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs +++ b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs @@ -48,7 +48,6 @@ namespace Ical.Net.Evaluation /// public class RecurrencePatternEvaluator : Evaluator { - // FIXME: in ical4j this is configurable. private const int _maxIncrementCount = 1000; protected RecurrencePattern Pattern { get; set; } @@ -136,7 +135,7 @@ private RecurrencePattern ProcessRecurrencePattern(IDateTime referenceDate) return r; } - +#pragma warning disable 0618 private void EnforceEvaluationRestrictions(RecurrencePattern pattern) { RecurrenceEvaluationModeType? evaluationMode = pattern.EvaluationMode; @@ -231,17 +230,16 @@ private void EnforceEvaluationRestrictions(RecurrencePattern pattern) } } } - - /** - * Returns a list of start dates in the specified period represented by this recur. This method includes a base date - * argument, which indicates the start of the fist occurrence of this recurrence. The base date is used to inject - * default values to return a set of dates in the correct format. For example, if the search start date (start) is - * Wed, Mar 23, 12:19PM, but the recurrence is Mon - Fri, 9:00AM - 5:00PM, the start dates returned should all be at - * 9:00AM, and not 12:19PM. - */ - +#pragma warning 0618 restore + /// + /// Returns a list of start dates in the specified period represented by this recurrence pattern. + /// This method includes a base date argument, which indicates the start of the first occurrence of this recurrence. + /// The base date is used to inject default values to return a set of dates in the correct format. + /// For example, if the search start date (start) is Wed, Mar 23, 12:19PM, but the recurrence is Mon - Fri, 9:00AM - 5:00PM, + /// the start dates returned should all be at 9:00AM, and not 12:19PM. + /// private HashSet GetDates(IDateTime seed, DateTime periodStart, DateTime periodEnd, int maxCount, RecurrencePattern pattern, - bool includeReferenceDateInResults) + bool includeReferenceDateInResults) { var dates = new HashSet(); var originalDate = DateUtil.GetSimpleDateTimeData(seed); @@ -331,13 +329,13 @@ private HashSet GetDates(IDateTime seed, DateTime periodStart, DateTim return dates; } - /** - * Returns a list of possible dates generated from the applicable BY* rules, using the specified date as a seed. - * @param date the seed date - * @param value the type of date list to return - * @return a DateList - */ - + /// + /// Returns a list of possible dates generated from the applicable BY* rules, using the specified date as a seed. + /// + /// The seed date. + /// + /// + /// A list of possible dates. private List GetCandidates(DateTime date, RecurrencePattern pattern, bool?[] expandBehaviors) { var dates = new List { date }; @@ -353,11 +351,12 @@ private List GetCandidates(DateTime date, RecurrencePattern pattern, b return dates; } - /** - * Applies BYSETPOS rules to dates. Valid positions are from 1 to the size of the date list. Invalid - * positions are ignored. - * @param dates - */ + /// + /// Applies BYSETPOS rules to . Valid positions are from 1 to the size of the date list. Invalid + /// positions are ignored. + /// + /// The list of dates to which the BYSETPOS rules will be applied. + /// private List ApplySetPosRules(List dates, RecurrencePattern pattern) { // return if no SETPOS rules specified.. @@ -379,12 +378,14 @@ private List ApplySetPosRules(List dates, RecurrencePattern return setPosDates; } - /** - * Applies BYMONTH rules specified in this Recur instance to the specified date list. If no BYMONTH rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ + /// + /// Applies BYMONTH rules specified in this Recur instance to the specified date list. + /// If no BYMONTH rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYMONTH rules will be applied. + /// + /// + /// The modified list of dates after applying the BYMONTH rules. private List GetMonthVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByMonth.Count == 0) @@ -406,12 +407,12 @@ private List GetMonthVariants(List dates, RecurrencePattern return dateSet.ToList(); } - /** - * Applies BYWEEKNO rules specified in this Recur instance to the specified date list. If no BYWEEKNO rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ + /// + /// Applies BYWEEKNO rules specified in this Recur instance to the specified date list. + /// If no BYWEEKNO rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYWEEKNO rules will be applied. + /// The modified list of dates after applying the BYWEEKNO rules. private List GetWeekNoVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByWeekNo.Count == 0) @@ -462,13 +463,12 @@ private List GetWeekNoVariants(List dates, RecurrencePattern return weekNoDates; } - /** - * Applies BYYEARDAY rules specified in this Recur instance to the specified date list. If no BYYEARDAY rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYYEARDAY rules specified in this Recur instance to the specified date list. + /// If no BYYEARDAY rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYYEARDAY rules will be applied. + /// The modified list of dates after applying the BYYEARDAY rules. private List GetYearDayVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByYearDay.Count == 0) @@ -516,13 +516,12 @@ private List GetYearDayVariants(List dates, RecurrencePatter return dates; } - /** - * Applies BYMONTHDAY rules specified in this Recur instance to the specified date list. If no BYMONTHDAY rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYMONTHDAY rules specified in this Recur instance to the specified date list. + /// If no BYMONTHDAY rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYMONTHDAY rules will be applied. + /// The modified list of dates after applying the BYMONTHDAY rules. private List GetMonthDayVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByMonthDay.Count == 0) @@ -571,20 +570,19 @@ select monthDay > 0 } } - Next: + Next: dates.RemoveAt(i); } return dates; } - /** - * Applies BYDAY rules specified in this Recur instance to the specified date list. If no BYDAY rules are specified - * the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYDAY rules specified in this Recur instance to the specified date list. + /// If no BYDAY rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which BYDAY rules will be applied. + /// The modified list of dates after applying BYDAY rules, or the original list if no BYDAY rules are specified. private List GetDayVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByDay.Count == 0) @@ -632,14 +630,13 @@ private List GetDayVariants(List dates, RecurrencePattern pa return dates; } - /** - * Returns a list of applicable dates corresponding to the specified week day in accordance with the frequency - * specified by this recurrence rule. - * @param date - * @param weekDay - * @return - */ - + /// + /// Returns a list of applicable dates corresponding to the specified week day in accordance with the frequency + /// specified by this recurrence rule. + /// + /// The date to start the evaluation from. + /// The week day to evaluate. + /// A list of applicable dates. private List GetAbsWeekDays(DateTime date, WeekDay weekDay, RecurrencePattern pattern) { var days = new List(); @@ -723,15 +720,13 @@ private List GetAbsWeekDays(DateTime date, WeekDay weekDay, Recurrence return GetOffsetDates(days, weekDay.Offset); } - /** - * Returns a single-element sublist containing the element of list at offset. Valid - * offsets are from 1 to the size of the list. If an invalid offset is supplied, all elements from list - * are added to sublist. - * @param list - * @param offset - * @param sublist - */ - + /// + /// Returns a single-element sublist containing the element of at . + /// Valid offsets are from 1 to the size of the list. If an invalid offset is supplied, all elements from + /// are added to result. + /// + /// The list from which to extract the element. + /// The position of the element to extract. private List GetOffsetDates(List dates, int offset) { if (offset == int.MinValue) @@ -752,13 +747,14 @@ private List GetOffsetDates(List dates, int offset) return offsetDates; } - /** - * Applies BYHOUR rules specified in this Recur instance to the specified date list. If no BYHOUR rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYHOUR rules specified in this Recur instance to the specified date list. + /// If no BYHOUR rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYHOUR rules will be applied. + /// + /// + /// The modified list of dates after applying the BYHOUR rules. private List GetHourVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByHour.Count == 0) @@ -802,13 +798,14 @@ private List GetHourVariants(List dates, RecurrencePattern p return dates; } - /** - * Applies BYMINUTE rules specified in this Recur instance to the specified date list. If no BYMINUTE rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYMINUTE rules specified in this Recur instance to the specified date list. + /// If no BYMINUTE rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYMINUTE rules will be applied. + /// + /// + /// The modified list of dates after applying the BYMINUTE rules. private List GetMinuteVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.ByMinute.Count == 0) @@ -852,13 +849,14 @@ private List GetMinuteVariants(List dates, RecurrencePattern return dates; } - /** - * Applies BYSECOND rules specified in this Recur instance to the specified date list. If no BYSECOND rules are - * specified the date list is returned unmodified. - * @param dates - * @return - */ - + /// + /// Applies BYSECOND rules specified in this Recur instance to the specified date list. + /// If no BYSECOND rules are specified, the date list is returned unmodified. + /// + /// The list of dates to which the BYSECOND rules will be applied. + /// + /// + /// The modified list of dates after applying the BYSECOND rules. private List GetSecondVariants(List dates, RecurrencePattern pattern, bool? expand) { if (expand == null || pattern.BySecond.Count == 0) @@ -927,7 +925,7 @@ private Period CreatePeriod(DateTime dt, IDateTime referenceDate) /// public override HashSet Evaluate(IDateTime referenceDate, DateTime periodStart, DateTime periodEnd, bool includeReferenceDateInResults) { - if ((this.Pattern.Frequency != FrequencyType.None) && (this.Pattern.Frequency < FrequencyType.Daily) && !referenceDate.HasTime) + if (Pattern.Frequency != FrequencyType.None && Pattern.Frequency < FrequencyType.Daily && !referenceDate.HasTime) { // This case is not defined by RFC 5545. We handle it by evaluating the rule // as if referenceDate had a time (i.e. set to midnight). diff --git a/Ical.Net/Evaluation/RecurrenceUtil.cs b/Ical.Net/Evaluation/RecurrenceUtil.cs index 7708e893..6d15c713 100644 --- a/Ical.Net/Evaluation/RecurrenceUtil.cs +++ b/Ical.Net/Evaluation/RecurrenceUtil.cs @@ -15,7 +15,7 @@ public static void ClearEvaluation(IRecurrable recurrable) } public static HashSet GetOccurrences(IRecurrable recurrable, IDateTime dt, bool includeReferenceDateInResults) => GetOccurrences(recurrable, - new CalDateTime(dt.AsSystemLocal.Date), new CalDateTime(dt.AsSystemLocal.Date.AddDays(1).AddSeconds(-1)), includeReferenceDateInResults); + new CalDateTime(dt.Date), new CalDateTime(dt.Date.AddDays(1).AddSeconds(-1)), includeReferenceDateInResults); public static HashSet GetOccurrences(IRecurrable recurrable, IDateTime periodStart, IDateTime periodEnd, bool includeReferenceDateInResults) { diff --git a/Ical.Net/Evaluation/RecurringEvaluator.cs b/Ical.Net/Evaluation/RecurringEvaluator.cs index c435b4a6..1460f562 100644 --- a/Ical.Net/Evaluation/RecurringEvaluator.cs +++ b/Ical.Net/Evaluation/RecurringEvaluator.cs @@ -29,7 +29,7 @@ public RecurringEvaluator(IRecurrable obj) } /// - /// Evaulates the RRule component, and adds each specified Period to the Periods collection. + /// Evaluates the RRule component, and adds each specified Period to the Periods collection. /// /// /// The beginning date of the range to evaluate. @@ -62,7 +62,7 @@ protected HashSet EvaluateRRule(IDateTime referenceDate, DateTime period return periods; } - /// Evalates the RDate component, and adds each specified DateTime or Period to the Periods collection. + /// Evaluates the RDate component, and adds each specified DateTime or Period to the Periods collection. protected HashSet EvaluateRDate(IDateTime referenceDate, DateTime periodStart, DateTime periodEnd) { if (Recurrable.RecurrenceDates == null || !Recurrable.RecurrenceDates.Any()) @@ -75,7 +75,7 @@ protected HashSet EvaluateRDate(IDateTime referenceDate, DateTime period } /// - /// Evaulates the ExRule component, and excludes each specified DateTime from the Periods collection. + /// Evaluates the ExRule component, and excludes each specified DateTime from the Periods collection. /// /// /// The beginning date of the range to evaluate. @@ -102,7 +102,7 @@ protected HashSet EvaluateExRule(IDateTime referenceDate, DateTime perio } /// - /// Evalates the ExDate component, and excludes each specified DateTime or Period from the Periods collection. + /// Evaluates the ExDate component, and excludes each specified DateTime or Period from the Periods collection. /// /// /// The beginning date of the range to evaluate.