一、需要解决的问题
有些业务流程复杂,环节多样。为了看清整个业务的进展,往往需要对各个环节设定预计完成时间开销,然后在用这个是时间去考核实际业务开展的效率。
业务环节不同,往往设定的预计完成时间开销也不同,有些是自然天,有些是工作日,有些是工作小时,有些特殊业务可能还存在更复杂的运算逻辑(比如,车管所“停电”,那过户的业务就不能开展)
例如有一个任务,start是任务开始的时刻,要求在若干个工作小时之内完成。可以想象,如果完全靠代码写逻辑,计算预计的完成时间,是相当麻烦的一件事。
算时效就可能更麻烦,例如实际完成时间超时了,需要计算超时的百分比(注意分母可能是工作小时)
二、解决思路
以某个时刻为起点(图中是2019.12.12 00:00:00),设置一些连续的单元格,每个格子代表一个小时。提前根据工作日、假期、工作时段等数据,将这些格子初始化。1是工作时间,0是非工作时间。时间的计算就退化为数格子数(自然小时)或者数值为1的格子数(工作小时)
1、根据开始时间计算期望完成时间
(1)1个自然日。从开始位置向后数24个格子
(2)5个工作小时。从开始位置向后数到第5个值为1的格子
(3)2个工作日。从开始位置向后数到第20个值为1的格子(假设一天工作10小时)
2、根据开始时间和实际完成时间计算
(1)工作小时。计算这两个单元格间有几个为1的格子
(2)工作日。计算这两个单元格之间有为1的格子数除以10(假设一天工作10小时)
三、工程实现
1、采用Java的ArrayList来保存时间轴(上一节的连续的单元格),保存1年的工作日历需要 365*24个元素空间,性能上没什么问题。
2、根据节假日、工作时间等配置,初始化ArrayList。
3、依赖这个ArrayList提供各种时间上的计算。
提供服务的具体方式可以多样化,可以提供jar包或者云服务。
四、一些延展
在跟数仓同学讨论这个方案的时候,熟悉DB的同学给了一个数据库的视角。保存一个如下图的数据库表,似乎通过SQL也能完成类似的计算。
这个图中有calendarA,calendarB,calendarC三个日历,可以为不同的业务提供不同的工作日历(calendarC看起来是上夜班的)。