From 3e35d537378ef41070037105157f2a3a401d80c4 Mon Sep 17 00:00:00 2001 From: Markus Minichmayr Date: Sat, 28 Dec 2024 19:23:02 +0100 Subject: [PATCH] Introduce `Duration` type to keep apart nominal vs exact durations. (#680) * Make Todo.Duration nullable * Remove Todo.ExtrapolateTimes() * Test: Minor fix related to CalendarEvent.Duration being nullable now * Introduce type `Duration` and replace `TimeSpanSerializer` by `DurationSerializer` in preparation of using the type throughout the lib. * Remove redundant `CalDateTime.Subtract(TimeSpan)`, which can also be written as `CalDateTime.Add(-d)`. * Remove obsolete `DaetUtil.Start/EndOfDay` * Change `CalendarEvent.Duration`, `Todo.Duration`, `Trigger.Duration` from `TimeSpan` to `Duration`. * Rename `CalDateTime.Subtract()` -> `CalDateTime.SubtractExact()` * Change `TimeSpan CalendarEvent.GetTimeSpanToAddToPeriodStartTime()` -> `Duration CalendarEvent.GetEffectiveDuration()`. * Fix date/time arithmetics: Keep apart nominal and exact durations. * CalDateTime doc comments * Change `Period.Duration` from `TimeSpan` to `Duration`. Remove extrapolation and introduce `GetEffectiveDuration()`, `GetEffectiveEndTime()`. * CalDateTimeTests: Indentation and whitespace * Test: Extend RecurrenceTest test cases to test for occurrences durations. * Improve `CalDateTime.ToTimeZone()` conversion of floating time that doesn't exist in the target tz. * RecurrencePatternEvaluator: Adjust nonexistent recurrence instances according to RFC 5545 3.3.5 * Test: DurationOfRecurrencesOverDst * Allow `IDateTime.ToTimeZone` to convert to floating time. * CalendarEvent: Avoid null-reference warnings. --- Ical.Net.Tests/CalDateTimeTests.cs | 71 +- Ical.Net.Tests/CalendarEventTest.cs | 25 +- Ical.Net.Tests/CopyComponentTests.cs | 4 +- Ical.Net.Tests/DeserializationTests.cs | 2 +- Ical.Net.Tests/EqualityAndHashingTests.cs | 4 +- Ical.Net.Tests/PeriodTests.cs | 32 +- Ical.Net.Tests/RecurrenceTests.cs | 1444 +++++++++-------- Ical.Net.Tests/SerializationTests.cs | 6 +- Ical.Net.Tests/SymmetricSerializationTests.cs | 5 +- Ical.Net/CalendarComponents/Alarm.cs | 13 +- Ical.Net/CalendarComponents/CalendarEvent.cs | 24 +- Ical.Net/CalendarComponents/Todo.cs | 42 +- Ical.Net/CalendarComponents/VTimeZone.cs | 4 +- Ical.Net/DataTypes/CalDateTime.cs | 97 +- Ical.Net/DataTypes/CalendarDataType.cs | 4 +- Ical.Net/DataTypes/Duration.cs | 222 +++ Ical.Net/DataTypes/IDateTime.cs | 35 +- Ical.Net/DataTypes/Period.cs | 91 +- Ical.Net/DataTypes/Trigger.cs | 6 +- Ical.Net/Evaluation/EventEvaluator.cs | 18 +- .../Evaluation/RecurrencePatternEvaluator.cs | 6 +- Ical.Net/Evaluation/TodoEvaluator.cs | 8 +- Ical.Net/Serialization/DataTypeMapper.cs | 4 +- .../DataTypes/DurationSerializer.cs | 103 ++ .../DataTypes/PeriodSerializer.cs | 11 +- .../DataTypes/TimeSpanSerializer.cs | 132 -- .../DataTypes/TriggerSerializer.cs | 8 +- Ical.Net/Serialization/SerializerFactory.cs | 6 +- Ical.Net/Utility/DateUtil.cs | 42 +- 29 files changed, 1392 insertions(+), 1077 deletions(-) create mode 100644 Ical.Net/DataTypes/Duration.cs create mode 100644 Ical.Net/Serialization/DataTypes/DurationSerializer.cs delete mode 100644 Ical.Net/Serialization/DataTypes/TimeSpanSerializer.cs diff --git a/Ical.Net.Tests/CalDateTimeTests.cs b/Ical.Net.Tests/CalDateTimeTests.cs index 2fef5491..f8e41414 100644 --- a/Ical.Net.Tests/CalDateTimeTests.cs +++ b/Ical.Net.Tests/CalDateTimeTests.cs @@ -36,6 +36,21 @@ private static CalendarEvent GetEventWithRecurrenceRules(string tzId) return calendarEvent; } + [Test] + public void ToTimeZoneFloating() + { + var dt = new CalDateTime(2024, 12, 28, 17, 45, 05, "Europe/Vienna"); + var floating = dt.ToTimeZone(null); + var dt2 = floating.ToTimeZone("Europe/Vienna"); + + Assert.Multiple(() => + { + Assert.That(dt, Is.EqualTo(dt2)); + Assert.That(floating.TzId, Is.Null); + Assert.That(floating.Value, Is.EqualTo(dt.Value)); + }); + } + [Test, TestCaseSource(nameof(ToTimeZoneTestCases))] public void ToTimeZoneTests(CalendarEvent calendarEvent, string targetTimeZone) { @@ -157,7 +172,7 @@ public static IEnumerable ToStringTestCases() yield return new TestCaseData(new CalDateTime(2024, 8, 30), null, CultureInfo.GetCultureInfo("IT")) // Date only cannot have timezone - .Returns("30/08/2024") + .Returns("30/08/2024") .SetName("Date only with 'IT' CultureInfo and default format arg"); } @@ -176,14 +191,10 @@ public static IEnumerable DateTimeArithmeticTestCases() .Returns(dateTime.AddHours(1)) .SetName($"{nameof(IDateTime.AddHours)} 1 hour"); - yield return new TestCaseData(new Func(dt => dt.Add(TimeSpan.FromSeconds(30)))) + yield return new TestCaseData(new Func(dt => dt.Add(Duration.FromSeconds(30)))) .Returns(dateTime.Add(TimeSpan.FromSeconds(30))) .SetName($"{nameof(IDateTime.Add)} 30 seconds"); - yield return new TestCaseData(new Func(dt => dt.Add(TimeSpan.FromMilliseconds(100)))) - .Returns(dateTime.Add(TimeSpan.FromMilliseconds(0))) - .SetName($"{nameof(IDateTime.Add)} 100 milliseconds round down"); - yield return new TestCaseData(new Func(dt => dt.AddMinutes(70))) .Returns(dateTime.AddMinutes(70)) .SetName($"{nameof(IDateTime.AddMinutes)} 70 minutes"); @@ -197,15 +208,15 @@ public bool EqualityTests(Func operation) public static IEnumerable EqualityTestCases() { - yield return new TestCaseData(new Func(dt => (CalDateTime) dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: CalDateTime.UtcTzId))) + yield return new TestCaseData(new Func(dt => (CalDateTime)dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: CalDateTime.UtcTzId))) .Returns(true) .SetName("== operator 2 UTC timezones"); - yield return new TestCaseData(new Func(dt => (CalDateTime) dt != new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: "Europe/Berlin"))) + yield return new TestCaseData(new Func(dt => (CalDateTime)dt != new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: "Europe/Berlin"))) .Returns(true) .SetName("!= operator 2 timezones"); - yield return new TestCaseData(new Func(dt => (CalDateTime) dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: null))) + yield return new TestCaseData(new Func(dt => (CalDateTime)dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: null))) .Returns(false) .SetName("== operator UTC vs. floating"); } @@ -245,9 +256,9 @@ public static IEnumerable DateOnlyValidArithmeticTestCases() { var dateTime = new DateTime(2025, 1, 15); - yield return new TestCaseData(new Func(dt => dt.Subtract(TimeSpan.FromDays(1)))) + yield return new TestCaseData(new Func(dt => dt.Add(-Duration.FromDays(1)))) .Returns((dateTime.AddDays(-1), false)) - .SetName($"{nameof(IDateTime.Subtract)} 1 day TimeSpan"); + .SetName($"{nameof(IDateTime.Add)} -1 day TimeSpan"); yield return new TestCaseData(new Func(dt => dt.AddYears(1))) .Returns((dateTime.AddYears(1), false)) @@ -261,23 +272,11 @@ public static IEnumerable DateOnlyValidArithmeticTestCases() .Returns((dateTime.AddDays(7), false)) .SetName($"{nameof(IDateTime.AddDays)} 7 days"); - yield return new TestCaseData(new Func(dt => dt.AddHours(24))) - .Returns((dateTime.AddHours(24), false)) - .SetName($"{nameof(IDateTime.AddHours)} 24 hours"); - - yield return new TestCaseData(new Func(dt => dt.AddMinutes(24 * 60))) - .Returns((dateTime.AddMinutes(24 * 60), false)) - .SetName($"{nameof(IDateTime.AddMinutes)} 1 day in minutes"); - - yield return new TestCaseData(new Func(dt => dt.AddSeconds(TimeSpan.FromDays(1).Seconds))) - .Returns((dateTime.AddSeconds(TimeSpan.FromDays(1).Seconds), false)) - .SetName($"{nameof(IDateTime.AddSeconds)} 1 day in seconds"); - - yield return new TestCaseData(new Func(dt => dt.Add(TimeSpan.FromDays(1)))) + yield return new TestCaseData(new Func(dt => dt.Add(Duration.FromDays(1)))) .Returns((dateTime.Add(TimeSpan.FromDays(1)), false)) .SetName($"{nameof(IDateTime.Add)} 1 day TimeSpan"); - yield return new TestCaseData(new Func(dt => dt.Add(TimeSpan.Zero))) + yield return new TestCaseData(new Func(dt => dt.Add(Duration.Zero))) .Returns((dateTime.Add(TimeSpan.Zero), false)) .SetName($"{nameof(IDateTime.Add)} TimeSpan.Zero"); } @@ -289,7 +288,7 @@ public void DateOnlyInvalidArithmeticTests() Assert.Multiple(() => { - Assert.That(() => dt.Add(TimeSpan.FromHours(1)), Throws.TypeOf()); + Assert.That(() => dt.Add(Duration.FromHours(1)), Throws.TypeOf()); Assert.That(() => dt.AddHours(2), Throws.TypeOf()); Assert.That(() => dt.AddMinutes(3), Throws.TypeOf()); Assert.That(() => dt.AddSeconds(4), Throws.TypeOf()); @@ -316,7 +315,7 @@ public void Simple_PropertyAndMethod_HasTime_Tests() Assert.That(CalDateTime.Today.Value.Kind, Is.EqualTo(DateTimeKind.Unspecified)); Assert.That(c.DayOfYear, Is.EqualTo(dt.DayOfYear)); Assert.That(c.Time?.ToTimeSpan(), Is.EqualTo(dt.TimeOfDay)); - Assert.That(c.Subtract(TimeSpan.FromSeconds(dt.Second)).Value.Second, Is.EqualTo(0)); + Assert.That(c.Add(-Duration.FromSeconds(dt.Second)).Value.Second, Is.EqualTo(0)); Assert.That(c.ToString("dd.MM.yyyy"), Is.EqualTo("02.01.2025 Europe/Berlin")); // Create a date-only CalDateTime from a CalDateTime Assert.That(new CalDateTime(new CalDateTime(2025, 1, 1)), Is.EqualTo(new CalDateTime(2025, 1, 1))); @@ -325,23 +324,23 @@ public void Simple_PropertyAndMethod_HasTime_Tests() public static IEnumerable AddAndSubtractTestCases() { - yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: null), TimeSpan.FromHours(4)) - .SetName("Floating"); + yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: null), Duration.FromHours(4)) + .SetName("Floating"); - yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: CalDateTime.UtcTzId), TimeSpan.FromHours(4)) - .SetName("UTC"); + yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: CalDateTime.UtcTzId), Duration.FromHours(4)) + .SetName("UTC"); - yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: "Europe/Paris"), TimeSpan.FromHours(4)) - .SetName("Zoned Date/Time with DST change"); + yield return new TestCaseData(new CalDateTime(2024, 10, 27, 0, 0, 0, tzId: "Europe/Paris"), Duration.FromHours(4)) + .SetName("Zoned Date/Time with DST change"); } [Test, TestCaseSource(nameof(AddAndSubtractTestCases))] - public void AddAndSubtract_ShouldBeReversible(CalDateTime t, TimeSpan d) + public void AddAndSubtract_ShouldBeReversible(CalDateTime t, Duration d) { Assert.Multiple(() => { - Assert.That(t.Add(d).Subtract(d), Is.EqualTo(t)); - Assert.That(t.Add(d).Subtract(t), Is.EqualTo(d)); + Assert.That(t.Add(d).Add(-d), Is.EqualTo(t)); + Assert.That(t.Add(d).SubtractExact(t), Is.EqualTo(d.ToTimeSpan())); }); } } diff --git a/Ical.Net.Tests/CalendarEventTest.cs b/Ical.Net.Tests/CalendarEventTest.cs index 2ce13859..20787e8f 100644 --- a/Ical.Net.Tests/CalendarEventTest.cs +++ b/Ical.Net.Tests/CalendarEventTest.cs @@ -475,7 +475,7 @@ public void HourMinuteSecondOffsetParsingTest() [Test, Category("CalendarEvent")] - public void GetNominalDurationTests() + public void GetEffectiveDurationTests() { var dt = new DateTime(2025, 3, 1, 14, 30, 0); const string tzIdStart = "America/New_York"; @@ -487,11 +487,12 @@ public void GetNominalDurationTests() DtEnd = new CalDateTime(DateOnly.FromDateTime(dt.AddHours(1)), TimeOnly.FromDateTime(dt.AddHours(1)), tzIdEnd) }; + var ed = evt.GetEffectiveDuration(); Assert.Multiple(() => { Assert.That(evt.DtStart.Value, Is.EqualTo(dt)); Assert.That(evt.DtEnd.Value, Is.EqualTo(dt.AddHours(1))); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.FromHours(1))); + Assert.That(evt.GetEffectiveDuration(), Is.EqualTo(Duration.FromHours(-4))); }); evt = new CalendarEvent @@ -503,7 +504,7 @@ public void GetNominalDurationTests() Assert.Multiple(() => { Assert.That(evt.DtStart.Value, Is.EqualTo(dt.Date)); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.Zero)); + Assert.That(evt.GetEffectiveDuration().IsZero, Is.True); }); evt = new CalendarEvent @@ -515,41 +516,41 @@ public void GetNominalDurationTests() { Assert.That(evt.DtStart.Value, Is.EqualTo(dt.Date)); Assert.That(evt.Duration, Is.Null); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.FromDays(1))); + Assert.That(evt.GetEffectiveDuration(), Is.EqualTo(Duration.FromDays(1))); }); evt = new CalendarEvent { DtStart = new CalDateTime(DateOnly.FromDateTime(dt), TimeOnly.FromDateTime(dt)), - Duration = TimeSpan.FromHours(2), + Duration = Duration.FromHours(2), }; Assert.Multiple(() => { Assert.That(evt.DtStart.Value, Is.EqualTo(dt)); Assert.That(evt.DtEnd, Is.Null); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.FromHours(2))); + Assert.That(evt.GetEffectiveDuration(), Is.EqualTo(Duration.FromHours(2))); }); evt = new CalendarEvent() { DtStart = new CalDateTime(DateOnly.FromDateTime(dt.Date), TimeOnly.FromDateTime(dt.Date)), - Duration = TimeSpan.FromHours(2), + Duration = Duration.FromHours(2), }; Assert.Multiple(() => { Assert.That(evt.DtStart.Value, Is.EqualTo(dt.Date)); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.FromHours(2))); + Assert.That(evt.GetEffectiveDuration(), Is.EqualTo(Duration.FromHours(2))); }); evt = new CalendarEvent() { DtStart = new CalDateTime(DateOnly.FromDateTime(dt)), - Duration = TimeSpan.FromDays(1), + Duration = Duration.FromDays(1), }; Assert.Multiple(() => { Assert.That(evt.DtStart.Value, Is.EqualTo(dt.Date)); - Assert.That(evt.GetTimeSpanToAddToPeriodStartTime(), Is.EqualTo(TimeSpan.FromDays(1))); + Assert.That(evt.GetEffectiveDuration(), Is.EqualTo(Duration.FromDays(1))); }); } @@ -564,9 +565,9 @@ public void EitherEndTime_OrDuraction_CanBeSet() Assert.Multiple(() => { Assert.That(() => evt.DtEnd = new CalDateTime(2025, 12, 11), Throws.Nothing); - Assert.That(() => evt.Duration = TimeSpan.FromDays(1), Throws.InvalidOperationException); + Assert.That(() => evt.Duration = Duration.FromDays(1), Throws.InvalidOperationException); Assert.That(() => evt.DtEnd = null, Throws.Nothing); - Assert.That(() => evt.Duration = TimeSpan.FromDays(1), Throws.Nothing); + Assert.That(() => evt.Duration = Duration.FromDays(1), Throws.Nothing); Assert.That(() => evt.DtEnd = new CalDateTime(2025, 12, 11), Throws.InvalidOperationException); }); } diff --git a/Ical.Net.Tests/CopyComponentTests.cs b/Ical.Net.Tests/CopyComponentTests.cs index 3c16c57b..24d77f30 100644 --- a/Ical.Net.Tests/CopyComponentTests.cs +++ b/Ical.Net.Tests/CopyComponentTests.cs @@ -110,7 +110,7 @@ public void CopyFreeBusyTest() { Start = new CalDateTime(_now), End = new CalDateTime(_later), - Entries = { new FreeBusyEntry { Language = "English", StartTime = new CalDateTime(2024, 10, 1), Duration = TimeSpan.FromDays(1), Status = FreeBusyStatus.Busy } } + Entries = { new FreeBusyEntry { Language = "English", StartTime = new CalDateTime(2024, 10, 1), Duration = Duration.FromDays(1), Status = FreeBusyStatus.Busy } } }; var copy = orig.Copy(); @@ -133,7 +133,7 @@ public void CopyAlarmTest() var orig = new Alarm { Action = AlarmAction.Display, - Trigger = new Trigger(TimeSpan.FromMinutes(15)), + Trigger = new Trigger(Duration.FromMinutes(15)), Description = "Test Alarm" }; diff --git a/Ical.Net.Tests/DeserializationTests.cs b/Ical.Net.Tests/DeserializationTests.cs index 1156e754..5a596c72 100644 --- a/Ical.Net.Tests/DeserializationTests.cs +++ b/Ical.Net.Tests/DeserializationTests.cs @@ -562,7 +562,7 @@ public void KeepApartDtEndAndDuration_Tests(bool useDtEnd) Assert.Multiple(() => { Assert.That(calendar.Events.Single().DtEnd != null, Is.EqualTo(useDtEnd)); - Assert.That(calendar.Events.Single().Duration != default, Is.EqualTo(!useDtEnd)); + Assert.That(calendar.Events.Single().Duration != null, Is.EqualTo(!useDtEnd)); }); } } diff --git a/Ical.Net.Tests/EqualityAndHashingTests.cs b/Ical.Net.Tests/EqualityAndHashingTests.cs index 8485d03b..f40113dd 100644 --- a/Ical.Net.Tests/EqualityAndHashingTests.cs +++ b/Ical.Net.Tests/EqualityAndHashingTests.cs @@ -111,7 +111,7 @@ public void Calendar_Tests() var e = new CalendarEvent { DtStart = new CalDateTime(_nowTime), - Duration = TimeSpan.FromHours(1), + Duration = Duration.FromHours(1), RecurrenceRules = new List { rruleA }, }; @@ -128,7 +128,7 @@ public void Calendar_Tests() expectedCalendar.Events.Add(new CalendarEvent { DtStart = new CalDateTime(_nowTime), - Duration = TimeSpan.FromHours(1), + Duration = Duration.FromHours(1), RecurrenceRules = new List { rruleB }, }); diff --git a/Ical.Net.Tests/PeriodTests.cs b/Ical.Net.Tests/PeriodTests.cs index 04d54d44..3ae3021d 100644 --- a/Ical.Net.Tests/PeriodTests.cs +++ b/Ical.Net.Tests/PeriodTests.cs @@ -18,7 +18,7 @@ public void CreatePeriodWithArguments() { var period = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York")); var periodWithEndTime = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), new CalDateTime(2025, 1, 1, 1, 0, 0, "America/New_York")); - var periodWithDuration = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), new TimeSpan(1, 0, 0)); + var periodWithDuration = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), Duration.FromHours(1)); Assert.Multiple(() => { @@ -27,12 +27,12 @@ public void CreatePeriodWithArguments() Assert.That(period.Duration, Is.Null); Assert.That(periodWithEndTime.StartTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"))); - Assert.That(periodWithEndTime.EndTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0, "America/New_York"))); - Assert.That(periodWithEndTime.Duration, Is.EqualTo(new TimeSpan(1, 0, 0))); + Assert.That(periodWithEndTime.GetEffectiveEndTime(), Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0, "America/New_York"))); + Assert.That(periodWithEndTime.GetEffectiveDuration(), Is.EqualTo(Duration.FromHours(1))); Assert.That(periodWithDuration.StartTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"))); - Assert.That(periodWithDuration.EndTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0, "America/New_York"))); - Assert.That(periodWithDuration.Duration, Is.EqualTo(new TimeSpan(1, 0, 0))); + Assert.That(periodWithDuration.GetEffectiveEndTime(), Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0, "America/New_York"))); + Assert.That(periodWithDuration.GetEffectiveDuration(), Is.EqualTo(Duration.FromHours(1))); }); } @@ -42,7 +42,7 @@ public void CreatePeriodWithInvalidArgumentsShouldThrow() Assert.Throws(() => _ = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"))); Assert.Throws(() => - _ = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), new TimeSpan(-1, 0, 0))); + _ = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0, "America/New_York"), Duration.FromHours(-1))); } [Test] public void SetAndGetStartTime() @@ -61,31 +61,31 @@ public void SetEndTime_GetDuration() var endTime = new CalDateTime(2025, 1, 31, 0, 0, 0); period.EndTime = endTime; + Assert.That(period.GetEffectiveEndTime(), Is.EqualTo(endTime)); Assert.That(period.EndTime, Is.EqualTo(endTime)); - Assert.That(period.GetOriginalValues().EndTime, Is.EqualTo(endTime)); - Assert.That(period.GetOriginalValues().Duration, Is.Null); - Assert.That(period.Duration, Is.EqualTo(new TimeSpan(30, 0, 0, 0))); + Assert.That(period.Duration, Is.Null); + Assert.That(period.GetEffectiveDuration(), Is.EqualTo(Duration.FromDays(30))); } [Test] public void SetDuration_GetEndTime() { var period = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0)); - var duration = new TimeSpan(1, 0, 0); + var duration = Duration.FromHours(1); period.Duration = duration; + Assert.That(period.GetEffectiveDuration(), Is.EqualTo(duration)); Assert.That(period.Duration, Is.EqualTo(duration)); - Assert.That(period.GetOriginalValues().Duration, Is.EqualTo(duration)); - Assert.That(period.GetOriginalValues().EndTime, Is.Null); - Assert.That(period.EndTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0))); + Assert.That(period.EndTime, Is.Null); + Assert.That(period.GetEffectiveEndTime(), Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0))); } [Test] public void CollidesWithPeriod() { - var period1 = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0), new TimeSpan(1, 0, 0)); - var period2 = new Period(new CalDateTime(2025, 1, 1, 0, 30, 0), new TimeSpan(1, 0, 0)); - var period3 = new Period(new CalDateTime(2025, 1, 1, 1, 30, 0), new TimeSpan(1, 0, 0)); + var period1 = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0), Duration.FromHours(1)); + var period2 = new Period(new CalDateTime(2025, 1, 1, 0, 30, 0), Duration.FromHours(1)); + var period3 = new Period(new CalDateTime(2025, 1, 1, 1, 30, 0), Duration.FromHours(1)); Assert.Multiple(() => { diff --git a/Ical.Net.Tests/RecurrenceTests.cs b/Ical.Net.Tests/RecurrenceTests.cs index 212848ef..ec12c482 100644 --- a/Ical.Net.Tests/RecurrenceTests.cs +++ b/Ical.Net.Tests/RecurrenceTests.cs @@ -29,7 +29,7 @@ private void EventOccurrenceTest( Calendar cal, IDateTime fromDate, IDateTime toDate, - IDateTime[] dateTimes, + Period[] expectedPeriods, string[] timeZones, int eventIndex ) @@ -39,8 +39,10 @@ int eventIndex #pragma warning disable 0618 if (rule != null) rule.RestrictionType = RecurrenceRestrictionType.NoRestriction; #pragma warning restore 0618 - fromDate.AssociatedObject = cal; - toDate.AssociatedObject = cal; + if (fromDate != null) + fromDate.AssociatedObject = cal; + if (toDate != null) + toDate.AssociatedObject = cal; var occurrences = evt.GetOccurrences(fromDate, toDate) .OrderBy(o => o.Period.StartTime) @@ -50,24 +52,26 @@ int eventIndex { Assert.That( occurrences, - Has.Count.EqualTo(dateTimes.Length), - "There should have been " + dateTimes.Length + " occurrences; there were " + occurrences.Count); + Has.Count.EqualTo(expectedPeriods.Length), + "There should have been " + expectedPeriods.Length + " occurrences; there were " + occurrences.Count); if (evt.RecurrenceRules.Count > 0) { Assert.That(evt.RecurrenceRules, Has.Count.EqualTo(1)); } - for (var i = 0; i < dateTimes.Length; i++) + for (var i = 0; i < expectedPeriods.Length; i++) { // Associate each incoming date/time with the calendar. - dateTimes[i].AssociatedObject = cal; + expectedPeriods[i].AssociatedObject = cal; - var dt = dateTimes[i]; - Assert.That(occurrences[i].Period.StartTime, Is.EqualTo(dt), "Event should occur on " + dt); + var period = expectedPeriods[i].Copy(); + period.EndTime = period.GetEffectiveEndTime(); + + Assert.That(occurrences[i].Period, Is.EqualTo(period), "Event should occur on " + period); if (timeZones != null) - Assert.That(dt.TimeZoneName, Is.EqualTo(timeZones[i]), - "Event " + dt + " should occur in the " + timeZones[i] + " timezone"); + Assert.That(period.StartTime.TimeZoneName, Is.EqualTo(timeZones[i]), + "Event " + period + " should occur in the " + timeZones[i] + " timezone"); } }); } @@ -76,11 +80,11 @@ private void EventOccurrenceTest( Calendar cal, IDateTime fromDate, IDateTime toDate, - IDateTime[] dateTimes, + Period[] expectedPeriods, string[] timeZones ) { - EventOccurrenceTest(cal, fromDate, toDate, dateTimes, timeZones, 0); + EventOccurrenceTest(cal, fromDate, toDate, expectedPeriods, timeZones, 0); } /// @@ -130,19 +134,18 @@ public void DailyCount1() iCal, new CalDateTime(2006, 7, 1), new CalDateTime(2006, 9, 1), - new[] - { - new CalDateTime(2006, 07, 18, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 20, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 22, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 24, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 26, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 28, 10, 00, 00, _tzid), - new CalDateTime(2006, 07, 30, 10, 00, 00, _tzid), - new CalDateTime(2006, 08, 01, 10, 00, 00, _tzid), - new CalDateTime(2006, 08, 03, 10, 00, 00, _tzid), - new CalDateTime(2006, 08, 05, 10, 00, 00, _tzid) - }, + [ + new(new CalDateTime(2006, 07, 18, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 20, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 22, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 24, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 26, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 28, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 07, 30, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 08, 01, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 08, 03, 10, 00, 00, _tzid), Duration.FromHours(1)), + new(new CalDateTime(2006, 08, 05, 10, 00, 00, _tzid), Duration.FromHours(1)) + ], null ); } @@ -195,56 +198,55 @@ public void Daily1() iCal, new CalDateTime(1997, 9, 1), new CalDateTime(1997, 12, 4), - new[] - { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 6, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 8, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 20, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 24, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 26, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 6, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 8, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 20, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 22, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 24, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 26, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 21, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 23, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 27, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 3, 9, 0, 0, _tzid) - }, + [ + new(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 21, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 3, 9, 0, 0, _tzid), Duration.FromHours(1)) + ], new[] { "US-Eastern", @@ -309,14 +311,13 @@ public void DailyCount2() iCal, new CalDateTime(1997, 9, 1), new CalDateTime(1998, 1, 1), - new[] - { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 12, 9, 0, 0, _tzid) - }, + [ + new(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 12, 9, 0, 0, _tzid), Duration.FromHours(1)) + ], null ); } @@ -387,19 +388,18 @@ public void WeeklyCount1() iCal, new CalDateTime(1997, 9, 1), new CalDateTime(1998, 1, 1), - new[] - { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 21, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid) - }, + [ + new(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 21, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid), Duration.FromHours(1)) + ], new[] { "US-Eastern", @@ -427,26 +427,25 @@ public void WeeklyUntil1() iCal, new CalDateTime(1997, 9, 1), new CalDateTime(1999, 1, 1), - new[] - { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 21, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 23, 9, 0, 0, _tzid) - }, + [ + new(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 21, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new(new CalDateTime(1997, 12, 23, 9, 0, 0, _tzid), Duration.FromHours(1)) + ], new[] { "US-Eastern", @@ -483,17 +482,17 @@ public void WeeklyWkst1() new CalDateTime(1998, 1, 31), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 23, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 6, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 20, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 20, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -525,16 +524,16 @@ public void WeeklyUntilWkst1() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 25, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -575,30 +574,30 @@ public void WeeklyUntilWkst2() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 27, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 24, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 26, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 8, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -644,28 +643,28 @@ public void WeeklyUntilWkst2_1() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 27, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 24, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 26, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 8, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -708,14 +707,14 @@ public void WeeklyCountWkst2() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 16, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 16, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -734,16 +733,16 @@ public void MonthlyCountByDay1() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 5, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 2, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 6, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 6, 9, 0, 0, _tzid), - new CalDateTime(1998, 4, 3, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 1, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 5, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 4, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 5, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -774,10 +773,10 @@ public void MonthlyUntilByDay1() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 5, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 5, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -802,16 +801,16 @@ public void MonthlyCountByDay2() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 30, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 4, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 25, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 1, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 29, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 3, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 31, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 31, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -842,12 +841,12 @@ public void MonthlyCountByDay3() new CalDateTime(1999, 1, 1), new[] { - new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 20, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 19, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 16, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 16, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -874,12 +873,12 @@ public void ByMonthDay1() new CalDateTime(1998, 3, 1), new[] { - new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 29, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 29, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 26, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 26, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -907,16 +906,16 @@ public void MonthlyCountByMonthDay1() new CalDateTime(1998, 3, 1), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 15, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 2, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 15, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 15, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -947,16 +946,16 @@ public void MonthlyCountByMonthDay2() new CalDateTime(1998, 3, 1), new[] { - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 31, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 1, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 31, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 1, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 1, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -987,16 +986,16 @@ public void MonthlyCountByMonthDay3() new CalDateTime(2000, 1, 1), new[] { - new CalDateTime(1997, 9, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 11, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 12, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 13, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 13, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1027,24 +1026,24 @@ public void MonthlyByDay1() new CalDateTime(1998, 4, 1), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 18, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 6, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 20, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 27, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 3, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 10, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 17, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 24, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 31, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 31, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1083,16 +1082,16 @@ public void YearlyByMonth1() new CalDateTime(2002, 1, 1), new[] { - new CalDateTime(1997, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 10, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 10, 9, 0, 0, _tzid), - new CalDateTime(2000, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(2000, 7, 10, 9, 0, 0, _tzid), - new CalDateTime(2001, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(2001, 7, 10, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2001, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2001, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1111,16 +1110,16 @@ public void YearlyCountByMonth1() new CalDateTime(2003, 4, 1), new[] { - new CalDateTime(1997, 3, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 1, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 2, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 10, 9, 0, 0, _tzid), - new CalDateTime(2001, 1, 10, 9, 0, 0, _tzid), - new CalDateTime(2001, 2, 10, 9, 0, 0, _tzid), - new CalDateTime(2001, 3, 10, 9, 0, 0, _tzid), - new CalDateTime(2003, 1, 10, 9, 0, 0, _tzid), - new CalDateTime(2003, 2, 10, 9, 0, 0, _tzid), - new CalDateTime(2003, 3, 10, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 1, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 2, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2001, 1, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2001, 2, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2001, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 1, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 2, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 3, 10, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1139,16 +1138,16 @@ public void YearlyCountByYearDay1() new CalDateTime(2007, 1, 1), new[] { - new CalDateTime(1997, 1, 1, 9, 0, 0, _tzid), - new CalDateTime(1997, 4, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 19, 9, 0, 0, _tzid), - new CalDateTime(2000, 1, 1, 9, 0, 0, _tzid), - new CalDateTime(2000, 4, 9, 9, 0, 0, _tzid), - new CalDateTime(2000, 7, 18, 9, 0, 0, _tzid), - new CalDateTime(2003, 1, 1, 9, 0, 0, _tzid), - new CalDateTime(2003, 4, 10, 9, 0, 0, _tzid), - new CalDateTime(2003, 7, 19, 9, 0, 0, _tzid), - new CalDateTime(2006, 1, 1, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 1, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 4, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 1, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 4, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 7, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 1, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 4, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2003, 7, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2006, 1, 1, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1179,9 +1178,9 @@ public void YearlyByDay1() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 5, 19, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 18, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 5, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1217,9 +1216,9 @@ public void YearlyByWeekNo1() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1243,9 +1242,9 @@ public void YearlyByWeekNo2() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1268,8 +1267,8 @@ public void YearlyByWeekNo3() new CalDateTime(2003, 1, 31), new[] { - new CalDateTime(2002, 1, 1, 10, 0, 0, _tzid), - new CalDateTime(2002, 12, 31, 10, 0, 0, _tzid) + new Period(new CalDateTime(2002, 1, 1, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 12, 31, 10, 0, 0, _tzid), Duration.FromMinutes(30)) }, null ); @@ -1291,27 +1290,27 @@ public void YearlyByWeekNo4() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 15, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 16, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 5, 18, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 12, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 14, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 15, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 16, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 17, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 18, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 19, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 20, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 21, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 22, 9, 0, 0, _tzid), - new CalDateTime(1999, 5, 23, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 5, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 5, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 21, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 5, 23, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1335,19 +1334,19 @@ public void YearlyByWeekNo5() new CalDateTime(2003, 1, 31), new[] { - new CalDateTime(2002, 1, 1, 10, 0, 0, _tzid), - new CalDateTime(2002, 1, 2, 10, 0, 0, _tzid), - new CalDateTime(2002, 1, 3, 10, 0, 0, _tzid), - new CalDateTime(2002, 1, 4, 10, 0, 0, _tzid), - new CalDateTime(2002, 1, 5, 10, 0, 0, _tzid), - new CalDateTime(2002, 1, 6, 10, 0, 0, _tzid), - new CalDateTime(2002, 12, 30, 10, 0, 0, _tzid), - new CalDateTime(2002, 12, 31, 10, 0, 0, _tzid), - new CalDateTime(2003, 1, 1, 10, 0, 0, _tzid), - new CalDateTime(2003, 1, 2, 10, 0, 0, _tzid), - new CalDateTime(2003, 1, 3, 10, 0, 0, _tzid), - new CalDateTime(2003, 1, 4, 10, 0, 0, _tzid), - new CalDateTime(2003, 1, 5, 10, 0, 0, _tzid) + new Period(new CalDateTime(2002, 1, 1, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 1, 2, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 1, 3, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 1, 4, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 1, 5, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 1, 6, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 12, 30, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2002, 12, 31, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2003, 1, 1, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2003, 1, 2, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2003, 1, 3, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2003, 1, 4, 10, 0, 0, _tzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2003, 1, 5, 10, 0, 0, _tzid), Duration.FromMinutes(30)) }, null ); @@ -1366,17 +1365,17 @@ public void YearlyByMonth2() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 3, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 3, 20, 9, 0, 0, _tzid), - new CalDateTime(1997, 3, 27, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 5, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 12, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 19, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 26, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 4, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 11, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 18, 9, 0, 0, _tzid), - new CalDateTime(1999, 3, 25, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 3, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 3, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 3, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 3, 25, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1395,45 +1394,45 @@ public void YearlyByMonth3() new CalDateTime(1999, 12, 31), new[] { - new CalDateTime(1997, 6, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 6, 12, 9, 0, 0, _tzid), - new CalDateTime(1997, 6, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 6, 26, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 24, 9, 0, 0, _tzid), - new CalDateTime(1997, 7, 31, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 14, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 21, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 28, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 4, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 11, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 18, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 25, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 2, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 9, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 16, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 23, 9, 0, 0, _tzid), - new CalDateTime(1998, 7, 30, 9, 0, 0, _tzid), - new CalDateTime(1998, 8, 6, 9, 0, 0, _tzid), - new CalDateTime(1998, 8, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 8, 20, 9, 0, 0, _tzid), - new CalDateTime(1998, 8, 27, 9, 0, 0, _tzid), - new CalDateTime(1999, 6, 3, 9, 0, 0, _tzid), - new CalDateTime(1999, 6, 10, 9, 0, 0, _tzid), - new CalDateTime(1999, 6, 17, 9, 0, 0, _tzid), - new CalDateTime(1999, 6, 24, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 1, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 8, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 15, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 22, 9, 0, 0, _tzid), - new CalDateTime(1999, 7, 29, 9, 0, 0, _tzid), - new CalDateTime(1999, 8, 5, 9, 0, 0, _tzid), - new CalDateTime(1999, 8, 12, 9, 0, 0, _tzid), - new CalDateTime(1999, 8, 19, 9, 0, 0, _tzid), - new CalDateTime(1999, 8, 26, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 6, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 6, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 6, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 6, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 7, 31, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 14, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 21, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 28, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 18, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 25, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 16, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 23, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 7, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 8, 6, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 8, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 8, 20, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 8, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 6, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 6, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 6, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 6, 24, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 1, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 15, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 22, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 7, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 8, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 8, 12, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 8, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 8, 26, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1454,11 +1453,11 @@ public void MonthlyByMonthDay1() new CalDateTime(2000, 12, 31), new[] { - new CalDateTime(1998, 2, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 11, 13, 9, 0, 0, _tzid), - new CalDateTime(1999, 8, 13, 9, 0, 0, _tzid), - new CalDateTime(2000, 10, 13, 9, 0, 0, _tzid) + new Period(new CalDateTime(1998, 2, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 11, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1999, 8, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 10, 13, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1484,16 +1483,16 @@ public void MonthlyByMonthDay2() new CalDateTime(1998, 6, 30), new[] { - new CalDateTime(1997, 9, 13, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 11, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 8, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 13, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 10, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 7, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 7, 9, 0, 0, _tzid), - new CalDateTime(1998, 4, 11, 9, 0, 0, _tzid), - new CalDateTime(1998, 5, 9, 9, 0, 0, _tzid), - new CalDateTime(1998, 6, 13, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 8, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 13, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 4, 11, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 5, 9, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 6, 13, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1524,9 +1523,9 @@ public void YearlyByMonthDay1() new CalDateTime(2004, 12, 31), new[] { - new CalDateTime(1996, 11, 5, 9, 0, 0, _tzid), - new CalDateTime(2000, 11, 7, 9, 0, 0, _tzid), - new CalDateTime(2004, 11, 2, 9, 0, 0, _tzid) + new Period(new CalDateTime(1996, 11, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2000, 11, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(2004, 11, 2, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1545,9 +1544,9 @@ public void MonthlyBySetPos1() new CalDateTime(2004, 12, 31), new[] { - new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 6, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 4, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 7, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 6, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1571,13 +1570,13 @@ public void MonthlyBySetPos2() new CalDateTime(1998, 3, 31), new[] { - new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), - new CalDateTime(1997, 10, 30, 9, 0, 0, _tzid), - new CalDateTime(1997, 11, 27, 9, 0, 0, _tzid), - new CalDateTime(1997, 12, 30, 9, 0, 0, _tzid), - new CalDateTime(1998, 1, 29, 9, 0, 0, _tzid), - new CalDateTime(1998, 2, 26, 9, 0, 0, _tzid), - new CalDateTime(1998, 3, 30, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 9, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 10, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 11, 27, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 12, 30, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 1, 29, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 2, 26, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1998, 3, 30, 9, 0, 0, _tzid), Duration.FromHours(1)) }, new[] { @@ -1605,12 +1604,12 @@ public void HourlyUntil1() iCal, fromDate: new CalDateTime(1996, 1, 1), toDate: new CalDateTime(1998, 3, 31), - dateTimes: new[] + expectedPeriods: new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 15, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 18, 0, 0, _tzid), + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 15, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 18, 0, 0, _tzid), Duration.FromHours(1)), }, timeZones: null ); @@ -1629,12 +1628,12 @@ public void MinutelyCount1() new CalDateTime(1997, 9, 3), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 9, 15, 0, _tzid), - new CalDateTime(1997, 9, 2, 9, 30, 0, _tzid), - new CalDateTime(1997, 9, 2, 9, 45, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 15, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 9, 15, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 9, 30, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 9, 45, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 15, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1653,10 +1652,10 @@ public void MinutelyCount2() new CalDateTime(1998, 12, 31), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 30, 0, _tzid), - new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 13, 30, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 30, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 13, 30, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1675,16 +1674,16 @@ public void MinutelyCount3() new CalDateTime(2010, 8, 28), new[] { - new CalDateTime(2010, 8, 27, 11, 0, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 1, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 2, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 3, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 4, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 5, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 6, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 7, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 8, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 9, 0, _tzid) + new Period(new CalDateTime(2010, 8, 27, 11, 0, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 1, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 2, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 3, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 4, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 5, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 6, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 7, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 8, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 9, 0, _tzid), Duration.FromMinutes(3)) }, null ); @@ -1703,16 +1702,16 @@ public void MinutelyCount4() new CalDateTime(2010, 8, 28), new[] { - new CalDateTime(2010, 8, 27, 11, 0, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 7, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 14, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 21, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 28, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 35, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 42, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 49, 0, _tzid), - new CalDateTime(2010, 8, 27, 11, 56, 0, _tzid), - new CalDateTime(2010, 8, 27, 12, 3, 0, _tzid) + new Period(new CalDateTime(2010, 8, 27, 11, 0, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 7, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 14, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 21, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 28, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 35, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 42, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 49, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 11, 56, 0, _tzid), Duration.FromMinutes(3)), + new Period(new CalDateTime(2010, 8, 27, 12, 3, 0, _tzid), Duration.FromMinutes(3)) }, null ); @@ -1731,54 +1730,54 @@ public void DailyByHourMinute1() new CalDateTime(1997, 9, 4), new[] { - new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 9, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 9, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 10, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 11, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 11, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 11, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 12, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 12, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 13, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 13, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 13, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 14, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 14, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 14, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 15, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 15, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 15, 40, 0, _tzid), - new CalDateTime(1997, 9, 2, 16, 0, 0, _tzid), - new CalDateTime(1997, 9, 2, 16, 20, 0, _tzid), - new CalDateTime(1997, 9, 2, 16, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 9, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 9, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 9, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 10, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 10, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 10, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 11, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 11, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 11, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 12, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 12, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 12, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 13, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 13, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 13, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 14, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 14, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 14, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 15, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 15, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 15, 40, 0, _tzid), - new CalDateTime(1997, 9, 3, 16, 0, 0, _tzid), - new CalDateTime(1997, 9, 3, 16, 20, 0, _tzid), - new CalDateTime(1997, 9, 3, 16, 40, 0, _tzid) + new Period(new CalDateTime(1997, 9, 2, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 9, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 9, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 10, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 11, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 11, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 11, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 12, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 12, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 12, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 13, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 13, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 13, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 14, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 14, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 14, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 15, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 15, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 15, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 16, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 16, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 2, 16, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 9, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 9, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 10, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 10, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 10, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 11, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 11, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 11, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 12, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 12, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 12, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 13, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 13, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 13, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 14, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 14, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 14, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 15, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 15, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 15, 40, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 16, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 16, 20, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 9, 3, 16, 40, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1817,10 +1816,10 @@ public void WeeklyCountWkst3() new CalDateTime(1998, 12, 31), new[] { - new CalDateTime(1997, 8, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 10, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 24, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 8, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 10, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 24, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1840,10 +1839,10 @@ public void WeeklyCountWkst4() new CalDateTime(1998, 12, 31), new[] { - new CalDateTime(1997, 8, 5, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 17, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 19, 9, 0, 0, _tzid), - new CalDateTime(1997, 8, 31, 9, 0, 0, _tzid) + new Period(new CalDateTime(1997, 8, 5, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 17, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 19, 9, 0, 0, _tzid), Duration.FromHours(1)), + new Period(new CalDateTime(1997, 8, 31, 9, 0, 0, _tzid), Duration.FromHours(1)) }, null ); @@ -1863,18 +1862,18 @@ public void Bug1741093() new CalDateTime(2007, 8, 1), new[] { - new CalDateTime(2007, 7, 2, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 3, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 4, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 5, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 6, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 16, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 17, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 18, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 19, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 20, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 30, 8, 0, 0, _tzid), - new CalDateTime(2007, 7, 31, 8, 0, 0, _tzid) + new Period(new CalDateTime(2007, 7, 2, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 3, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 4, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 5, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 6, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 16, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 17, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 18, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 19, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 20, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 30, 8, 0, 0, _tzid), Duration.FromHours(9)), + new Period(new CalDateTime(2007, 7, 31, 8, 0, 0, _tzid), Duration.FromHours(9)) }, null ); @@ -1888,13 +1887,13 @@ public void Secondly_DefinedNumberOfOccurrences_ShouldSucceed() 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. - var dateTimes = new List(); + var periods = new List(); for (var dt = start; dt.LessThan(end); dt = (CalDateTime) dt.AddSeconds(1)) { - dateTimes.Add(new CalDateTime(dt)); + periods.Add(new Period(new CalDateTime(dt), Duration.FromHours(9))); } - EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); + EventOccurrenceTest(iCal, start, end, periods.ToArray(), null); } [Test, Category("Recurrence")] @@ -1905,13 +1904,13 @@ public void Minutely_DefinedNumberOfOccurrences_ShouldSucceed() 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. - var dateTimes = new List(); + var periods = new List(); for (var dt = start; dt.LessThan(end); dt = (CalDateTime)dt.AddMinutes(1)) { - dateTimes.Add(new CalDateTime(dt)); + periods.Add(new Period(new CalDateTime(dt), Duration.FromHours(9))); } - EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); + EventOccurrenceTest(iCal, start, end, periods.ToArray(), null); } [Test, Category("Recurrence")] @@ -1922,13 +1921,13 @@ public void Hourly_DefinedNumberOfOccurrences_ShouldSucceed() 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(); + var periods = new List(); for (var dt = start; dt.LessThan(end); dt = (CalDateTime)dt.AddHours(1)) { - dateTimes.Add(new CalDateTime(dt)); + periods.Add(new Period(new CalDateTime(dt), Duration.FromHours(9))); } - EventOccurrenceTest(iCal, start, end, dateTimes.ToArray(), null); + EventOccurrenceTest(iCal, start, end, periods.ToArray(), null); } /// @@ -1944,8 +1943,8 @@ public void MonthlyInterval1() new CalDateTime(2008, 2, 29, 7, 0, 0, _tzid), new[] { - new CalDateTime(2008, 2, 11, 7, 0, 0, _tzid), - new CalDateTime(2008, 2, 12, 7, 0, 0, _tzid) + new Period(new CalDateTime(2008, 2, 11, 7, 0, 0, _tzid), Duration.FromHours(24)), + new Period(new CalDateTime(2008, 2, 12, 7, 0, 0, _tzid), Duration.FromHours(24)) }, null ); @@ -1964,8 +1963,8 @@ public void YearlyInterval1() new CalDateTime(2007, 1, 31, 7, 0, 0, _tzid), new[] { - new CalDateTime(2007, 1, 8, 7, 0, 0, _tzid), - new CalDateTime(2007, 1, 9, 7, 0, 0, _tzid) + new Period(new CalDateTime(2007, 1, 8, 7, 0, 0, _tzid), Duration.FromHours(24)), + new Period(new CalDateTime(2007, 1, 9, 7, 0, 0, _tzid), Duration.FromHours(24)) }, null ); @@ -1984,8 +1983,8 @@ public void DailyInterval1() new CalDateTime(2007, 4, 16, 7, 0, 0, _tzid), new[] { - new CalDateTime(2007, 4, 12, 7, 0, 0, _tzid), - new CalDateTime(2007, 4, 15, 7, 0, 0, _tzid) + new Period(new CalDateTime(2007, 4, 12, 7, 0, 0, _tzid), Duration.FromHours(24)), + new Period(new CalDateTime(2007, 4, 15, 7, 0, 0, _tzid), Duration.FromHours(24)) }, null ); @@ -2008,9 +2007,9 @@ public void HourlyInterval1() // after the start of the evaluation period. // See bug #3007244. // https://sourceforge.net/tracker/?func=detail&aid=3007244&group_id=187422&atid=921236 - new CalDateTime(2007, 4, 9, 7, 0, 0, _tzid), - new CalDateTime(2007, 4, 10, 1, 0, 0, _tzid), - new CalDateTime(2007, 4, 10, 19, 0, 0, _tzid) + new Period(new CalDateTime(2007, 4, 9, 7, 0, 0, _tzid), Duration.FromHours(24)), + new Period(new CalDateTime(2007, 4, 10, 1, 0, 0, _tzid), Duration.FromHours(24)), + new Period(new CalDateTime(2007, 4, 10, 19, 0, 0, _tzid), Duration.FromHours(24)) }, null ); @@ -2031,16 +2030,16 @@ public void YearlyBySetPos1() new CalDateTime(2020, 1, 1, 0, 0, 0, _tzid), new[] { - new CalDateTime(2009, 9, 27, 5, 30, 0), - new CalDateTime(2010, 9, 26, 5, 30, 0), - new CalDateTime(2011, 9, 25, 5, 30, 0), - new CalDateTime(2012, 9, 30, 5, 30, 0), - new CalDateTime(2013, 9, 29, 5, 30, 0), - new CalDateTime(2014, 9, 28, 5, 30, 0), - new CalDateTime(2015, 9, 27, 5, 30, 0), - new CalDateTime(2016, 9, 25, 5, 30, 0), - new CalDateTime(2017, 9, 30, 5, 30, 0), - new CalDateTime(2018, 9, 30, 5, 30, 0) + new Period(new CalDateTime(2009, 9, 27, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 9, 26, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2011, 9, 25, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2012, 9, 30, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2013, 9, 29, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2014, 9, 28, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2015, 9, 27, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2016, 9, 25, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2017, 9, 30, 5, 30, 0), Duration.FromMinutes(30)), + new Period(new CalDateTime(2018, 9, 30, 5, 30, 0), Duration.FromMinutes(30)) }, null ); @@ -2060,7 +2059,7 @@ public void Empty1() new CalDateTime(2010, 1, 1, 0, 0, 0, _tzid), new[] { - new CalDateTime(2009, 9, 27, 5, 30, 0) + new Period(new CalDateTime(2009, 9, 27, 5, 30, 0), new Duration(days: 3, minutes: 30)) }, null ); @@ -2079,17 +2078,17 @@ public void HourlyInterval2() new CalDateTime(2007, 4, 10, 23, 0, 1), // End time is exclusive, not inclusive new[] { - new CalDateTime(2007, 4, 9, 7, 0, 0), - new CalDateTime(2007, 4, 9, 11, 0, 0), - new CalDateTime(2007, 4, 9, 15, 0, 0), - new CalDateTime(2007, 4, 9, 19, 0, 0), - new CalDateTime(2007, 4, 9, 23, 0, 0), - new CalDateTime(2007, 4, 10, 3, 0, 0), - new CalDateTime(2007, 4, 10, 7, 0, 0), - new CalDateTime(2007, 4, 10, 11, 0, 0), - new CalDateTime(2007, 4, 10, 15, 0, 0), - new CalDateTime(2007, 4, 10, 19, 0, 0), - new CalDateTime(2007, 4, 10, 23, 0, 0) + new Period(new CalDateTime(2007, 4, 9, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 11, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 15, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 19, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 23, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 3, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 11, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 15, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 19, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 10, 23, 0, 0), Duration.FromDays(1)) }, null ); @@ -2108,17 +2107,17 @@ public void MinutelyInterval1() new CalDateTime(2007, 4, 9, 12, 0, 1), // End time is exclusive, not inclusive new[] { - new CalDateTime(2007, 4, 9, 7, 0, 0), - new CalDateTime(2007, 4, 9, 7, 30, 0), - new CalDateTime(2007, 4, 9, 8, 0, 0), - new CalDateTime(2007, 4, 9, 8, 30, 0), - new CalDateTime(2007, 4, 9, 9, 0, 0), - new CalDateTime(2007, 4, 9, 9, 30, 0), - new CalDateTime(2007, 4, 9, 10, 0, 0), - new CalDateTime(2007, 4, 9, 10, 30, 0), - new CalDateTime(2007, 4, 9, 11, 0, 0), - new CalDateTime(2007, 4, 9, 11, 30, 0), - new CalDateTime(2007, 4, 9, 12, 0, 0) + new Period(new CalDateTime(2007, 4, 9, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 7, 30, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 8, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 8, 30, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 9, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 9, 30, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 10, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 10, 30, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 11, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 11, 30, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 9, 12, 0, 0), Duration.FromDays(1)) }, null ); @@ -2137,16 +2136,16 @@ public void DailyInterval2() new CalDateTime(2007, 4, 27, 7, 0, 1), // End time is exclusive, not inclusive new[] { - new CalDateTime(2007, 4, 9, 7, 0, 0), - new CalDateTime(2007, 4, 11, 7, 0, 0), - new CalDateTime(2007, 4, 13, 7, 0, 0), - new CalDateTime(2007, 4, 15, 7, 0, 0), - new CalDateTime(2007, 4, 17, 7, 0, 0), - new CalDateTime(2007, 4, 19, 7, 0, 0), - new CalDateTime(2007, 4, 21, 7, 0, 0), - new CalDateTime(2007, 4, 23, 7, 0, 0), - new CalDateTime(2007, 4, 25, 7, 0, 0), - new CalDateTime(2007, 4, 27, 7, 0, 0) + new Period(new CalDateTime(2007, 4, 9, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 11, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 13, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 15, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 17, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 19, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 21, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 23, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 25, 7, 0, 0), Duration.FromDays(1)), + new Period(new CalDateTime(2007, 4, 27, 7, 0, 0), Duration.FromDays(1)) }, null ); @@ -2165,12 +2164,12 @@ public void DailyByDay1() new CalDateTime(2007, 9, 27, 7, 0, 1), // End time is exclusive, not inclusive new[] { - new CalDateTime(2007, 9, 10, 7, 0, 0), - new CalDateTime(2007, 9, 13, 7, 0, 0), - new CalDateTime(2007, 9, 17, 7, 0, 0), - new CalDateTime(2007, 9, 20, 7, 0, 0), - new CalDateTime(2007, 9, 24, 7, 0, 0), - new CalDateTime(2007, 9, 27, 7, 0, 0) + new Period(new CalDateTime(2007, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 13, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 17, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 20, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 24, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 27, 7, 0, 0), Duration.FromHours(1)) }, null ); @@ -2189,16 +2188,16 @@ public void WeeklyWeekStartsLastYear() new CalDateTime(2012, 1, 15, 11, 59, 59), new[] { - new CalDateTime(2012, 1, 2, 7, 0, 0), - new CalDateTime(2012, 1, 3, 7, 0, 0), - new CalDateTime(2012, 1, 4, 7, 0, 0), - new CalDateTime(2012, 1, 5, 7, 0, 0), - new CalDateTime(2012, 1, 6, 7, 0, 0), - new CalDateTime(2012, 1, 9, 7, 0, 0), - new CalDateTime(2012, 1, 10, 7, 0, 0), - new CalDateTime(2012, 1, 11, 7, 0, 0), - new CalDateTime(2012, 1, 12, 7, 0, 0), - new CalDateTime(2012, 1, 13, 7, 0, 0) + new Period(new CalDateTime(2012, 1, 2, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 3, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 4, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 5, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 6, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 9, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 10, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 11, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 12, 7, 0, 0), Duration.Zero), + new Period(new CalDateTime(2012, 1, 13, 7, 0, 0), Duration.Zero) }, null ); @@ -2217,15 +2216,15 @@ public void WeeklyInterval1() new CalDateTime(2007, 12, 31, 11, 59, 59), new[] { - new CalDateTime(2007, 9, 10, 7, 0, 0), - new CalDateTime(2007, 9, 24, 7, 0, 0), - new CalDateTime(2007, 10, 8, 7, 0, 0), - new CalDateTime(2007, 10, 22, 7, 0, 0), - new CalDateTime(2007, 11, 5, 7, 0, 0), - new CalDateTime(2007, 11, 19, 7, 0, 0), - new CalDateTime(2007, 12, 3, 7, 0, 0), - new CalDateTime(2007, 12, 17, 7, 0, 0), - new CalDateTime(2007, 12, 31, 7, 0, 0) + new Period(new CalDateTime(2007, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 9, 24, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 10, 8, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 10, 22, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 11, 5, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 11, 19, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 12, 3, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 12, 17, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 12, 31, 7, 0, 0), Duration.FromHours(1)) }, null ); @@ -2244,19 +2243,19 @@ public void Monthly1() new CalDateTime(2008, 9, 10, 7, 0, 1), // Period end is exclusive, not inclusive new[] { - new CalDateTime(2007, 9, 10, 7, 0, 0), - new CalDateTime(2007, 10, 10, 7, 0, 0), - new CalDateTime(2007, 11, 10, 7, 0, 0), - new CalDateTime(2007, 12, 10, 7, 0, 0), - new CalDateTime(2008, 1, 10, 7, 0, 0), - new CalDateTime(2008, 2, 10, 7, 0, 0), - new CalDateTime(2008, 3, 10, 7, 0, 0), - new CalDateTime(2008, 4, 10, 7, 0, 0), - new CalDateTime(2008, 5, 10, 7, 0, 0), - new CalDateTime(2008, 6, 10, 7, 0, 0), - new CalDateTime(2008, 7, 10, 7, 0, 0), - new CalDateTime(2008, 8, 10, 7, 0, 0), - new CalDateTime(2008, 9, 10, 7, 0, 0) + new Period(new CalDateTime(2007, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 10, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 11, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2007, 12, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 1, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 2, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 3, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 4, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 5, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 6, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 7, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 8, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 9, 10, 7, 0, 0), Duration.FromHours(1)) }, null ); @@ -2275,20 +2274,20 @@ public void Yearly1() new CalDateTime(2020, 9, 10, 7, 0, 1), // Period end is exclusive, not inclusive new[] { - new CalDateTime(2007, 9, 10, 7, 0, 0), - new CalDateTime(2008, 9, 10, 7, 0, 0), - new CalDateTime(2009, 9, 10, 7, 0, 0), - new CalDateTime(2010, 9, 10, 7, 0, 0), - new CalDateTime(2011, 9, 10, 7, 0, 0), - new CalDateTime(2012, 9, 10, 7, 0, 0), - new CalDateTime(2013, 9, 10, 7, 0, 0), - new CalDateTime(2014, 9, 10, 7, 0, 0), - new CalDateTime(2015, 9, 10, 7, 0, 0), - new CalDateTime(2016, 9, 10, 7, 0, 0), - new CalDateTime(2017, 9, 10, 7, 0, 0), - new CalDateTime(2018, 9, 10, 7, 0, 0), - new CalDateTime(2019, 9, 10, 7, 0, 0), - new CalDateTime(2020, 9, 10, 7, 0, 0) + new Period(new CalDateTime(2007, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2008, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2009, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2010, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2011, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2012, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2013, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2014, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2015, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2016, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2017, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2018, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2019, 9, 10, 7, 0, 0), Duration.FromHours(1)), + new Period(new CalDateTime(2020, 9, 10, 7, 0, 0), Duration.FromHours(1)) }, null ); @@ -2312,13 +2311,13 @@ public void Bug2912657() new CalDateTime(2009, 12, 12, 0, 0, 0, localTzid), new[] { - new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 5, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 6, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 7, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 8, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 9, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 10, 2, 00, 00, localTzid) + new Period(new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 5, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 6, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 7, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 8, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 9, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 10, 2, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 0 @@ -2331,7 +2330,7 @@ public void Bug2912657() new CalDateTime(2009, 12, 10), new[] { - new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid) + new Period(new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 1 @@ -2344,8 +2343,8 @@ public void Bug2912657() new CalDateTime(2009, 12, 12), new[] { - new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid), - new CalDateTime(2009, 12, 11, 2, 00, 00, localTzid) + new Period(new CalDateTime(2009, 12, 4, 2, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2009, 12, 11, 2, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 2 @@ -2370,8 +2369,8 @@ public void Bug2916581() new CalDateTime(2010, 1, 3, 0, 0, 0, localTzid), new[] { - new CalDateTime(2009, 12, 25, 11, 00, 00, localTzid), - new CalDateTime(2010, 1, 1, 11, 00, 00, localTzid) + new Period(new CalDateTime(2009, 12, 25, 11, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 1, 1, 11, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 0 @@ -2384,8 +2383,8 @@ public void Bug2916581() new CalDateTime(2010, 1, 3, 0, 0, 0, localTzid), new[] { - new CalDateTime(2009, 12, 26, 11, 00, 00, localTzid), - new CalDateTime(2010, 1, 2, 11, 00, 00, localTzid) + new Period(new CalDateTime(2009, 12, 26, 11, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 1, 2, 11, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 1 @@ -2409,13 +2408,13 @@ public void Bug2959692() new CalDateTime(2008, 4, 1, 0, 0, 0, localTzid), new[] { - new CalDateTime(2008, 1, 3, 17, 00, 00, localTzid), - new CalDateTime(2008, 1, 17, 17, 00, 00, localTzid), - new CalDateTime(2008, 1, 31, 17, 00, 00, localTzid), - new CalDateTime(2008, 2, 14, 17, 00, 00, localTzid), - new CalDateTime(2008, 2, 28, 17, 00, 00, localTzid), - new CalDateTime(2008, 3, 13, 17, 00, 00, localTzid), - new CalDateTime(2008, 3, 27, 17, 00, 00, localTzid) + new Period(new CalDateTime(2008, 1, 3, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 1, 17, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 1, 31, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 2, 14, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 2, 28, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 3, 13, 17, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2008, 3, 27, 17, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 0 @@ -2439,12 +2438,12 @@ public void Bug2966236() new CalDateTime(2010, 3, 1, 0, 0, 0, localTzid), new[] { - new CalDateTime(2010, 1, 19, 8, 00, 00, localTzid), - new CalDateTime(2010, 1, 26, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 2, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 9, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 16, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 23, 8, 00, 00, localTzid) + new Period(new CalDateTime(2010, 1, 19, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 1, 26, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 2, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 9, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 16, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 23, 8, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 0 @@ -2456,10 +2455,10 @@ public void Bug2966236() new CalDateTime(2010, 3, 1, 0, 0, 0, localTzid), new[] { - new CalDateTime(2010, 2, 2, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 9, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 16, 8, 00, 00, localTzid), - new CalDateTime(2010, 2, 23, 8, 00, 00, localTzid) + new Period(new CalDateTime(2010, 2, 2, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 9, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 16, 8, 00, 00, localTzid), Duration.FromMinutes(30)), + new Period(new CalDateTime(2010, 2, 23, 8, 00, 00, localTzid), Duration.FromMinutes(30)) }, null, 0 @@ -2481,7 +2480,7 @@ public void Bug3007244() cal: iCal, fromDate: new CalDateTime(2010, 7, 18), toDate: new CalDateTime(2010, 7, 26), - dateTimes: new[] { new CalDateTime(2010, 05, 23) }, + expectedPeriods: new[] { new Period(new CalDateTime(2010, 05, 23), Duration.FromDays(102)) }, timeZones: null, eventIndex: 0 ); @@ -2491,7 +2490,92 @@ public void Bug3007244() cal: iCal, fromDate: new CalDateTime(2011, 7, 18), toDate: new CalDateTime(2011, 7, 26), - dateTimes: new[] { new CalDateTime(2011, 05, 23) }, + expectedPeriods: new[] { new Period(new CalDateTime(2011, 05, 23), Duration.FromDays(102)) }, + timeZones: null, + eventIndex: 0 + ); + } + + [Test, Category("Recurrence")] + // If duaration is specified via DTEND or time-only, then the ducation is exact. + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DTEND;TZID=Europe/Vienna:20241020T040000", "20241020T010000/PT3H", "20241027T010000/PT3H", "20241103T010000/PT3H")] + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:PT3H", "20241020T010000/PT3H", "20241027T010000/PT3H", "20241103T010000/PT3H")] + + // specified via DTEND: exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DTEND;TZID=Europe/Vienna:20241021T040000", "20241020T010000/PT27H", "20241027T010000/PT27H", "20241103T010000/PT27H")] + // First days are applied nominal, then time exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:P1DT3H", "20241020T010000/PT27H", "20241027T010000/PT28H", "20241103T010000/PT27H")] + // Exact, because duration is time-only + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:PT27H", "20241020T010000/PT27H", "20241027T010000/PT27H", "20241103T010000/PT27H")] + + // specified via DTEND: exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DTEND;TZID=Europe/Vienna:20241027T040000", "20241020T010000/PT172H", "20241027T010000/PT172H", "20241103T010000/PT172H")] + // First days are applied nominal, then time exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:P7DT3H", "20241020T010000/PT171H", "20241027T010000/PT172H", "20241103T010000/PT171H")] + // Exact, because duration is time-only + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:PT171H", "20241020T010000/PT171H", "20241027T010000/PT171H", "20241103T010000/PT171H")] + + // specified via DTEND: exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DTEND;TZID=Europe/Vienna:20241020T023000", "20241020T010000/PT1H30M", "20241027T010000/PT1H30M", "20241103T010000/PT1H30M")] + // First days are applied nominal, then time exact + [TestCase("DTSTART;TZID=Europe/Vienna:20241020T010000", "DURATION:PT1H30M", "20241020T010000/PT1H30M", "20241027T010000/PT1H30M", "20241103T010000/PT1H30M")] + + // The following cases cover cases where DTSTART or DTEND are nonexistent. + // + // There seems to be a conflicting specification in RFC 5545 section 3.3.10 regarding nonexistent recurrences. + // + // 1) + // Recurrence rules may generate recurrence instances with an invalid + // date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM + // on a day where the local time is moved forward by an hour at 1:00 + // AM). Such recurrence instances MUST be ignored and MUST NOT be + // counted as part of the recurrence set. + // + // 2) + // If the computed local start time of a recurrence instance does not + // exist, or occurs more than once, for the specified time zone, the + // time of the recurrence instance is interpreted in the same manner + // as an explicit DATE-TIME value describing that date and time, as + // specified in Section 3.3.5. + // + // see https://github.com/ical-org/ical.net/issues/681 + [TestCase("DTSTART;TZID=Europe/Vienna:20250316T023000", "DTEND;TZID=Europe/Vienna:20250323T023000", "20250316T023000/PT168H", "20250323T023000/PT168H", "20250330T033000/PT168H")] + [TestCase("DTSTART;TZID=Europe/Vienna:20250316T023000", "DURATION:P1W", "20250316T023000/PT168H", "20250323T023000/PT168H", "20250330T033000/PT168H")] + [TestCase("DTSTART;TZID=Europe/Vienna:20250316T023000", "DURATION:P7D", "20250316T023000/PT168H", "20250323T023000/PT168H", "20250330T033000/PT168H")] + + public void DurationOfRecurrencesOverDst(string dtStart, string dtEnd, string d1, string d2, string d3) + { + var iCal = Calendar.Load($""" + BEGIN:VCALENDAR + BEGIN:VEVENT + {dtStart} + {dtEnd} + RRULE:FREQ=WEEKLY;COUNT=3 + END:VEVENT + END:VCALENDAR + """); + + var start = iCal.Events.First().Start; + + var periodSerializer = new PeriodSerializer(); + var expectedPeriods = + new[] { d1, d2, d3 } + .Where(x => x != null) + .Select(x => (Period)periodSerializer.Deserialize(new StringReader(x))) + .ToArray(); + + foreach (var p in expectedPeriods) + { + p.StartTime = p.StartTime.ToTimeZone(start.TzId); + p.EndTime = p.StartTime.Add(p.Duration.Value); + } + + // date only cannot have a time zone + EventOccurrenceTest( + cal: iCal, + fromDate: null, + toDate: null, + expectedPeriods: expectedPeriods, timeZones: null, eventIndex: 0 ); @@ -2541,7 +2625,7 @@ public void ReccurencePattern_MaxDate_StopsOnCount() var evt = new CalendarEvent { Start = new CalDateTime(2018, 1, 1, 12, 0, 0), - Duration = TimeSpan.FromHours(1) + Duration = Duration.FromHours(1) }; var pattern = new RecurrencePattern @@ -2609,7 +2693,7 @@ public void Bug3178652() var evt = new CalendarEvent { Start = new CalDateTime(2011, 1, 29, 11, 0, 0), - Duration = TimeSpan.FromHours(1.5), + Duration = Duration.FromMinutes(90), Summary = "29th February Test" }; diff --git a/Ical.Net.Tests/SerializationTests.cs b/Ical.Net.Tests/SerializationTests.cs index 7dcae04c..9d01c551 100644 --- a/Ical.Net.Tests/SerializationTests.cs +++ b/Ical.Net.Tests/SerializationTests.cs @@ -27,7 +27,7 @@ public class SerializationTests private static CalendarSerializer GetNewSerializer() => new CalendarSerializer(); private static string SerializeToString(Calendar c) => GetNewSerializer().SerializeToString(c); private static string SerializeToString(CalendarEvent e) => SerializeToString(new Calendar { Events = { e } }); - private static CalendarEvent GetSimpleEvent() => new CalendarEvent { DtStart = new CalDateTime(_nowTime), Duration = _later - _nowTime }; + private static CalendarEvent GetSimpleEvent() => new CalendarEvent { DtStart = new CalDateTime(_nowTime), Duration = (_later - _nowTime).ToDurationExact() }; private static Calendar UnserializeCalendar(string s) => Calendar.Load(s); internal static void CompareCalendars(Calendar cal1, Calendar cal2) @@ -353,9 +353,9 @@ public void AttendeesSerialized() //-Alarm [Test] - public void ZeroTimeSpan_Test() + public void ZeroDuration_Test() { - var result = new TimeSpanSerializer().SerializeToString(TimeSpan.Zero); + var result = new DurationSerializer().SerializeToString(Duration.Zero); Assert.That("P0D".Equals(result, StringComparison.Ordinal), Is.True); } diff --git a/Ical.Net.Tests/SymmetricSerializationTests.cs b/Ical.Net.Tests/SymmetricSerializationTests.cs index ffaf6ac4..b216d9aa 100644 --- a/Ical.Net.Tests/SymmetricSerializationTests.cs +++ b/Ical.Net.Tests/SymmetricSerializationTests.cs @@ -12,6 +12,7 @@ using Ical.Net.CalendarComponents; using Ical.Net.DataTypes; using Ical.Net.Serialization; +using Ical.Net.Utility; using NUnit.Framework; using NUnit.Framework.Interfaces; @@ -31,7 +32,7 @@ private static CalendarEvent GetSimpleEvent(bool useDtEnd = true) if (useDtEnd) evt.DtEnd = new CalDateTime(_later); else - evt.Duration = _later - _nowTime; + evt.Duration = (_later - _nowTime).ToDurationExact(); return evt; } @@ -73,7 +74,7 @@ private static IEnumerable Event_TestCasesInt(bool useDtEnd) if (useDtEnd) e.DtEnd = new CalDateTime(_later); else - e.Duration = _later - _nowTime; + e.Duration = (_later - _nowTime).ToDurationExact(); var calendar = new Calendar(); calendar.Events.Add(e); diff --git a/Ical.Net/CalendarComponents/Alarm.cs b/Ical.Net/CalendarComponents/Alarm.cs index 3ad781db..531e1747 100644 --- a/Ical.Net/CalendarComponents/Alarm.cs +++ b/Ical.Net/CalendarComponents/Alarm.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using Ical.Net.DataTypes; +using Ical.Net.Utility; namespace Ical.Net.CalendarComponents; @@ -39,9 +40,9 @@ public virtual string Description set => Properties.Set("DESCRIPTION", value); } - public virtual TimeSpan Duration + public virtual Duration Duration { - get => Properties.Get("DURATION"); + get => Properties.Get("DURATION"); set => Properties.Set("DURATION", value); } @@ -92,7 +93,7 @@ public virtual IList GetOccurrences(IRecurringComponent rc, IDa fromDate = rc.Start.Copy(); } - var d = default(TimeSpan); + Duration? d = null; foreach (var o in rc.GetOccurrences(fromDate, toDate)) { var dt = o.Period.StartTime; @@ -101,15 +102,15 @@ public virtual IList GetOccurrences(IRecurringComponent rc, IDa if (o.Period.EndTime != null) { dt = o.Period.EndTime; - if (d == default) + if (d == null) { d = o.Period.Duration!.Value; // the getter always returns a value } } // Use the "last-found" duration as a reference point - else if (d != default(TimeSpan)) + else if (d != null) { - dt = o.Period.StartTime.Add(d); + dt = o.Period.StartTime.Add(d.Value); } else { diff --git a/Ical.Net/CalendarComponents/CalendarEvent.cs b/Ical.Net/CalendarComponents/CalendarEvent.cs index c947e9b2..e22d6746 100644 --- a/Ical.Net/CalendarComponents/CalendarEvent.cs +++ b/Ical.Net/CalendarComponents/CalendarEvent.cs @@ -80,13 +80,13 @@ public virtual IDateTime? DtEnd /// an 'eventprop', but 'dtend' and 'duration' /// MUST NOT occur in the same 'eventprop' /// - public virtual TimeSpan? Duration + public virtual Duration? Duration { - get => Properties.Get("DURATION"); + get => Properties.Get("DURATION"); set { if (DtEnd is not null) throw new InvalidOperationException("DURATION property cannot be set when DTEND property is not null."); - SetProperty("DURATION", value); + SetProperty("DURATION", value); } } @@ -95,14 +95,14 @@ public virtual TimeSpan? Duration /// /// If the property is not null, its value will be returned.
/// If and are set, it will return minus .
- /// Otherwise, it will return . + /// Otherwise, it will return . ///
/// /// Note: For recurring events, the exact duration of individual occurrences may vary due to DST transitions /// of the given and timezones. /// /// The time span that gets added to the period start time to get the period end time. - internal TimeSpan GetTimeSpanToAddToPeriodStartTime() + internal Duration GetEffectiveDuration() { // 3.8.5.3. Recurrence Rule // If the duration of the recurring component is specified with the @@ -113,7 +113,11 @@ internal TimeSpan GetTimeSpanToAddToPeriodStartTime() if (Duration is not null) return Duration.Value; - System.Diagnostics.Debug.Assert(DtStart is not null); + if (DtStart is not { } dtStart) + { + // Mustn't happen + throw new InvalidOperationException("DtStart must be set."); + } if (DtEnd is not null) { @@ -131,17 +135,17 @@ because the caller will set the period end time to the same timezone as the event end time. This finally leads to an exact duration calculation from the zoned start time to the zoned end time. */ - return DtEnd.Value - DtStart.Value; + return DtEnd.Subtract(dtStart); } - if (!DtStart.HasTime) + if (!dtStart.HasTime) { // RFC 5545 3.6.1: // For cases where a "VEVENT" calendar component // specifies a "DTSTART" property with a DATE value type but no // "DTEND" nor "DURATION" property, the event’s duration is taken to // be one day. - return TimeSpan.FromDays(1); + return DataTypes.Duration.FromDays(1); } // For DtStart.HasTime but no DtEnd - also the default case @@ -151,7 +155,7 @@ calculation from the zoned start time to the zoned end time. // specifies a "DTSTART" property with a DATE-TIME value type but no // "DTEND" property, the event ends on the same calendar date and // time of day specified by the "DTSTART" property. - return TimeSpan.Zero; + return DataTypes.Duration.Zero; } /// diff --git a/Ical.Net/CalendarComponents/Todo.cs b/Ical.Net/CalendarComponents/Todo.cs index 8679b2fa..86e38815 100644 --- a/Ical.Net/CalendarComponents/Todo.cs +++ b/Ical.Net/CalendarComponents/Todo.cs @@ -10,6 +10,7 @@ using System.Runtime.Serialization; using Ical.Net.DataTypes; using Ical.Net.Evaluation; +using Ical.Net.Utility; namespace Ical.Net.CalendarComponents; @@ -30,19 +31,6 @@ public virtual IDateTime Completed set => Properties.Set("COMPLETED", value); } - /// - /// The start date/time of the todo item. - /// - public override IDateTime DtStart - { - get => base.DtStart; - set - { - base.DtStart = value; - ExtrapolateTimes(2); - } - } - /// /// The due date of the todo item. /// @@ -52,7 +40,6 @@ public virtual IDateTime Due set { Properties.Set("DUE", value); - ExtrapolateTimes(0); } } @@ -69,13 +56,12 @@ public virtual IDateTime Due // // Therefore, Duration is not serialized, as Due // should always be extrapolated from the duration. - public virtual TimeSpan Duration + public virtual Duration? Duration { - get => Properties.Get("DURATION"); + get => Properties.Get("DURATION"); set { Properties.Set("DURATION", value); - ExtrapolateTimes(1); } } @@ -190,26 +176,4 @@ protected override void OnDeserializing(StreamingContext context) //ToDo: a necessary evil, for now base.OnDeserializing(context); } - - private void ExtrapolateTimes(int source) - { - /* - * Source values, a fix introduced to prevent StackOverflow exceptions from occuring. - * 0 = Due - * 1 = Duration - * 2 = DtStart - */ - if (Due == null && DtStart != null && Duration != default(TimeSpan) && source != 0) - { - Due = DtStart.Add(Duration); - } - else if (Duration == default(TimeSpan) && DtStart != null && Due != null && source != 1) - { - Duration = Due.Subtract(DtStart); - } - else if (DtStart == null && Duration != default(TimeSpan) && Due != null && source != 2) - { - DtStart = Due.Subtract(Duration); - } - } } diff --git a/Ical.Net/CalendarComponents/VTimeZone.cs b/Ical.Net/CalendarComponents/VTimeZone.cs index d87597f4..5e37e6fb 100644 --- a/Ical.Net/CalendarComponents/VTimeZone.cs +++ b/Ical.Net/CalendarComponents/VTimeZone.cs @@ -74,7 +74,7 @@ public static VTimeZone FromDateTimeZone(string tzId, DateTime earlistDateTimeTo var interval = new ZoneInterval( name: vTimeZone._nodaZone.Id, start: Instant.FromDateTimeOffset(start), - end: Instant.FromDateTimeOffset(start) + Duration.FromHours(1), + end: Instant.FromDateTimeOffset(start) + NodaTime.Duration.FromHours(1), wallOffset: vTimeZone._nodaZone.MinOffset, savings: Offset.Zero); intervals.Add(interval); @@ -243,7 +243,7 @@ private static void PopulateTimeZoneInfoRecurrenceDates(VTimeZoneInfo tzi, List< { var periodList = new PeriodList(); var time = interval.IsoLocalStart.ToDateTimeUnspecified(); - var date = new CalDateTime(time, true).Add(delta) as CalDateTime; + var date = new CalDateTime(time, true).Add(delta.ToDurationExact()) as CalDateTime; if (date == null) { continue; diff --git a/Ical.Net/DataTypes/CalDateTime.cs b/Ical.Net/DataTypes/CalDateTime.cs index 771d0033..0de15b57 100644 --- a/Ical.Net/DataTypes/CalDateTime.cs +++ b/Ical.Net/DataTypes/CalDateTime.cs @@ -414,53 +414,94 @@ public DateTime Value private static TimeOnly? TruncateTimeToSeconds(DateTime dateTime) => new TimeOnly(dateTime.Hour, dateTime.Minute, dateTime.Second); /// - public IDateTime ToTimeZone(string otherTzId) + IDateTime IDateTime.ToTimeZone(string? otherTzId) => ToTimeZone(otherTzId); + + public CalDateTime ToTimeZone(string? otherTzId) { - if (IsFloating) return new CalDateTime(_dateOnly, _timeOnly, otherTzId); + if (otherTzId is null) + return new CalDateTime(Value, null, HasTime); - var zonedOriginal = DateUtil.ToZonedDateTimeLeniently(Value, TzId); - var converted = zonedOriginal.WithZone(DateUtil.GetZone(otherTzId)); + ZonedDateTime converted; + if (IsFloating) + { + // Make sure, we properly fix the time if it dosen't exist in the target tz. + converted = DateUtil.ToZonedDateTimeLeniently(Value, otherTzId); + } + else + { + var zonedOriginal = DateUtil.ToZonedDateTimeLeniently(Value, TzId); + converted = zonedOriginal.WithZone(DateUtil.GetZone(otherTzId)); + } return converted.Zone == DateTimeZone.Utc ? new CalDateTime(converted.ToDateTimeUtc(), UtcTzId) : new CalDateTime(converted.ToDateTimeUnspecified(), otherTzId); } - /// + /// /// /// Thrown when attempting to add a time span to a date-only instance, /// and the time span is not a multiple of full days. /// - public IDateTime Add(TimeSpan ts) + public IDateTime Add(Duration d) { - if (!HasTime && (ts.Ticks % TimeSpan.TicksPerDay) != 0) + if (!HasTime && d.HasTime) { throw new InvalidOperationException("This instance represents a 'date-only' value. Only multiples of full days can be added to a 'date-only' instance."); } - // Ensure to handle DST transitions correctly when timezones are involved. - var newDateTime = TzId is null ? Value.Add(ts) : AsUtc.Add(ts); + // RFC 5545 3.3.6: + // If the property permits, multiple "duration" values are specified by a COMMA-separated + // list of values.The format is based on the[ISO.8601.2004] complete representation basic + // format with designators for the duration of time.The format can represent nominal + // durations(weeks and days) and accurate durations(hours, minutes, and seconds). + // Note that unlike[ISO.8601.2004], this value type doesn't support the "Y" and "M" + // designators to specify durations in terms of years and months. + // + // The duration of a week or a day depends on its position in the calendar. In the case + // of discontinuities in the time scale, such as the change from standard time to daylight + // time and back, the computation of the exact duration requires the subtraction or + // addition of the change of duration of the discontinuity.Leap seconds MUST NOT be + // considered when computing an exact duration.When computing an exact duration, the + // greatest order time components MUST be added first, that is, the number of days MUST be + // added first, followed by the number of hours, number of minutes, and number of seconds. + + (TimeSpan? nominalPart, TimeSpan? exactPart) dt; + if (TzId is null) + dt = (d.ToTimeSpan(), null); + else + dt = (d.HasDate ? d.DateAsTimeSpan : null, d.HasTime ? d.TimeAsTimeSpan : null); + + var newDateTime = this; + if (dt.nominalPart is not null) + newDateTime = new CalDateTime(newDateTime.Value.Add(dt.nominalPart.Value), TzId, HasTime); + + if (dt.exactPart is not null) + newDateTime = new CalDateTime(newDateTime.AsUtc.Add(dt.exactPart.Value), UtcTzId, HasTime); + + if (TzId is not null) + // Convert to the original timezone even if already set to ensure we're not in a non-existing time. + newDateTime = newDateTime.ToTimeZone(TzId); - var copy = Copy(); - copy._dateOnly = DateOnly.FromDateTime(newDateTime); - copy._timeOnly = HasTime ? TruncateTimeToSeconds(newDateTime) : null; - copy._tzId = TzId is null ? null : UtcTzId; + AssociateWith(this); - return TzId is null ? copy : copy.ToTimeZone(TzId); + return newDateTime; } - /// Returns a new from subtracting the specified from to the value of this instance. - /// - public TimeSpan Subtract(IDateTime dt) => AsUtc - dt.AsUtc; + /// + public TimeSpan SubtractExact(IDateTime dt) => AsUtc - dt.AsUtc; - /// Returns a new by subtracting the specified from the value of this instance. - /// An interval. - /// An object whose value is the difference of the date and time represented by this instance and the time interval represented by . - /// - /// Thrown when attempting to subtracting a time span from a date-only instance, - /// and the time span is not a multiple of full days. - /// - public IDateTime Subtract(TimeSpan ts) => Add(-ts); + /// + public Duration Subtract(IDateTime dt) + { + if (this.TzId is not null) + return SubtractExact(dt).ToDurationExact(); + + if (dt.HasTime != HasTime) + throw new InvalidOperationException("Trying to calculate the difference between dates of different types. An instance of type DATE cannot be subtracted from a DATE-TIME and vice versa."); + + return (Value - dt.Value).ToDuration(); + } /// public IDateTime AddYears(int years) @@ -491,21 +532,21 @@ public IDateTime AddDays(int days) /// Thrown when attempting to add a time span to a date-only instance, /// and the time span is not a multiple of full days. /// - public IDateTime AddHours(int hours) => Add(TimeSpan.FromHours(hours)); + public IDateTime AddHours(int hours) => Add(Duration.FromHours(hours)); /// /// /// Thrown when attempting to add a time span to a date-only instance, /// and the time span is not a multiple of full days. /// - public IDateTime AddMinutes(int minutes) => Add(TimeSpan.FromMinutes(minutes)); + public IDateTime AddMinutes(int minutes) => Add(Duration.FromMinutes(minutes)); /// /// /// Thrown when attempting to add a time span to a date-only instance, /// and the time span is not a multiple of full days. /// - public IDateTime AddSeconds(int seconds) => Add(TimeSpan.FromSeconds(seconds)); + public IDateTime AddSeconds(int seconds) => Add(Duration.FromSeconds(seconds)); /// /// Returns if the current instance is less than . diff --git a/Ical.Net/DataTypes/CalendarDataType.cs b/Ical.Net/DataTypes/CalendarDataType.cs index a3889d87..0d75e2fc 100644 --- a/Ical.Net/DataTypes/CalendarDataType.cs +++ b/Ical.Net/DataTypes/CalendarDataType.cs @@ -69,7 +69,7 @@ public virtual Type GetValueType() case "DATE-TIME": return typeof(IDateTime); case "DURATION": - return typeof(TimeSpan); + return typeof(Duration); case "FLOAT": return typeof(double); case "INTEGER": @@ -179,4 +179,4 @@ public virtual T Copy() public void RemoveService(Type type) => _serviceProvider.RemoveService(type); public void RemoveService(string name) => _serviceProvider.RemoveService(name); -} \ No newline at end of file +} diff --git a/Ical.Net/DataTypes/Duration.cs b/Ical.Net/DataTypes/Duration.cs new file mode 100644 index 00000000..2748df4a --- /dev/null +++ b/Ical.Net/DataTypes/Duration.cs @@ -0,0 +1,222 @@ +// +// Copyright ical.net project maintainers and contributors. +// Licensed under the MIT license. +// + +using System; +using System.IO; +using Ical.Net.Serialization.DataTypes; + +namespace Ical.Net.DataTypes; + +/// +/// Represents an iCalendar DURATION. +/// +public struct Duration +{ + /// + /// Initializes a new instance of the struct. + /// + /// All non-null arguments must have the same sign. + /// Thrown if not all non-null arguments have the same sign. + public Duration(int? weeks = null, int? days = null, int? hours = null, int? minutes = null, int? seconds = null) + { + var sign = GetSign(weeks) ?? GetSign(days) ?? GetSign(hours) ?? GetSign(minutes) ?? GetSign(seconds) ?? 1; + if ( + ((GetSign(weeks) ?? sign) != sign) + || ((GetSign(days) ?? sign) != sign) + || ((GetSign(hours) ?? sign) != sign) + || ((GetSign(minutes) ?? sign) != sign) + || ((GetSign(seconds) ?? sign) != sign)) + { + throw new ArgumentException("All parts of a duration must have the same sign."); + } + + Weeks = weeks; + Days = days; + Hours = hours; + Minutes = minutes; + Seconds = seconds; + } + + /// + /// Gets the number of weeks. + /// + public int? Weeks { get; private set; } + + /// + /// Gets the number of days. + /// + public int? Days { get; private set; } + + /// + /// Gets the number of hours. + /// + public int? Hours { get; private set; } + + /// + /// Gets the number of minutes. + /// + public int? Minutes { get; private set; } + + /// + /// Gets the number of seconds. + /// + public int? Seconds { get; private set; } + + /// + /// Returns +1 if the duration is positive or zero, -1 if the duration is negative. + /// + public int Sign => GetSign(Weeks) ?? GetSign(Days) ?? GetSign(Hours) ?? GetSign(Minutes) ?? GetSign(Seconds) ?? 1; + + /// + /// Gets a value indicating whether this instance has a date component. + /// + public bool HasDate => ((Weeks ?? 0) != 0) || ((Days ?? 0) != 0); + + /// + /// Gets a value indicating whether this instance has a time component. + /// + public bool HasTime => ((Hours ?? 0) != 0) || ((Minutes ?? 0) != 0) || ((Seconds ?? 0) != 0); + + /// + /// Gets an instance representing a duration of zero. + /// + public static Duration Zero { get; } = new Duration(); + + /// + /// Gets an instance representing a duration of the given number of weeks. + /// + public static Duration FromWeeks(int weeks) => + new Duration(weeks: weeks); + + /// + /// Gets an instance representing a duration of the given number of days. + /// + public static Duration FromDays(int days) => + new Duration(days: days); + + /// + /// Gets an instance representing a duration of the given number of hours. + /// + public static Duration FromHours(int hours) => + new Duration(hours: hours); + + /// + /// Gets an instance representing a duration of the given number of minutes. + /// + public static Duration FromMinutes(int minutes) => + new Duration(minutes: minutes); + + /// + /// Gets an instance representing a duration of the given number of seconds. + /// + public static Duration FromSeconds(int seconds) => + new Duration(seconds: seconds); + + /// + /// Parses the specified value according to RFC 5545. + /// + /// Thrown if the value is not a valid duration. + public static Duration Parse(string value) => (Duration)new DurationSerializer().Deserialize(new StringReader(value)); + + /// + /// Creates an instance that represents the given time span as exact value, that is, time-only. + /// + /// + /// According to RFC5545 the weeks and day fields of a duration are considered nominal durations while the time fields are considered exact values. + /// + internal static Duration FromTimeSpanExact(TimeSpan t) + // As a TimeSpan always refers to exact time, we specify days as part of the hours field, + // because time is added as exact values rather than nominal according to RFC 5545. + => new Duration(hours: NullIfZero(t.Days * 24 + t.Hours), minutes: NullIfZero(t.Minutes), seconds: NullIfZero(t.Seconds)); + + /// + /// Creates an instance that represents the given time span, treating the days as nominal duration and the time part as exact. + /// + /// + /// According to RFC5545 the weeks and day fields of a duration are considered nominal durations while the time fields are considered exact values. + /// + internal static Duration FromTimeSpan(TimeSpan t) + => new Duration(days: NullIfZero(t.Days), hours: NullIfZero(t.Hours), minutes: NullIfZero(t.Minutes), seconds: NullIfZero(t.Seconds)); + + /// + /// Gets a value representing the time parts of the given instance. + /// + internal TimeSpan TimeAsTimeSpan + { + get + { + return new TimeSpan( + 0, + Hours ?? 0, + Minutes ?? 0, + Seconds ?? 0); + } + } + + /// + /// Gets a value representing the date parts (days and weeks) of the given instance. + /// + internal TimeSpan DateAsTimeSpan + { + get + { + return new TimeSpan( + (Weeks ?? 0) * 7 + (Days ?? 0), + 0, + 0, + 0); + } + } + + /// + /// Convert the instance to a . + /// + internal TimeSpan ToTimeSpan() + => new TimeSpan( + (Weeks ?? 0) * 7 + (Days ?? 0), + Hours ?? 0, + Minutes ?? 0, + Seconds ?? 0); + + /// + /// Gets a value indicating whether the duration is zero, that is, all fields are null or 0. + /// + internal bool IsZero + => ((Weeks ?? 0) == 0) + && ((Days ?? 0) == 0) + && ((Hours ?? 0) == 0) + && ((Minutes ?? 0) == 0) + && ((Seconds ?? 0) == 0); + + /// + /// Gets a value indicating whether the duration is empty, that is, all fields are null. + /// + internal bool IsEmpty + => (Weeks == null) + && (Days == null) + && (Hours == null) + && (Minutes == null) + && (Seconds == null); + + /// + /// Returns a negated copy of the given instance. + /// + public static Duration operator-(Duration d) => + new Duration(-d.Weeks, -d.Days, -d.Hours, -d.Minutes, -d.Seconds); + + /// + public override string ToString() + => new DurationSerializer().SerializeToString(this); + + private static int? GetSign(int? v) => + v switch + { + null => null, + >= 0 => 1, + < 0 => -1 + }; + + private static int? NullIfZero(int v) => (v == 0) ? null : v; +} diff --git a/Ical.Net/DataTypes/IDateTime.cs b/Ical.Net/DataTypes/IDateTime.cs index 9f79a333..67eb2d65 100644 --- a/Ical.Net/DataTypes/IDateTime.cs +++ b/Ical.Net/DataTypes/IDateTime.cs @@ -108,16 +108,41 @@ public interface IDateTime : IEncodableDataType, IComparable, IFormat /// /// Converts the to a date/time - /// within the specified timezone. + /// within the specified timezone or + /// to floating time if is null. /// /// If == /// it means that the is considered as local time for every timezone: /// The returned is unchanged and the is set as . /// - IDateTime ToTimeZone(string otherTzId); - IDateTime Add(TimeSpan ts); - IDateTime Subtract(TimeSpan ts); - TimeSpan Subtract(IDateTime dt); + IDateTime ToTimeZone(string? otherTzId); + + /// + /// Add the specified to this instance/>. + /// + /// + /// In correspondence to RFC5545, the weeks and day fields of a duration are considered nominal durations while the time fields are considered exact values. + /// + IDateTime Add(Duration d); + + /// + /// Returns a new from subtracting the specified from to the value of this instance. + /// The returned value represents the exact time difference. I.e. the calculation is done after converting both operands to UTC. + /// In case of floating time, no conversion is performed. + /// + TimeSpan SubtractExact(IDateTime dt); + + /// + /// Returns a new from subtracting the specified from to the value of this instance. + /// + /// + /// If the operands are date-only, the returned value will be date-only as well, so it + /// can be used with . Otherwise the returned value represents + /// the exact difference between the two operands, i.e. if the operands are non-floating, + /// they will be converted to UTC before the subtraction. + /// + Duration Subtract(IDateTime dt); + IDateTime AddYears(int years); IDateTime AddMonths(int months); IDateTime AddDays(int days); diff --git a/Ical.Net/DataTypes/Period.cs b/Ical.Net/DataTypes/Period.cs index b23f4d59..31527302 100644 --- a/Ical.Net/DataTypes/Period.cs +++ b/Ical.Net/DataTypes/Period.cs @@ -35,7 +35,7 @@ public Period(IDateTime start, IDateTime? end = null) } StartTime = start ?? throw new ArgumentNullException(nameof(start)); - _endTime = end; + EndTime = end; } /// @@ -45,15 +45,13 @@ public Period(IDateTime start, IDateTime? end = null) /// /// /// - public Period(IDateTime start, TimeSpan duration) + public Period(IDateTime start, Duration duration) { - if (duration < TimeSpan.Zero) - { + if (duration.Sign < 0) throw new ArgumentException("Duration must be greater than or equal to zero.", nameof(duration)); - } StartTime = start; - _duration = duration; + Duration = duration; } /// @@ -64,8 +62,8 @@ public override void CopyFrom(ICopyable obj) if (obj is not Period p) return; StartTime = p.StartTime.Copy(); - _endTime = p._endTime?.Copy(); - _duration = p._duration; + EndTime = p.EndTime?.Copy(); + Duration = p.Duration; } protected bool Equals(Period other) => Equals(StartTime, other.StartTime) && Equals(EndTime, other.EndTime) && Duration.Equals(other.Duration); @@ -102,8 +100,6 @@ public override string ToString() /// public virtual IDateTime StartTime { get; set; } = null!; - private IDateTime? _endTime; - /// /// Gets either the end time of the period that was set, /// or calculates the exact end time based on the nominal duration. @@ -112,20 +108,7 @@ public override string ToString() /// Either the or the can be set at a time. /// The last one set will be stored, and the other will be calculated. /// - public virtual IDateTime? EndTime - { - get => _endTime ?? (_duration != null ? StartTime.Add(_duration.Value) : null); - set - { - _endTime = value; - if (_endTime != null) - { - _duration = null; - } - } - } - - private TimeSpan? _duration; + public virtual IDateTime? EndTime { get; set; } /// /// Gets either the nominal duration of the period that was set, @@ -138,34 +121,28 @@ public virtual IDateTime? EndTime /// A that has a date-only , no /// and no duration set, is considered to last for one day. /// - public virtual TimeSpan? Duration + public virtual Duration? Duration { get; set; } + + internal Duration GetEffectiveDuration() { - get - { - if (_endTime == null && !StartTime.HasTime) - { - return TimeSpan.FromDays(1); - } - return _duration ?? _endTime?.Subtract(StartTime); - } - set - { - _duration = value; - if (_duration != null) - { - _endTime = null; - } - } + if (Duration is { } d) + return d; + + if (EndTime is { } endTime) + return endTime.Subtract(StartTime); + + if (!StartTime.HasTime) + return DataTypes.Duration.FromDays(1); + + return DataTypes.Duration.Zero; } - /// - /// Gets the original start time, end time, and duration as they were set, - /// while or properties may be calculated. - /// - /// - public (IDateTime StartTime, IDateTime? EndTime, TimeSpan? Duration) GetOriginalValues() + internal IDateTime GetEffectiveEndTime() { - return (StartTime, _endTime, _duration); + if (EndTime is { } endTime) + return endTime; + + return StartTime.Add(GetEffectiveDuration()); } /// @@ -183,8 +160,9 @@ public virtual bool Contains(IDateTime? dt) return false; } + var endTime = GetEffectiveEndTime(); // End time is exclusive - return EndTime == null || EndTime.GreaterThan(dt); + return endTime == null || endTime.GreaterThan(dt); } /// @@ -198,17 +176,10 @@ public virtual bool Contains(IDateTime? dt) /// /// public virtual bool CollidesWith(Period period) - { - // Check if the start or end time of the given period is within the current period - var startContained = Contains(period.StartTime); - var endContained = period.EndTime != null && Contains(period.EndTime); - - // Check if the current period is completely within the given period - var currentStartContained = period.Contains(StartTime); - var currentEndContained = EndTime != null && period.Contains(EndTime); - - return startContained || endContained || currentStartContained || currentEndContained; - } + => Contains(period.StartTime) + || period.Contains(StartTime) + || Contains(period.GetEffectiveEndTime()) + || period.Contains(GetEffectiveEndTime()); public int CompareTo(Period? other) { diff --git a/Ical.Net/DataTypes/Trigger.cs b/Ical.Net/DataTypes/Trigger.cs index d527c290..ebefcfbb 100644 --- a/Ical.Net/DataTypes/Trigger.cs +++ b/Ical.Net/DataTypes/Trigger.cs @@ -16,7 +16,7 @@ namespace Ical.Net.DataTypes; public class Trigger : EncodableDataType { private IDateTime _mDateTime; - private TimeSpan? _mDuration; + private Duration? _mDuration; private string _mRelated = TriggerRelation.Start; public virtual IDateTime DateTime @@ -45,7 +45,7 @@ public virtual IDateTime DateTime } } - public virtual TimeSpan? Duration + public virtual Duration? Duration { get => _mDuration; set @@ -71,7 +71,7 @@ public virtual string Related public Trigger() { } - public Trigger(TimeSpan ts) + public Trigger(Duration ts) { Duration = ts; } diff --git a/Ical.Net/Evaluation/EventEvaluator.cs b/Ical.Net/Evaluation/EventEvaluator.cs index fd44b334..89de4ca4 100644 --- a/Ical.Net/Evaluation/EventEvaluator.cs +++ b/Ical.Net/Evaluation/EventEvaluator.cs @@ -69,10 +69,10 @@ It evaluates the event's definition of DtStart and either DtEnd or Duration. The exact duration is calculated from the zoned end time and the zoned start time, and it may differ from the time span added to the period start time. */ - var tsToAdd = CalendarEvent.GetTimeSpanToAddToPeriodStartTime(); + var tsToAdd = CalendarEvent.GetEffectiveDuration(); IDateTime endTime; - if (tsToAdd == TimeSpan.Zero) + if (tsToAdd.IsZero) { // For a zero-duration event, the end time is the same as the start time. endTime = period.StartTime; @@ -80,14 +80,14 @@ and it may differ from the time span added to the period start time. else { // Calculate the end time of the event as a DateTime - var endDt = period.StartTime.Value.Add(tsToAdd); + var endDt = period.StartTime.Add(tsToAdd); + if ((CalendarEvent.End is { } end) && (end.TzId != period.StartTime.TzId) && (end.TzId is { } tzid)) + { + // Ensure the end time has the same timezone as the event end time. + endDt = endDt.ToTimeZone(tzid); + } - // Create a CalDateTime object with the calculated end time. - // Ensure date-only or date-time consistency with the start time. - endTime = new CalDateTime( - DateOnly.FromDateTime(endDt), - period.StartTime.HasTime ? TimeOnly.FromDateTime(endDt) : null, - CalendarEvent.End?.TzId ?? CalendarEvent.Start.TzId); + endTime = endDt; } // Return the Period object with the calculated end time and duration. diff --git a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs index 8fdccc45..cb9d8e6f 100644 --- a/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs +++ b/Ical.Net/Evaluation/RecurrencePatternEvaluator.cs @@ -943,7 +943,11 @@ private static Period CreatePeriod(DateTime dateTime, IDateTime referenceDate) { // Turn each resulting date/time into an IDateTime and associate it // with the reference date. - IDateTime newDt = new CalDateTime(dateTime, referenceDate.TzId, referenceDate.HasTime); + IDateTime newDt = new CalDateTime(dateTime, null, referenceDate.HasTime); + if (referenceDate.TzId != null) { + // Adjust nonexistent recurrence instances according to RFC 5545 3.3.5 + newDt = newDt.ToTimeZone(referenceDate.TzId); + } newDt.AssociateWith(referenceDate); diff --git a/Ical.Net/Evaluation/TodoEvaluator.cs b/Ical.Net/Evaluation/TodoEvaluator.cs index d7d9ddd5..17e268f3 100644 --- a/Ical.Net/Evaluation/TodoEvaluator.cs +++ b/Ical.Net/Evaluation/TodoEvaluator.cs @@ -90,14 +90,14 @@ Period PeriodWithDuration(Period p) var period = p.Copy(); - period.Duration = Todo.Duration; - if (period.Duration != default) + var d = Todo.Duration; + if (d != null) { - period.EndTime = period.StartTime.Add(Todo.Duration); + period.EndTime = period.StartTime.Add(d.Value); } else { - period.Duration = Todo.Duration; + period.Duration = default; } return period; diff --git a/Ical.Net/Serialization/DataTypeMapper.cs b/Ical.Net/Serialization/DataTypeMapper.cs index 872faedc..b4710b8d 100644 --- a/Ical.Net/Serialization/DataTypeMapper.cs +++ b/Ical.Net/Serialization/DataTypeMapper.cs @@ -37,7 +37,7 @@ public DataTypeMapper() AddPropertyMapping("DTSTAMP", typeof(IDateTime), false); AddPropertyMapping("DTSTART", typeof(IDateTime), false); AddPropertyMapping("DUE", typeof(IDateTime), false); - AddPropertyMapping("DURATION", typeof(TimeSpan), false); + AddPropertyMapping("DURATION", typeof(Duration), false); AddPropertyMapping("EXDATE", typeof(PeriodList), false); AddPropertyMapping("EXRULE", typeof(RecurrencePattern), false); AddPropertyMapping("FREEBUSY", typeof(FreeBusyEntry), true); @@ -149,4 +149,4 @@ public virtual Type GetPropertyMapping(object obj) ? m.ObjectType : m.Resolver(p); } -} \ No newline at end of file +} diff --git a/Ical.Net/Serialization/DataTypes/DurationSerializer.cs b/Ical.Net/Serialization/DataTypes/DurationSerializer.cs new file mode 100644 index 00000000..7f86f807 --- /dev/null +++ b/Ical.Net/Serialization/DataTypes/DurationSerializer.cs @@ -0,0 +1,103 @@ +// +// Copyright ical.net project maintainers and contributors. +// Licensed under the MIT license. +// + +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using Ical.Net.DataTypes; + +namespace Ical.Net.Serialization.DataTypes; + +public class DurationSerializer : SerializerBase +{ + public DurationSerializer() { } + + public DurationSerializer(SerializationContext ctx) : base(ctx) { } + + public override Type TargetType => typeof(Duration); + + public override string SerializeToString(object obj) + => (obj is not Duration duration) ? null : SerializeToString(duration); + + private static string SerializeToString(Duration ts) + { + if (ts.IsEmpty) + return "P0D"; + + var sb = new StringBuilder(); + + var sign = ts.Sign; + if (sign < 0) + sb.Append('-'); + + sb.Append('P'); + if (ts.Weeks != null) + sb.Append($"{sign * ts.Weeks}W"); + if (ts.Days != null) + sb.Append($"{sign * ts.Days}D"); + + if (ts.Hours != null || ts.Minutes != null || ts.Seconds != null) + { + sb.Append('T'); + if (ts.Hours != null) + sb.Append($"{sign * ts.Hours}H"); + if (ts.Minutes != null) + sb.Append($"{sign * ts.Minutes}M"); + if (ts.Seconds != null) + sb.Append($"{sign * ts.Seconds}S"); + } + + return sb.ToString(); + } + + internal static readonly Regex TimespanMatch = + new Regex(@"^(?\+|-)?P(((?\d+)W)|(?
((?\d+)D)?(?