Skip to content

Commit

Permalink
Enhance CalDateTime and DateTimeSerializer (#638)
Browse files Browse the repository at this point in the history
* Enhance CalDateTime and DateTimeSerializer

* Introduced new methods and test cases in `CalDateTimeTests.cs` to ensure correct behavior of `CalDateTime` properties and methods.
* Updated various tests in `DeserializationTests.cs` and `RecurrenceTests.cs` to handle `CalDateTime` without time components and improve clarity.
* Refined `IsAllDay` property in `CalendarEvent.cs` and updated methods in `UniqueComponent.cs` and `VTimeZone.cs` to use `CalDateTime` with time components.
* Removed outdated comments and improved code formatting.
* Enabled nullable reference types and updated `IDateTime` interface.
* Added new methods and properties to `CalDateTime.cs` for better date and time management.
* Refactored methods in `Period`, `RecurrencePatternEvaluator`, and `RecurringEvaluator` classes to handle `HasTime` property correctly.
* Improved `DateTimeSerializer` class for better performance and handling of nullable types.
* Added XML documentation and marked obsolete methods.

Resolves #630
Resolves #633
Resolves #635
Resolves #636
Resolves #637

* Fix occasual failing unit test

Depending on the time offset from local time to UTC the tests failed.
Changed all date kinds to UTC.

* Make AlmostZeroEpsilon private const

* Replace DateTimeKind.Local with DateTimeKind.Unspecified

Affected classes:
* `CalDateTime`
* `DateUtil`
* `DateTimeSerializer`

* SOC: Move getting "TZID" from `IParameterCollection` to `DateTimeSerializer`

`CalDateTime.TzId` does no more read or write `CalDateTime.Parameters`

* Use backing fields `DateOnly` and `TimeOnly` to create the `CalDateTime.Value`

* Depending on `HasTime`, `Value` contains only the `DateTime.Date`, or the value including `DateTime.TimeOfDay`.
* The timezone dermines whether `DateTimeKind.Utc`or `DateTimeKind.Unspecified`will be used.

* Remove the redundant `Calendar` argument to CTORs

* Implement review comments

* `if (Math.Abs(right.TotalDays % 1) > AlmostZeroEpsilon)` is now `if ((right.Ticks % TimeSpan.TicksPerDay) != 0)`
* `DateUtil.DateTime GetSimpleDateTimeData(IDateTime dt)` returns `dt.Value`
* Move internal `DateUtil.SimpleDateTimeToMatch` as private to `RecurrenceTests`
* Move internal `DateUtil.MatchTimeZone` as private  to `RecurrencePatternEvaluator`
* Create tasks in #646 and #647 for new PRs

* Remove xmldoc for non-existing parameter "kind"

Also refactor for SonarCloud complaints
  • Loading branch information
axunonb authored Nov 25, 2024
1 parent 1e4962e commit 796018e
Show file tree
Hide file tree
Showing 29 changed files with 1,198 additions and 1,004 deletions.
7 changes: 4 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,13 @@ csharp_prefer_braces = false:suggestion

# Expression-bodied members
csharp_style_expression_bodied_methods = false:suggestion
csharp_style_expression_bodied_properties = true:suggestion
csharp_style_expression_bodied_properties = true
csharp_style_expression_bodied_properties = when_on_single_line:suggestion
csharp_style_expression_bodied_indexers = false:warning
#prefer block bodies for constructors
csharp_style_expression_bodied_constructors = false:suggestion
csharp_style_expression_bodied_constructors = true
#prefer block bodies for accessors
csharp_style_expression_bodied_accessors = false:suggestion
csharp_style_expression_bodied_accessors = true


#Style - expression level options
Expand Down
4 changes: 2 additions & 2 deletions Ical.Net.Benchmarks/ApplicationWorkflows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
// Licensed under the MIT license.
//

using BenchmarkDotNet.Attributes;
using Ical.Net.DataTypes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BenchmarkDotNet.Attributes;
using Ical.Net.DataTypes;

namespace Ical.Net.Benchmarks;

Expand Down
2 changes: 1 addition & 1 deletion Ical.Net.Benchmarks/CalDateTimePerfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// Licensed under the MIT license.
//

using System;
using BenchmarkDotNet.Attributes;
using Ical.Net.DataTypes;
using System;

namespace Ical.Net.Benchmarks;

Expand Down
6 changes: 3 additions & 3 deletions Ical.Net.Benchmarks/OccurencePerfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
// Licensed under the MIT license.
//

using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ical.Net.Benchmarks;

Expand Down
4 changes: 2 additions & 2 deletions Ical.Net.Benchmarks/Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// Licensed under the MIT license.
//

using System.IO;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Running;
using System.IO;

namespace Ical.Net.Benchmarks;

Expand All @@ -15,7 +15,7 @@ private static void Main(string[] args)
{
#if DEBUG
BenchmarkSwitcher.FromAssembly(typeof(ApplicationWorkflows).Assembly).Run(args, new DebugInProcessConfig());
#else
#else
#region * ApplicationWorkflows results *
/*
// * Summary *
Expand Down
6 changes: 3 additions & 3 deletions Ical.Net.Benchmarks/SerializationPerfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
// Licensed under the MIT license.
//

using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using Ical.Net.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ical.Net.Benchmarks;

Expand Down
2 changes: 1 addition & 1 deletion Ical.Net.Benchmarks/ThroughputTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// Licensed under the MIT license.
//

using BenchmarkDotNet.Attributes;
using System;
using System.Linq;
using BenchmarkDotNet.Attributes;

namespace Ical.Net.Benchmarks;

Expand Down
200 changes: 60 additions & 140 deletions Ical.Net.Tests/AlarmTest.cs
Original file line number Diff line number Diff line change
@@ -1,174 +1,94 @@
//
//
// Copyright ical.net project maintainers and contributors.
// Licensed under the MIT license.
//

using System;
using System.Collections.Generic;
using System.Linq;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;

namespace Ical.Net.Tests;

[TestFixture]
public class AlarmTest
public class AttendeeTest
{
private const string _tzid = "US-Eastern";

public void TestAlarm(string calendarString, List<IDateTime> dates, CalDateTime start, CalDateTime end)
internal static CalendarEvent VEventFactory() => new CalendarEvent
{
var iCal = Calendar.Load(calendarString);
ProgramTest.TestCal(iCal);
var evt = iCal.Events.First();

// Poll all alarms that occurred between Start and End
var alarms = evt.PollAlarms(start, end);
Summary = "Testing",
Start = new CalDateTime(2010, 3, 25),
End = new CalDateTime(2010, 3, 26)
};

var utcDates = new HashSet<DateTime>(dates.Select(d => d.AsUtc));

//Only compare the UTC values here, since we care about the time coordinate when the alarm fires, and nothing else
foreach (var alarm in alarms.Select(a => a.DateTime.AsUtc))
{
Assert.That(utcDates.Contains(alarm), Is.True, "Alarm triggers at " + alarm + ", but it should not.");
}
Assert.That(dates.Count == alarms.Count, Is.True, "There were " + alarms.Count + " alarm occurrences; there should have been " + dates.Count + ".");
}

[Test, Category("Alarm")]
public void Alarm1()
private static readonly IList<Attendee> _attendees = new List<Attendee>
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
new Attendee("MAILTO:james@example.com")
{
new CalDateTime(2006, 7, 18, 9, 30, 0, _tzid)
});

var content = IcsFiles.Alarm1;
TestAlarm(content, dateTimes, new CalDateTime(2006, 7, 1, _tzid), new CalDateTime(2006, 9, 1, _tzid));
}

[Test, Category("Alarm")]
public void Alarm2()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
CommonName = "James James",
Role = ParticipationRole.RequiredParticipant,
Rsvp = true,
ParticipationStatus = EventParticipationStatus.Tentative
},
new Attendee("MAILTO:mary@example.com")
{
new CalDateTime(2006, 7, 18, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 20, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 22, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 24, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 26, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 28, 9, 30, 0, _tzid),
new CalDateTime(2006, 7, 30, 9, 30, 0, _tzid),
new CalDateTime(2006, 8, 1, 9, 30, 0, _tzid),
new CalDateTime(2006, 8, 3, 9, 30, 0, _tzid),
new CalDateTime(2006, 8, 5, 9, 30, 0, _tzid)
});
CommonName = "Mary Mary",
Role = ParticipationRole.RequiredParticipant,
Rsvp = true,
ParticipationStatus = EventParticipationStatus.Accepted
}
}.AsReadOnly();

var content = IcsFiles.Alarm2;
TestAlarm(content, dateTimes, new CalDateTime(2006, 7, 1, _tzid), new CalDateTime(2006, 9, 1, _tzid));
}

[Test, Category("Alarm")]
public void Alarm3()
/// <summary>
/// Ensures that attendees can be properly added to an event.
/// </summary>
[Test, Category("Attendee")]
public void Add1Attendee()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
{
new CalDateTime(1998, 2, 11, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 11, 9, 0, 0, _tzid),
new CalDateTime(1998, 11, 11, 9, 0, 0, _tzid),
new CalDateTime(1999, 8, 11, 9, 0, 0, _tzid),
new CalDateTime(2000, 10, 11, 9, 0, 0, _tzid)
});
var evt = VEventFactory();
Assert.That(evt.Attendees.Count, Is.EqualTo(0));

var content = IcsFiles.Alarm3;
TestAlarm(content, dateTimes, new CalDateTime(1997, 1, 1, _tzid), new CalDateTime(2000, 12, 31, _tzid));
}
evt.Attendees.Add(_attendees[0]);
Assert.That(evt.Attendees, Has.Count.EqualTo(1));

[Test, Category("Alarm")]
public void Alarm4()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
Assert.Multiple(() =>
{
new CalDateTime(1998, 2, 11, 9, 0, 0, _tzid),
new CalDateTime(1998, 2, 11, 11, 0, 0, _tzid),
new CalDateTime(1998, 2, 11, 13, 0, 0, _tzid),
new CalDateTime(1998, 2, 11, 15, 0, 0, _tzid),
new CalDateTime(1998, 3, 11, 9, 0, 0, _tzid),
new CalDateTime(1998, 3, 11, 11, 0, 0, _tzid),
new CalDateTime(1998, 3, 11, 13, 0, 0, _tzid),
new CalDateTime(1998, 3, 11, 15, 0, 0, _tzid),
new CalDateTime(1998, 11, 11, 9, 0, 0, _tzid),
new CalDateTime(1998, 11, 11, 11, 0, 0, _tzid),
new CalDateTime(1998, 11, 11, 13, 0, 0, _tzid),
new CalDateTime(1998, 11, 11, 15, 0, 0, _tzid),
new CalDateTime(1999, 8, 11, 9, 0, 0, _tzid),
new CalDateTime(1999, 8, 11, 11, 0, 0, _tzid),
new CalDateTime(1999, 8, 11, 13, 0, 0, _tzid),
new CalDateTime(1999, 8, 11, 15, 0, 0, _tzid),
new CalDateTime(2000, 10, 11, 9, 0, 0, _tzid),
new CalDateTime(2000, 10, 11, 11, 0, 0, _tzid),
new CalDateTime(2000, 10, 11, 13, 0, 0, _tzid),
new CalDateTime(2000, 10, 11, 15, 0, 0, _tzid)
//the properties below had been set to null during the Attendees.Add operation in NuGet version 2.1.4
Assert.That(evt.Attendees[0].Role, Is.EqualTo(ParticipationRole.RequiredParticipant));
Assert.That(evt.Attendees[0].ParticipationStatus, Is.EqualTo(EventParticipationStatus.Tentative));
});

var content = IcsFiles.Alarm4;
TestAlarm(content, dateTimes, new CalDateTime(1997, 1, 1, _tzid), new CalDateTime(2000, 12, 31, _tzid));
}

[Test, Category("Alarm")]
public void Alarm5()
[Test, Category("Attendee")]
public void Add2Attendees()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
{
new CalDateTime(1998, 1, 2, 8, 0, 0, _tzid)
});
var evt = VEventFactory();
Assert.That(evt.Attendees.Count, Is.EqualTo(0));

var content = IcsFiles.Alarm5;
TestAlarm(content, dateTimes, new CalDateTime(1997, 7, 1, _tzid), new CalDateTime(2000, 12, 31, _tzid));
evt.Attendees.Add(_attendees[0]);
evt.Attendees.Add(_attendees[1]);
Assert.That(evt.Attendees, Has.Count.EqualTo(2));
Assert.That(evt.Attendees[1].Role, Is.EqualTo(ParticipationRole.RequiredParticipant));
}

[Test, Category("Alarm")]
public void Alarm6()
/// <summary>
/// Ensures that attendees can be properly removed from an event.
/// </summary>
[Test, Category("Attendee")]
public void Remove1Attendee()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
{
new CalDateTime(1998, 1, 2, 8, 0, 0, _tzid),
new CalDateTime(1998, 1, 5, 8, 0, 0, _tzid),
new CalDateTime(1998, 1, 8, 8, 0, 0, _tzid),
new CalDateTime(1998, 1, 11, 8, 0, 0, _tzid),
new CalDateTime(1998, 1, 14, 8, 0, 0, _tzid),
new CalDateTime(1998, 1, 17, 8, 0, 0, _tzid)
});
var evt = VEventFactory();
Assert.That(evt.Attendees.Count, Is.EqualTo(0));

var content = IcsFiles.Alarm6;
TestAlarm(content, dateTimes, new CalDateTime(1997, 7, 1, _tzid), new CalDateTime(2000, 12, 31, _tzid));
}
var attendee = _attendees.First();
evt.Attendees.Add(attendee);
Assert.That(evt.Attendees, Has.Count.EqualTo(1));

[Test, Category("Alarm")]
public void Alarm7()
{
var dateTimes = new List<IDateTime>();
dateTimes.AddRange(new[]
{
new CalDateTime(2006, 7, 18, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 20, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 22, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 24, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 26, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 28, 10, 30, 0, _tzid),
new CalDateTime(2006, 7, 30, 10, 30, 0, _tzid),
new CalDateTime(2006, 8, 1, 10, 30, 0, _tzid),
new CalDateTime(2006, 8, 3, 10, 30, 0, _tzid),
new CalDateTime(2006, 8, 5, 10, 30, 0, _tzid)
});
evt.Attendees.Remove(attendee);
Assert.That(evt.Attendees.Count, Is.EqualTo(0));

var content = IcsFiles.Alarm7;
TestAlarm(content, dateTimes, new CalDateTime(2006, 7, 1, _tzid), new CalDateTime(2006, 9, 1, _tzid));
evt.Attendees.Remove(_attendees.Last());
Assert.That(evt.Attendees.Count, Is.EqualTo(0));
}
}
}
9 changes: 4 additions & 5 deletions Ical.Net.Tests/AttendeeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
// Licensed under the MIT license.
//

using System.Collections.Generic;
using System.Linq;
using Ical.Net;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using NUnit.Framework;

namespace Ical.Net.Tests;
using System.Collections.Generic;
using System.Linq;

[TestFixture]
public class AttendeeTest
Expand Down Expand Up @@ -91,4 +90,4 @@ public void Remove1Attendee()
evt.Attendees.Remove(_attendees.Last());
Assert.That(evt.Attendees.Count, Is.EqualTo(0));
}
}
}
Loading

0 comments on commit 796018e

Please sign in to comment.