diff --git a/v2/Ical.Net.nuspec b/v2/Ical.Net.nuspec index 37d7279c4..b328576c9 100644 --- a/v2/Ical.Net.nuspec +++ b/v2/Ical.Net.nuspec @@ -2,7 +2,7 @@ Ical.Net - 2.2.32 + 2.2.33 Ical.Net Rian Stockbower, Douglas Day, M. David Peterson Rian Stockbower diff --git a/v2/ical.NET.UnitTests/GetOccurrenceTests.cs b/v2/ical.NET.UnitTests/GetOccurrenceTests.cs index 307be8046..1b9fe0e79 100644 --- a/v2/ical.NET.UnitTests/GetOccurrenceTests.cs +++ b/v2/ical.NET.UnitTests/GetOccurrenceTests.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Ical.Net.DataTypes; +using Ical.Net.Interfaces.DataTypes; +using Ical.Net.Utility; using NUnit.Framework; namespace Ical.Net.UnitTests @@ -51,6 +54,44 @@ public void WrongDurationTest() Assert.AreEqual(secondEndCopy, secondOccurrence.Period.EndTime); } + [Test] + public void SkippedOccurrenceOnWeeklyPattern() + { + const int evaluationsCount = 1000; + var eventStart = new CalDateTime(new DateTime(2016, 1, 1, 10, 0, 0, DateTimeKind.Utc)); + var eventEnd = new CalDateTime(new DateTime(2016, 1, 1, 11, 0, 0, DateTimeKind.Utc)); + var vEvent = new Event + { + DtStart = eventStart, + DtEnd = eventEnd, + }; + + var pattern = new RecurrencePattern + { + Frequency = FrequencyType.Weekly, + ByDay = new List { new WeekDay(DayOfWeek.Friday) } + + }; + vEvent.RecurrenceRules.Add(pattern); + var calendar = new Calendar(); + calendar.Events.Add(vEvent); + + var intervalStart = eventStart; + var intervalEnd = intervalStart.AddDays(7 * evaluationsCount); + + var occurrences = RecurrenceUtil.GetOccurrences(vEvent, intervalStart, intervalEnd, false) + .Select(o => o.Period.StartTime) + .OrderBy(dt => dt) + .ToList(); + Assert.AreEqual(evaluationsCount, occurrences.Count); + for (DateTime currentOccurrence = intervalStart.AsUtc; + currentOccurrence.CompareTo(intervalEnd.AsUtc) < 0; currentOccurrence = currentOccurrence.AddDays(7)) + { + Assert.IsTrue(occurrences.Contains(new CalDateTime(currentOccurrence)), + string.Format("Collection does not contain {0}, but it is a {1}", currentOccurrence, currentOccurrence.DayOfWeek)); + } + } + [Test] public void EnumerationChangedException() { diff --git a/v2/ical.NET/Evaluation/RecurrencePatternEvaluator.cs b/v2/ical.NET/Evaluation/RecurrencePatternEvaluator.cs index 408978277..2cf547127 100644 --- a/v2/ical.NET/Evaluation/RecurrencePatternEvaluator.cs +++ b/v2/ical.NET/Evaluation/RecurrencePatternEvaluator.cs @@ -679,10 +679,22 @@ private List GetAbsWeekDays(DateTime date, IWeekDay weekDay, IRecurren date = date.AddDays(1); } - while (Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, pattern.FirstDayOfWeek) == weekNo) + var nextWeekNo = Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, + pattern.FirstDayOfWeek); + + var currentWeekNo = Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, + pattern.FirstDayOfWeek); + while (currentWeekNo == weekNo || + //When we manage weekly recurring pattern and we have boundary case: + //Weekdays: 31.12, 01.01, 02.01, 03.01, 04.01, 05.01, 06.01 + //31.12 - It's a 53th week number, but all another are 1st week number. + //So, we should add exception rule for this situation(only for weekly events). + (nextWeekNo < weekNo && currentWeekNo == nextWeekNo && pattern.Frequency == FrequencyType.Weekly)) { days.Add(date); date = date.AddDays(7); + currentWeekNo = Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, + pattern.FirstDayOfWeek); } } else if (pattern.Frequency == FrequencyType.Monthly || pattern.ByMonth.Count > 0)