ICal.net 日历比较

ICal.net Calendar Comparison

我一直在使用名为 ICal.net 的 nuget 包来加载 ics 文件以检查最近添加的事件。

我注意到在为此使用 IEnumerable Except 方法时遗漏了一些事件,即使您可以看到添加了更多事件。

我在活动中遇到了 Uid 属性,检查了一下,发现它很独特 - https://github.com/rianjs/ical.net/blob/5176d27ac243eb98a01157f2ed7ff3e2852b98eb/v2/ical.NET/Interfaces/Components/IUniqueComponent.cs#L14

我使用 Uid 为此写了一个 IEqualityComparer<IEvent>,但现在所有事件都被视为新事件。

只是想知道是否有人对我如何使用 2 个日历、比较事件并找出差异有什么建议?目前有 2000 多个事件并且还在增加,因此试图保持其性能。

我建议使用 LINQ 进行 Where In 查询。

假设您有两个 collections(已注册并且可能是新的):

List<string> registeredIds = GetRegisteredComponentsUIds();

List<ComponentImplemenation> newEvents = GetNewEvents();

List<ComponentImplemenation> result = newEvents.Where(m => registeredIds.Contains(m.Uid))
                                               .ToList();

如果我没理解错的话,你有两个日历集合。一个表示具有多个 VEVENT 的 VCALENDAR,第二个表示稍后时间点的相同 VCALENDAR + VEVENT。由于显而易见的原因,较晚的 VCALENDAR 日历通常比较早的日历有更多的事件。并且您想比较两者以查看差异,即找到新事件。

  • 使用Uid可能就足够了,也可能不够;这取决于您的日历系统。虽然每个 UID 都应该是唯一的,但这取决于您的应用程序来保证。当 ical.net 创建事件时,它会执行 Guid.NewGuid().ToString(),因此如果您使用 ical.net 创建事件,它们应该是唯一的。 Google 日历和(我假设)其他流行的日历应用程序也提供确定性唯一的 Uid。
  • ical.net 不认为 Uid 出于相等或散列的目的。而是关注事件本身的构成。

如果您知道每个事件的 UID 都是唯一的,并且您没有兴趣比较具有不匹配 Uid 的两个事件,我会这样做:

var eventIdSet = new HashSet<string>(StringComparison.OrdinalIgnoreCase);
var firstEventIds = firstCalendarCollection
    .SelectMany(cc => cc.Event)
    .Select(e => e.Uid);
eventIdSet.UnionWith(firstEventIds);

var secondEventIds = secondCalendarCollection
    .SelectMany(cc => cc.Event)
    .Select(e => e.Uid);

eventIdSet.ExceptWith(secondEventIds);

这应该会为您提供第一个集合中存在的新日历 ID,但第二个集合中不会。

如果你想比较事件内容,我会遵循相同的模式,停在 Event 对象:

var firstSet = new HashSet<Event>();
var firstEvents = firstCalendarCollection.SelectMany(cc => cc.Event);
firstSet.UnionWith(firstEventIds);

var secondEvents = secondCalendarCollection.SelectMany(cc => cc.Event);
firstSet.ExceptWith(secondEvents);

这会做同样的事情,但正如我上面所说,事件 ID 被内部 GetHashCodeEquals 实现忽略。

单独比较 Uid 比比较每个 Event 的全部内容要快。也就是说,除非这是一个繁忙的服务器应用程序,每秒必须多次执行此操作,否则这无关紧要。我们正在使用 ical.net,并对 800-1000 个日历事件执行类似这样的设置操作,这在 WPF 应用程序中的计算时间为毫秒。除非在极端情况下,否则您可能不会注意到 Uid 比较与整个 Event 内容比较之间的区别。

编辑:我创建了一个 wiki 页面:https://github.com/rianjs/ical.net/wiki/Comparing-collections-of-calendar-events