From 8bcb891089ce314c0e790b5b1b4e8bb9ea5139b7 Mon Sep 17 00:00:00 2001 From: Mark Knapp Date: Thu, 22 Jan 2026 17:03:24 -0500 Subject: [PATCH] Stop todo evaluation at given datetime Fixes #913 --- Ical.Net.Tests/TodoTest.cs | 27 ++++++++++++++++++++++++++- Ical.Net/Evaluation/TodoEvaluator.cs | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Ical.Net.Tests/TodoTest.cs b/Ical.Net.Tests/TodoTest.cs index 239b98cf8..608bde0f3 100644 --- a/Ical.Net.Tests/TodoTest.cs +++ b/Ical.Net.Tests/TodoTest.cs @@ -3,7 +3,6 @@ // Licensed under the MIT license. // -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -240,4 +239,30 @@ public void Todo_WithFutureStart_AndNoDuration_ShouldSucceed() Assert.That(firstOccurrence.Period.StartTime, Is.Not.Null); Assert.That(firstOccurrence.Period.Duration, Is.Null); } + + [Test, Category("Todo")] + public void Todo_RecurrenceWithNoEnd_IsCompletedUntilNextOccurrence() + { + var start = new CalDateTime(2026, 1, 15, 0, 0, 0, "UTC"); + + var todo = new Todo + { + Start = start, + RecurrenceRules = [new("FREQ=DAILY;BYDAY=TH")], + }; + + todo.Status = "COMPLETED"; + todo.Completed = new CalDateTime(2026, 1, 16, 0, 0, 0, "UTC"); + + var results = Enumerable.Range(14, 10) + .Select(x => new CalDateTime(2026, 1, x, 0, 0, 0, "UTC")) + .Select(todo.IsCompleted) + .ToList(); + + // Jan 14-21: true (8 days) - TODO is considered completed + // Jan 22-23: false (2 days) - TODO is NOT completed + List expected = [true, true, true, true, true, true, true, true, false, false]; + + Assert.That(results, Is.EquivalentTo(expected)); + } } diff --git a/Ical.Net/Evaluation/TodoEvaluator.cs b/Ical.Net/Evaluation/TodoEvaluator.cs index 25f4fe5ca..05427ab01 100644 --- a/Ical.Net/Evaluation/TodoEvaluator.cs +++ b/Ical.Net/Evaluation/TodoEvaluator.cs @@ -48,7 +48,7 @@ internal IEnumerable EvaluateToPreviousOccurrence(CalDateTime completedD } return Evaluate(Todo.Start, beginningDate, options) - .Where(p => p.StartTime <= currDt); + .TakeWhile(p => p.StartTime <= currDt); } private static void DetermineStartingRecurrence(IEnumerable rdate, ref CalDateTime referenceDateTime)