Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Duration type to keep apart nominal vs exact durations. #680

Merged
merged 19 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
997b3ed
Make Todo.Duration nullable
minichma Dec 25, 2024
d31f1a4
Remove Todo.ExtrapolateTimes()
minichma Dec 25, 2024
e8e562f
Test: Minor fix related to CalendarEvent.Duration being nullable now
minichma Dec 25, 2024
dc5feb7
Introduce type `Duration` and replace `TimeSpanSerializer` by `Durati…
minichma Dec 25, 2024
8e6b745
Remove redundant `CalDateTime.Subtract(TimeSpan)`, which can also be …
minichma Dec 25, 2024
2e157e4
Remove obsolete `DaetUtil.Start/EndOfDay`
minichma Dec 25, 2024
e33b8bf
Change `CalendarEvent.Duration`, `Todo.Duration`, `Trigger.Duration` …
minichma Dec 25, 2024
449571e
Rename `CalDateTime.Subtract()` -> `CalDateTime.SubtractExact()`
minichma Dec 25, 2024
13d98d7
Change `TimeSpan CalendarEvent.GetTimeSpanToAddToPeriodStartTime()` -…
minichma Dec 26, 2024
21f93b8
Fix date/time arithmetics: Keep apart nominal and exact durations.
minichma Dec 26, 2024
3b73d31
CalDateTime doc comments
minichma Dec 27, 2024
d2590b4
Change `Period.Duration` from `TimeSpan` to `Duration`. Remove extrap…
minichma Dec 26, 2024
eda7371
CalDateTimeTests: Indentation and whitespace
minichma Dec 27, 2024
9b14dd0
Test: Extend RecurrenceTest test cases to test for occurrences durati…
minichma Dec 27, 2024
d0ef8e7
Improve `CalDateTime.ToTimeZone()` conversion of floating time that d…
minichma Dec 27, 2024
1c99517
RecurrencePatternEvaluator: Adjust nonexistent recurrence instances a…
minichma Dec 27, 2024
07a55e6
Test: DurationOfRecurrencesOverDst
minichma Dec 27, 2024
17be80d
Allow `IDateTime.ToTimeZone` to convert to floating time.
minichma Dec 28, 2024
6566285
CalendarEvent: Avoid null-reference warnings.
minichma Dec 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 35 additions & 36 deletions Ical.Net.Tests/CalDateTimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");
}

Expand All @@ -176,14 +191,10 @@ public static IEnumerable DateTimeArithmeticTestCases()
.Returns(dateTime.AddHours(1))
.SetName($"{nameof(IDateTime.AddHours)} 1 hour");

yield return new TestCaseData(new Func<IDateTime, IDateTime>(dt => dt.Add(TimeSpan.FromSeconds(30))))
yield return new TestCaseData(new Func<IDateTime, IDateTime>(dt => dt.Add(Duration.FromSeconds(30))))
.Returns(dateTime.Add(TimeSpan.FromSeconds(30)))
.SetName($"{nameof(IDateTime.Add)} 30 seconds");

yield return new TestCaseData(new Func<IDateTime, IDateTime>(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<IDateTime, IDateTime>(dt => dt.AddMinutes(70)))
.Returns(dateTime.AddMinutes(70))
.SetName($"{nameof(IDateTime.AddMinutes)} 70 minutes");
Expand All @@ -197,15 +208,15 @@ public bool EqualityTests(Func<IDateTime, bool> operation)

public static IEnumerable EqualityTestCases()
{
yield return new TestCaseData(new Func<IDateTime, bool>(dt => (CalDateTime) dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: CalDateTime.UtcTzId)))
yield return new TestCaseData(new Func<IDateTime, bool>(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<IDateTime, bool>(dt => (CalDateTime) dt != new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: "Europe/Berlin")))
yield return new TestCaseData(new Func<IDateTime, bool>(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<IDateTime, bool>(dt => (CalDateTime) dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: null)))
yield return new TestCaseData(new Func<IDateTime, bool>(dt => (CalDateTime)dt == new CalDateTime(2025, 1, 15, 10, 20, 30, tzId: null)))
.Returns(false)
.SetName("== operator UTC vs. floating");
}
Expand Down Expand Up @@ -245,9 +256,9 @@ public static IEnumerable DateOnlyValidArithmeticTestCases()
{
var dateTime = new DateTime(2025, 1, 15);

yield return new TestCaseData(new Func<IDateTime, IDateTime>(dt => dt.Subtract(TimeSpan.FromDays(1))))
yield return new TestCaseData(new Func<IDateTime, IDateTime>(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<IDateTime, IDateTime>(dt => dt.AddYears(1)))
.Returns((dateTime.AddYears(1), false))
Expand All @@ -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<IDateTime, IDateTime>(dt => dt.AddHours(24)))
.Returns((dateTime.AddHours(24), false))
.SetName($"{nameof(IDateTime.AddHours)} 24 hours");

yield return new TestCaseData(new Func<IDateTime, IDateTime>(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<IDateTime, IDateTime>(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<IDateTime, IDateTime>(dt => dt.Add(TimeSpan.FromDays(1))))
yield return new TestCaseData(new Func<IDateTime, IDateTime>(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<IDateTime, IDateTime>(dt => dt.Add(TimeSpan.Zero)))
yield return new TestCaseData(new Func<IDateTime, IDateTime>(dt => dt.Add(Duration.Zero)))
.Returns((dateTime.Add(TimeSpan.Zero), false))
.SetName($"{nameof(IDateTime.Add)} TimeSpan.Zero");
}
Expand All @@ -289,7 +288,7 @@ public void DateOnlyInvalidArithmeticTests()

Assert.Multiple(() =>
{
Assert.That(() => dt.Add(TimeSpan.FromHours(1)), Throws.TypeOf<InvalidOperationException>());
Assert.That(() => dt.Add(Duration.FromHours(1)), Throws.TypeOf<InvalidOperationException>());
Assert.That(() => dt.AddHours(2), Throws.TypeOf<InvalidOperationException>());
Assert.That(() => dt.AddMinutes(3), Throws.TypeOf<InvalidOperationException>());
Assert.That(() => dt.AddSeconds(4), Throws.TypeOf<InvalidOperationException>());
Expand All @@ -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)));
Expand All @@ -325,23 +324,23 @@ public void Simple_PropertyAndMethod_HasTime_Tests()

public static IEnumerable<TestCaseData> 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()));
});
}
}
25 changes: 13 additions & 12 deletions Ical.Net.Tests/CalendarEventTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)));
});
}

Expand All @@ -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);
});
}
Expand Down
4 changes: 2 additions & 2 deletions Ical.Net.Tests/CopyComponentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<FreeBusy>();
Expand All @@ -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"
};

Expand Down
2 changes: 1 addition & 1 deletion Ical.Net.Tests/DeserializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
});
}
}
4 changes: 2 additions & 2 deletions Ical.Net.Tests/EqualityAndHashingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<RecurrencePattern> { rruleA },
};

Expand All @@ -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<RecurrencePattern> { rruleB },
});

Expand Down
32 changes: 16 additions & 16 deletions Ical.Net.Tests/PeriodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(() =>
{
Expand All @@ -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)));
});
}

Expand All @@ -42,7 +42,7 @@ public void CreatePeriodWithInvalidArgumentsShouldThrow()
Assert.Throws<ArgumentException>(() => _ = 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<ArgumentException>(() =>
_ = 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()
Expand All @@ -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(() =>
{
Expand Down
Loading
Loading