6.9 KiB
日历原理
本文档记述此日历所用到的一些数据的注解,包含对一些字段,API,数据结构设计的解读,但不包含具体的日历算法。
杂项
日历的主要运算负载在循环事件的计算和处理上。在这方面,服务端负责计算循环事件的起始和结束时间。客户端利用服务端计算出的起始和结束时间,计算循环事件到底在哪些日子被循环了,进而进行渲染。
本日历系统基于UNIX时间戳进行处理。在设计上使用Int64进行存储以规避2038问题。
本日历目前无条件限定最小时间为1950年1月1日,最大时间为2049年12月31日。
尽管允许客户端调换一个星期开始的日子是星期几,但是在设计上和计算上,均认为星期一是一个星期的开始。
API只有在遇到非当前接口应该产生的错误时,才使用外层结构来进行返回错误,例如token无效,应用程序错误,参数错误等。其应当返回的错误应该通过内层进行返回,例如登录接口的登陆成功与失败,删除接口的成功与否,应该通过内层返回true或false来决定。
数据库
同步容错
如果当前表中具有名为ccn_lastChange的字段,则标名该表具有同步容错功能,客户端上传的请求来操作该表时,会比对这个字段数值,如果相同才允许操作,并更新一个新数值返回给客户端。如果不相同,则表示客户端和服务端之间的数据不同步,需要重新同步各端数据。
在未来会增加一个或几个新的表来专门处理同步冲突并允许用户选择保留哪一个数据。
日历表
数据库方面,其余表都非常显而易见,只有calendar表需要详细讲述每个字段的功能。
CREATE TABLE calendar(
[ccn_uuid] TEXT NOT NULL,
[ccn_belongTo] TEXT NOT NULL,
[ccn_title] TEXT NOT NULL,
[ccn_description] TEXT NOT NULL,
[ccn_lastChange] TEXT NOT NULL,
[ccn_eventDateTimeStart] BIGINT NOT NULL,
[ccn_eventDateTimeEnd] BIGINT NOT NULL,
[ccn_loopRules] TEXT NOT NULL,
[ccn_loopDateTimeStart] BIGINT NOT NULL,
[ccn_loopDateTimeEnd] BIGINT NOT NULL,
PRIMARY KEY (ccn_uuid),
FOREIGN KEY (ccn_belongTo) REFERENCES collection(ccn_uuid) ON DELETE CASCADE
);
ccn_title是事件标题。ccn_description是事件描述,是一段JSON字典,其内容交由客户端自行解析,例如事件的标题颜色,设置提醒等,甚至包括ics文件标准中的一些基本用不到的功能,例如忙碌状态,地点,备注等,均交由此字段存储,交给客户端自行解析此字段决定如何使用这些数据。本日历不负责定义此处需要存储何种内容,但是定义其存储必须为JSON,为了方便不同的客户端进行解析,方便与ics文件之间相互转换。
ccn_eventDateTimeStart和ccn_eventDateTimeEnd,分别表示开始时间和结束时间。如果是循环事件,则表示此循环事件的第一个事件发生的时间。对于常用的点事件,或者全天事件,归于前者情况里面,通过设定开始和结束时间为一分钟和全天来解决。
ccn_loopRules是事件循环的规则,其格式详见后文的事件循环规则字符串章节。
ccn_loopDateTimeStart和ccn_loopDateTimeEnd是事件循环的时间,同时也被用于检索符合条件的事件返回给客户端。因此,对于非循环事件,其数值与ccn_eventDateTimeStart和ccn_eventDateTimeEnd保持一致。对于循环事件,则表示循环事件的循环的开始和结束时间。通常来说,ccn_loopDateTimeStart和ccn_eventDateTimeStart是一样的,无论是循环还是非循环事件。循环结束时间有3种类型,如果是无限循环,则将结束时间设置为Int64最大值。如果是指定时间,则设置成指定时间当天的最后一秒。如果是指定次数,则由算法算出最后时间。
需要注意的是,ccn_loopDateTimeStart和ccn_loopDateTimeEnd描述的是一段区间,一段包含该循环事件所有事件的开始时间的区间,但不一定包含所有结束时间。如下图所示:
Event loop span
+-----------------------------------------------------------------------+
| |
| |
+---------------------+ +----------------------+ +------------------------+
|Event 1 | |Event 2 | |Event 3 |
+---------------------+ +----------------------+ +------------------------+
+----------------------------------------------------------------------------------------------------> Time line
| |
| |
v v
Event start Event end
API
事件循环规则字符串
事件循环规则字符串 是一串用于描述当前事件循环规则的字符串,通过解析字符串可以计算出整个时间序列。本字符串借鉴了ics设计,但与ics设计毫无相似之处。
一个事件循环规则字符串的格式是[rules]-[stop],其中,[rules]是循环规则。而[stop]是循环停止规则。
循环规则
按年
格式:Y[span]
每间隔[span]年在同样的月份和日期进行循环。但需要考虑闰年,假设在2月29日设置3年循环一次,则实际上是12年循环一次(不考虑400年非闰)
按月
按月有4种格式
- 每月第
[num]天:MA[num][span] - 每月倒数第
[num]天:MB[num][span] - 每月第
[num1]个星期第[num2]天:MC[num1],[num2],[span] - 每月倒数第
[num1]个星期第[num2]天:MD[num1],[num2],[span]
[span]表示每隔多少个月处理一次此类事件。 需要注意相关数字的钳制,此种类型的事件循环也是算力消耗最大的。
按周
格式:W[T|F][T|F][T|F][T|F][T|F][T|F][T|F][span]
[span]表示每隔多少个周处理一次此类事件。[T|F]表示从T和F中选择一个写入,共7个,表示从星期一到星期日是否循环这个事件。
按日
格式:D[span]
每间隔[span]天进行循环。
循环停止规则
永远
格式:F
表示这个事件永远持续下去
指定时间
格式:D[timestamp]
在指定时间停止下来,实际上就是手动指定了ccn_loopDateTimeEnd。[timestamp]是结束时间的UNIX时间戳。
指定次数
格式:T[times]
在指定次数后停止下来。[times]是次数,为非0正整数。