forked from ical-org/ical.net
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix
Period
and PeriodList
to work with EXDATE
and RDATE
Improve reliability and usability for `Period` and `PeriodList` to become less error-prone by enforcing timezones being used consistently Period - Make parameterless CTOR `internal` to ensure proper initialization by users - A period can be defined 1. by a start time and an end time, 2. by a start time and a duration, 3. by a start time only, with the duration unspecified. This is for EXDATE and RDATE date-only and date/time. - For cosistency, either the `EndTime` or the `Duration` can be set at a time. The last one set with a value not `null` will prevail, while the other will become `null`. - Timezones of `StartTime`and (optional) `EndTime` must be the same - `CompareTo` uses `AsUtc` for comparing the `StartTime` - Remove returning a "magic" duration of 1 day, if `EndTime` is null and `StartTime` is date-only. This broke `EXDATE` and `RDATE` of an event, when the only a start time exists. - Added `EffectiveEndTime` and `EffectiveDuration` properties to provide calculated values based on the set values. - Update the `EndTime` and `Duration` properties to directly return the set values. - Change the access modifiers of `GetEffectiveDuration()` and `GetEffectiveEndTime` methods from internal to private. PeriodList - `TzId`: `public` setter changed to `private` - `EnsureConsistentTimezones`: The first period determines the timezone of the `PeriodList` and all other `Period`s added must have the same timezone - Add `SetService(new PeriodListEvaluator(this))` for `StringReader` CTOR overload - Add `static PeriodList FromStringReader(StringReader)` - Add `static PeriodList FromDateTime(IDateTime)` - Add `PeriodList AddPeriod(Period)` for chaining - Add `PeriodList Add(IDateTime)` for chaining - nullable enable EventEvaluator: - `EventEvaluator.WithEndTime(Period)` only sets the `EndTime`, as `Period.EffectiveDuration` returns the duration. TodoEvaluator: - Remove method `PeriodWithDuration(Period)` as it became redudant with the refactored `Period` class. DataTypeSerializer and other serializers, CalendarObjectBase: - `Activator.CreateInstance(TargetType, true)` allows for not `public` CTORs, so that parameterless CTORs can be excluded from the public API, if proper initialization can't be assured (like with `Period`). PropertySerializer: - TBD: Never set the UTC timezone ID (use appending 'Z') - Resolves ical-org#590 - Resolves ical-org#591 - Resolves ical-org#614 - Resolves ical-org#676
- Loading branch information
Showing
27 changed files
with
954 additions
and
347 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// | ||
// Copyright ical.net project maintainers and contributors. | ||
// Licensed under the MIT license. | ||
// | ||
|
||
#nullable enable | ||
using System; | ||
using System.IO; | ||
using Ical.Net.DataTypes; | ||
using NUnit.Framework; | ||
|
||
namespace Ical.Net.Tests; | ||
|
||
[TestFixture] | ||
public class PeriodListTests | ||
{ | ||
[Test] | ||
public void RemovePeriod_ShouldDecreaseCount() | ||
{ | ||
// Arrange | ||
var periodList = new PeriodList(); | ||
var period = new Period(new CalDateTime(2023, 1, 1, 0, 0, 0), Duration.FromHours(1)); | ||
periodList.Add(period); | ||
|
||
// Act | ||
periodList.Remove(period); | ||
|
||
// Assert | ||
Assert.That(periodList, Has.Count.EqualTo(0)); | ||
} | ||
|
||
[Test] | ||
public void GetSet_Period_ShouldReturnCorrectPeriod() | ||
{ | ||
// Arrange | ||
var periodList = new PeriodList(); | ||
var period1 = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0), Duration.FromHours(1)); | ||
var period2 = new Period(new CalDateTime(2025, 2, 1, 0, 0, 0), Duration.FromHours(1)); | ||
|
||
periodList.AddPeriod(period1).AddPeriod(period1); | ||
|
||
// Act | ||
var retrievedPeriod = periodList[0]; | ||
periodList[1] = period2; | ||
|
||
// Assert | ||
Assert.Multiple(() => | ||
{ | ||
Assert.That(period1, Is.EqualTo(retrievedPeriod)); | ||
Assert.That(periodList.Contains(period1), Is.True); | ||
Assert.That(periodList[periodList.IndexOf(period2)], Is.EqualTo(period2)); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void Clear_ShouldRemoveAllPeriods() | ||
{ | ||
// Arrange | ||
var periodList = new PeriodList(); | ||
var pl = PeriodList | ||
.FromDateTime(new CalDateTime(2025, 1, 2)) | ||
.Add(new CalDateTime(2025, 1, 3)); | ||
|
||
var count = pl.Count; | ||
|
||
// Act | ||
periodList.Clear(); | ||
|
||
// Assert | ||
Assert.Multiple(() => | ||
{ | ||
Assert.That(count, Is.EqualTo(2)); | ||
Assert.That(periodList, Has.Count.EqualTo(0)); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void Create_FromStringReader_ShouldSucceed() | ||
{ | ||
// Arrange | ||
const string periodString = "20250101T000000Z/20250101T010000Z,20250102T000000Z/20250102T010000Z"; | ||
using var reader = new StringReader(periodString); | ||
|
||
// Act | ||
var periodList = PeriodList.FromStringReader(reader); | ||
|
||
// Assert | ||
Assert.Multiple(() => | ||
{ | ||
Assert.That(periodList, Has.Count.EqualTo(2)); | ||
Assert.That(periodList[0].StartTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 0, 0, 0, "UTC"))); | ||
Assert.That(periodList[0].EndTime, Is.EqualTo(new CalDateTime(2025, 1, 1, 1, 0, 0, "UTC"))); | ||
Assert.That(periodList[1].StartTime, Is.EqualTo(new CalDateTime(2025, 1, 2, 0, 0, 0, "UTC"))); | ||
Assert.That(periodList[1].EndTime, Is.EqualTo(new CalDateTime(2025, 1, 2, 1, 0, 0, "UTC"))); | ||
Assert.That(periodList.IsReadOnly, Is.EqualTo(false)); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void InsertAt_ShouldInsertPeriodAtCorrectPosition() | ||
{ | ||
// Arrange | ||
var periodList = new PeriodList(); | ||
var period1 = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0), Duration.FromHours(1)); | ||
var period2 = new Period(new CalDateTime(2025, 1, 2, 0, 0, 0), Duration.FromHours(1)); | ||
var period3 = new Period(new CalDateTime(2025, 1, 3, 0, 0, 0), Duration.FromHours(1)); | ||
periodList.AddPeriod(period1).AddPeriod(period3); | ||
|
||
// Act | ||
periodList.Insert(1, period2); | ||
|
||
// Assert | ||
Assert.Multiple(() => | ||
{ | ||
Assert.That(periodList, Has.Count.EqualTo(3)); | ||
Assert.That(periodList[1], Is.EqualTo(period2)); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void RemoveAt_ShouldRemovePeriodAtCorrectPosition() | ||
{ | ||
// Arrange | ||
var periodList = new PeriodList(); | ||
var period1 = new Period(new CalDateTime(2025, 1, 1, 0, 0, 0), Duration.FromHours(1)); | ||
var period2 = new Period(new CalDateTime(2025, 1, 2, 0, 0, 0), Duration.FromHours(1)); | ||
var period3 = new Period(new CalDateTime(2025, 1, 3, 0, 0, 0), Duration.FromHours(1)); | ||
periodList.AddPeriod(period1).AddPeriod(period2).AddPeriod(period3); | ||
|
||
// Act | ||
periodList.RemoveAt(1); | ||
|
||
// Assert | ||
Assert.Multiple(() => | ||
{ | ||
Assert.That(periodList, Has.Count.EqualTo(2)); | ||
Assert.That(periodList[1], Is.EqualTo(period3)); | ||
}); | ||
} | ||
} |
Oops, something went wrong.