我正在用 PHP 编写一个应用程序处理系统。需要将具有截止日期的简单任务转换为周期性任务。
如我所见:任务被赋予一个频率,例如“每周的周一”,创建任务时,会找到下周一的日期,并在该日期设置截止日期。在执行周期性任务时,确定下周一的日期并创建具有新截止日期的新任务,依此类推。也就是说,目前只有一个开放任务。
您需要能够灵活设置频率,例如:
- 每个月的第一个工作日
- 每个月的第一个星期一
- 每月10号和25号
- 每周一周三和周五
- 每两周的周三
- 每个工作日
- 每年九月的第一个星期一
- 每年 5 月和 10 月的第一个工作日两次
- 等等
所以问题是:以什么形式将这些周期性存储在数据库中,然后解析它们并获取事件的下一个和上一个日期。
strtotime是不够的,例如,如果我想通过复选框指定星期几。
从开始日期开始计算天数也不合适,因为事件之间的时间段不是恒定的。
您可以执行以下操作:
对于每个模板,设置其自己的“索引”并创建一个将模板扩展为年度计划的过程。由于大多数模板(尤其是具有相同频率的模板)将允许代码合并(差异微不足道),列表可以分为两级,因此,可以将这种类型的子类型传递给过程以考虑次要功能. 程序运行的结果应该是内存中的一个临时海图表。
编写一个用户定义的函数,根据给定的类型、子类型、参数和给定的日期,通过调用过程,将接收一个表,从中选择所需的值并返回它。
很明显,这将几乎是过程式编程——但逻辑将转到服务器,这将大大简化客户端。此外,此代码将属于“调试一次,永远忘记”类别。
此外,根据第 2 段:
使用构建第一个表的参数制作第二个表也许是有意义的 - 一种伪缓存。考虑到您需要获取事件的下一个和上一个日期这一事实,这已经至少可以重复使用一次,因此可以节省开支。
为方便起见,您可以在此数据库或服务数据库中创建一个静态数字表(从 1 到 366)。为了不每次都“即时”生成它。
如果您使用 \DateTime,那么日期存储的格式无关紧要。
您可以从 UNIXTIME 或普通 TIMESTAMP 获取日期和时间,然后使用格式方法以所需格式显示日期和时间。
使用 add 方法,您可以将日期更改为 N 天、小时、周、年等...
http://php.net/manual/ru/class.datetime.php
如果所有与日期的操作都将发生在数据库级别,则首选 TIMESTAMP 或 DATE。
我通过cron-mask解决了类似的问题
例子
0 12 1-14 * 30 12 1-7 9 10 12 1-7 5,10 1这样的口罩无法设定“工作日”的概念
为了设置各种变态的面具,你可以设置一系列面具,条件是在前一个面具起作用后开始考虑下一个面具
0 12 1-7 * 2 | 0 12 1-14 * 1