在日历应用程序中为重复事件建模的最佳方法是什么?
我正在构建一个需要支持重复事件的组日历应用程序,但是我为处理这些事件而想出的所有解决方案似乎都是黑客。我可以限制一个人可以看到的距离,然后立即生成所有事件。或者,我可以将事件存储为重复事件,并在日历上向前看时动态显示它们,但是如果有人想更改事件特定实例的详细信息,则必须将它们转换为正常事件。
我敢肯定有更好的方法可以做到这一点,但我还没有找到。对重复事件建模的最佳方法是什么,我们可以在其中更改特定事件实例的详细信息或者删除特定事件实例?
(我使用的是Ruby,但是请不要让它限制答案。但是,如果有特定于Ruby的库或者其他东西,那就很高兴了。
解决方案
回答
我们可能需要查看iCalendar软件实现或者标准本身(RFC 2445 RFC 5545)。
很快就会想到的是Mozilla项目http://www.mozilla.org/projects/calendar/快速搜索也显示了http://icalendar.rubyforge.org/。
可以考虑其他选项,具体取决于我们将如何存储事件。我们正在构建自己的数据库架构吗?使用基于iCalendar的工具等?
回答
我们可以将事件存储为重复事件,如果已编辑特定实例,则使用相同的事件ID创建一个新事件。然后,在查找事件时,搜索具有相同事件ID的所有事件以获取所有信息。我不确定我们是否滚动了自己的事件库,或者是否正在使用现有的事件库,因此可能无法实现。
回答
我会在以后的所有重复事件中使用"链接"概念。它们将动态显示在日历中,并链接回单个参考对象。事件发生后,链接断开,该事件成为独立实例。如果我们尝试编辑重复发生的事件,请提示更改所有将来的项目(即更改单个链接的引用)或者仅更改该实例(在这种情况下,将其转换为独立实例,然后进行更改)。后者的情况有些麻烦,因为我们需要跟踪所有转换为单个实例的未来事件的重复列表。但是,这完全是可行的。
因此,从本质上讲,有2类事件:单个实例和重复发生的事件。
回答
将事件存储为重复事件并动态显示它们,但是允许重复发生的事件包含特定事件的列表,这些列表可能会覆盖特定日期的默认信息。
当我们查询重复事件时,它可以检查当天的特定替代。
如果用户进行更改,则可以询问他是否要针对所有实例(默认详细信息)或者仅在当天进行更新(进行新的特定事件并将其添加到列表中)。
如果用户要求删除此事件的所有重复发生,那么我们还可以获取详细信息列表,并且可以轻松删除它们。
唯一有问题的情况是用户是否要更新此事件以及所有将来的事件。在这种情况下,我们必须将重复发生的事件分成两部分。此时,我们可能需要考虑以某种方式链接重复发生的事件,以便将其全部删除。
回答
- 跟踪重复规则(可能基于iCalendar,基于@Kris K.)。这将包括模式和范围(每第三个星期二,出现10次)。
- 对于要编辑/删除特定事件的时间,请跟踪上述重复规则的异常日期(规则未指定事件发生的日期)。
- 如果删除了,那就足够了,如果我们进行编辑,则可以创建另一个事件,并将其父ID设置为主要事件。我们可以选择是在该记录中包括所有主事件的信息,还是仅保留更改并继承所有未更改的信息。
请注意,如果我们允许不终止的重复规则,则必须考虑如何显示现在无限量的信息。
希望对我们有所帮助!
回答
我建议使用日期库的功能以及ruby的range模块的语义。重复发生的事件实际上是一个时间,一个日期范围(开始和结束),通常是一周中的某一天。使用日期和范围,我们可以回答任何问题:
#!/usr/bin/ruby require 'date' start_date = Date.parse('2008-01-01') end_date = Date.parse('2008-04-01') wday = 5 # friday (start_date..end_date).select{|d| d.wday == wday}.map{|d| d.to_s}.inspect
产生活动的所有日子,包括the年!
# =>"[\"2008-01-04\", \"2008-01-11\", \"2008-01-18\", \"2008-01-25\", \"2008-02-01\", \"2008-02-08\", \"2008-02-15\", \"2008-02-22\", \"2008-02-29\", \"2008-03-07\", \"2008-03-14\", \"2008-03-21\", \"2008-03-28\"]"
回答
从这些答案中,我找到了一个解决方案。我真的很喜欢链接概念的想法。重复事件可以是一个链表,而尾巴知道其重复规则。这样,更改一个事件就很容易了,因为链接保持不变,删除事件也很容易,我们只需取消链接事件,删除事件并在事件之前和之后重新链接它即可。每次有人查看日历上从未见过的新时间段时,我们仍然必须查询重复发生的事件,但是这样做很干净。
回答
对于准备支付一些许可费用的.NET程序员,我们可能会发现Aspose.Network有用...它包括一个iCalendar兼容库,用于定期约会。
回答
重复发生的事件可能会有很多问题,让我强调一些我所知道的问题。
解决方案1-没有实例
存储原始约会和重复数据,而不存储所有实例。
问题:
- 需要时,我们必须在日期窗口中计算所有实例,成本很高
- 无法处理异常(例如,我们删除一个实例,或者将其移动,或者,我们无法使用此解决方案来执行此操作)
解决方案2-存储实例
存储从1开始的所有内容,还存储所有实例,并链接回原始约会。
问题:
- 占用大量空间(但空间便宜,因此较小)
- 必须妥善处理异常,特别是如果我们在发生异常后返回并编辑原始约会时,尤其如此。例如,如果我们将第三个实例向前移动一天,那么如果我们回去编辑原始约会的时间,然后在原始日期重新插入另一个并留下移动的那个,该怎么办?取消移动的链接?尝试适当地更改已移动的?
当然,如果我们不打算做例外,那么任何一种解决方案都应该很好,并且我们基本上可以从时间/空间权衡方案中进行选择。
回答
我正在使用如下所述的数据库架构来存储重复参数
http://github.com/bakineggs/recurring_events_for
然后,我使用矮子来动态计算日期。
https://github.com/mlipper/runt
回答
What if you have a recurring appointment with no end date? As cheap as space is, you don't have infinite space, so Solution 2 is a non-starter there...
我可以建议将"无结束日期"解析为本世纪末的结束日期。即使是日常活动,空间仍然很便宜。
回答
我正在处理以下内容:
- http://github.com/elevation/event_calendar-日历的模型和助手
- http://github.com/seejohnrun/ice_cube-很棒的重复宝石
- http://github.com/justinfrench/formtastic-简单表格
以及正在进行的gem扩展形式,其输入类型为:recurring(form.schedule:as =>:recurring
),它呈现一个类似于iCal的界面和一个before_filter
来将视图序列化为IceCube
对象再次,贫民窟。
我的想法是使添加循环属性到模型并在视图中轻松连接变得容易。共有两行。
那这给我什么呢?索引的,可编辑的,重复出现的属性。
"事件"存储一天的实例,并在日历视图/帮助器中使用
假设task.schedule
存储了Yaml的IceCube
对象,因此我们可以执行诸如task.schedule.next_suggestion
这样的调用。
回顾:我使用两种模型,一种用于日历显示,而另一种用于功能。
回答
日历的Martin Fowler重复活动包含一些有趣的见解和模式。
矮宝石实现了这种模式。