设计Google日历等日历系统

pub*_*tic 12 algorithm calendar

我必须创建类似于Google日历的内容,因此我创建了一个包含用户所有事件的事件表.

困难的部分是处理重新发生的事件,事件表中的行有一个event_type字段,告诉你它是什么类型的事件,因为事件可以只针对一个日期,或者每x天重新发生一次事件.

主要的设计挑战是处理重新发生的事件.

当用户使用月份视图查看日历时,如何显示给定月份的所有事件?查询会很棘手,所以我认为创建另一个表并为每个事件创建一个行会更容易,包括重新发生的事件.

你们有什么感想?

Mat*_* S. 6

我正在解决这个问题,并且我已经将iCalendarrfc 2445)完全隔开,直到阅读此线程,所以我不知道这将或不会与该线程集成得有多好。无论如何,到目前为止我想出的设计看起来像这样:

  • 您不可能存储重复事件的所有实例,至少不能在它们发生之前存储,因此我只需使用一个表来将事件的第一个实例存储为实际日期、可选的到期时间以及可为空的 Repeat_unit 和 Repeat_increment 字段来描述重复。对于单个实例,重复字段为空,否则单位将为“日”、“周”、“月”、“年”,增量只是添加到下一次出现的开始日期的单位倍数。
  • 仅当您需要与模型中的其他实体建立关系时,存储过去的事件才显得有利,即使如此,也没有必要在每种情况下都有一个显式的“事件实例”表。如果其他实体已经具有日期/时间“实例”数据,则事件的外键(或多对多的连接表)很可能就足够了。
  • 为了“更改此实例”/“更改所有未来实例”,我计划仅复制事件并使过时的事件过期。因此,要更改单个实例,您需要使旧实例在最后一次出现时过期,为新的、唯一的实例制作一份包含更改且不重复的副本,并在下一次出现时复制原始副本,并重复到未来。更改所有未来的实例都是类似的,您只需使原始实例过期并制作包含更改和重复详细信息的新副本。

到目前为止,我发现此设计存在两个问题:

  1. 这使得 MWF 类型的事件难以表示。这是可能的,但会强制用户创建三个单独的事件,这些事件每周在 M、W、F 上分别重复,并且他们想要进行的任何更改也必须分别对每个事件进行。这类事件在我的应用程序中并不是特别有用,但它确实在模型上留下了缺陷,使其通用性低于我的预期。
  2. 通过复制事件进行更改,您可以打破它们之间的关联,这在某些情况下可能很有用(或者,可能只是偶尔会出现问题。)理论上,事件表可以包含一个“copied_from”id 字段来跟踪事件发生的位置。事件起源,但我还没有充分思考类似的事情会有多大用处。一方面,从 SQL 查询父/子层次关系是一件痛苦的事情,因此其好处需要相当大才能超过查询该数据的成本。我想你可以使用嵌套集来代替。

最后,我认为可以使用直接 SQL 来计算给定时间跨度的事件,但我还没有计算出确切的细节,而且我认为查询通常最终会变得太麻烦而不值得。但是,为了便于论证,您可以使用以下表达式来计算事件给定月份和年份之间的月份差异:

(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12))
Run Code Online (Sandbox Code Playgroud)

在上一个示例的基础上,您可以使用 MOD 来确定月份差异是否是正确的倍数:

MOD(:month + (:year * 12)) - (MONTH(occursOn) + (YEAR(occursOn) * 12), repeatIncrement) = 0
Run Code Online (Sandbox Code Playgroud)

无论如何,这并不完美(它不会忽略过期的事件,不会考虑事件的开始/结束时间等),因此它只是作为一个激励示例。一般来说,虽然我认为大多数查询最终都会变得过于复杂。您可能最好查询给定范围内发生的事件,或者在该范围之前不会过期的事件,并用代码而不是 SQL 计算实例本身。如果您确实希望数据库进行处理,那么存储过程可能会让您的生活变得更加轻松。


Der*_*ark 5

试图存储每个事件的每个实例似乎真的有问题,而且,不可能.如果某人创建了"每个星期四,永远"发生的事件,您显然无法存储所有未来事件.

可以尝试按需生成未来事件,并仅在必要时填充未来事件以显示它们或发送有关它们的通知.但是,如果您打算构建"按需"生成代码,为什么不一直使用它?而不是从事件表中拉出,然后必须使用按需事件生成来填充尚未添加到表中的任何新事件,而是仅使用按需事件生成.最终结果是一样的.使用此方案,您只需存储开始和结束日期以及事件频率.

我没有看到任何方法可以避免生成按需事件,因此我无法在事件表中看到该实用程序.如果你想要它来缓存,那么我认为你采取了错误的方法.首先,它是一个糟糕的缓存,因为无论如何你无法避免按需事件生成.其次,无论如何你应该在更高的层次上缓存.如果要缓存,则缓存生成的页面,而不是事件.

至于使您的轮询更有效率,如果您每15分钟轮询一次,并且您的数据库和/或服务器无法处理负载,那么您已经注定失败.如果用户无法处理更多,更频繁的轮询而不会出汗,那么您的数据库将无法处理用户.


Ste*_*nby 5

如前所述,不要重新发明轮子,只需增强它。

结帐VCalendar,它是开源的,并且带有 PHP、ASP 和 ASP.Net (C#)!

您也可以查看Day Pilot,它提供了用 Asp.Net 2.0 编写的日历。他们提供您可以查看的精简版,如果它适合您,您可以购买许可证。

更新 (9/30/09):

当然除非轮子坏了!此外,如果您愿意,您可以涂上一层闪亮的新油漆(即:制作更好的用户界面)。但至少尝试找到一些基础来构建,因为日历系统可能很棘手(具有重复事件),并且已经完成了数千次。


Dev*_*ris 3

我想说从标准开始。如果您使用它作为您的模型,那么您将能够执行 google calendar、outlook、mac ical(程序)的所有操作,并且几乎可以立即与它们集成。

从那时起,是时候加强你的 ajax 和 javascript 了,因为如果没有大量的 ajax 和 javascript,你就不可能拥有带有拖放功能的华丽 Web UI 和多个日历。