Home » Code » 时间段的选择联动及交叉判断

时间段的选择联动及交叉判断

在日常业务开发中,经常需要输入多个时间区间,比如为一个广告设置多个有效的时间区间,时间区间选择采用三个select来分别选择年、月、日,那么整个区间选择开始与结束就需要6个select。现以选择时-分-秒来看这个问题。

时间区间:10时10分10秒~10时11分11秒

现在考虑这么个问题,如何在前端就保证只能选择合法的值——开始时间不大于结束时间。显然的,需要监听某些select的change事件,当它的值改变时,对相应的其他某些select进行复位甚至禁用某些option。一开始认为,只要左边的总值(以最小单位计,大的乘以倍数)不大于右边,就不需要触发任何事件,其实不然,因为右边某些option可能需要禁用掉。比如开始是10:10:00,结束是10:10:10,当左边的分钟改为01结果为10:01:00,当然没有大于右边10:10:10,但相应的右边的分钟里的option,原来是0~9需要禁用掉的(都是10:10,要保证右边不小于左边,因此0~9要禁用),现在左边分钟变为了01,比它小的只有00,因此右边由原来的禁用0~9要改为禁用0,也是需要触 发事件的。

另外,还以为右边不需要绑定事件,只是左边开始部分变了跟着改右边即可。这也是错误的。假如开始是10:09:01,右边是10:10:01,很显然,右边秒数部分不需要禁用任何一个option,因为分钟那里右边就比左边大了。当改变右边分钟也变为09时,小时与分钟均跟左边相同,那右边的秒数就不能小于左边的秒数01,因此要禁用掉00,也就是说右边的select也是需要绑定事件的。事实上,除了最右的那个select,都需要绑定事件。

显然的,左边开始三个select的改变会影响右边结束三个select的可选范围,而且影响的不仅是相同位置的select,如左边第二个,不仅会影响右边第二个,也会影响右边第三个。右边的select,则是影响右边它往后的select。因此,我采用的做法的是:监听除最后一个外的所有select的change事件,当它的change事件触发时,若是左边的select,循环右边相同位置到最后一个位置,对这循环中的每个select姑且称为X的处理是:判断从最左到它之前(不含它)的左边select与右边select的值,若有左边小于右边的,select X显然全部option可选,若有左边大于右边的,select X显然全部要禁用全部option并重置为空,若左边的都相等,则看跟select X相同位置的左边值跟X相比,若小于,则将值小于左边select值的option禁用,否则启用。看文本可能晕了不知所云,还是看代码:

以下是上边代码的效果:

可以看到,无论如何操作各个select,始终保持左边不大于右边。这里边有个常识性的约定,右边结束部分,当不选择时,它其实等于最大值,比如右边只选择第一个小时为2,分钟与秒钟都不选择,它代表的实际值是02:59:59。

前端控制好了,后端除了验证开始值要小于结束值外,还要判断这个新的即将插入的时间区间是否会跟已有的时间区间发生交叉的情况,这是不允许的。这又要如何判断呢?

如上图,上边大的那个是我们即将要插入数据库的时间区间,下边各种小的是数据库中已有的时间区间,想像一个小的区间从左边向右边移动的过程中,什么时候会交叉呢?容易看出当小区间的END大于等于大区间的BEGIN,且小区间的BEGIN小于等于大于大区间的END时候,它们会有交叉。因此,查询条件就是:

end_time >= $insertBeginTime AND begin_time <= $insertEndTime

用以上条件若能找出记录,则这些记录的时间区间跟要插入的时间区间交叉了,否则不存在会交叉的情况。

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.