在开发一些OA系统的过程中,经常能遇到一个问题,就是时长计算,比如请假有请假的时长,出差有出差的时长,有的公司请假只能按照整天或小时为单位请假,这种都比较好处理,只要排除休息日节假日天数或排除工作小时数加午休( 如果有的话😂)小时数直接相减即可,但是如果需求是按照半天为单位,OA系统该怎样计算总时长呢?
以半天为最小单位时,机械的加减有时可能无法和实际情况相符,例如我在OA系统提交休假审批,从1号上午到2号上午为假期,如果直接假定开始的小时都一样直接把日期时间简单相减,那么休假时间就是24小时构成的1天,但是实际上假期的构成是1号上午,1号下午,以及2号上午,按照工时的普遍计算逻辑就是1.5个工作日,OA系统应计算实际休假时长是1.5天,那这种场景下OA系统要怎样计算才准确呢,我把情况分为4种分别处理,分别计算休假一天,两天和三天的情况,进而推导到更长时间
1. 上午开始,上午结束
1天内的情况是0.5天,2天内的是1.5天,3天内是2.5天
2. 上午开始,下午结束
1天内的情况是1天,2天内的是2天,3天内是3天
3. 下午开始,下午结束
1天内的情况是0.5天,2天内的是1.5天,3天内是2.5天
4. 下午开始,上午结束
1天内不会有这种情况,2天内的是1天,3天内是2天
综上,计算的代码就是这样的:
public static void main(String[] args) {System.out.println(test(LocalDate.parse("2024-12-01"),LocalDate.parse("2024-12-03"),1,1));
}/*** * @param start 开始日期* @param end 结束日期* @param startPeriod 开始 1上午2下午* @param endPeriod 结束 1上午 2下午* @return*/
public static double test(LocalDate start, LocalDate end, int startPeriod, int endPeriod) {// 如果开始时间或结束时间为空,则返回 0 天if (start == null || end == null) {return 0.0; // 确保返回值类型一致}// 先将小时分钟秒调到00:00:00计算两个日期之间的整天数double between = (double) java.time.temporal.ChronoUnit.DAYS.between(start, end);//天数相减会把涉及的天数算少一天,所以要加回来between ++;// 根据时间段调整天数if (startPeriod == 1) { // 开始是上午if (endPeriod == 1) { // 结束是上午between = between - 0.5 ;}}else if (startPeriod == 2) { // 开始是下午if (endPeriod == 1) { // 结束是上午between = between - 1;}else if (endPeriod == 2) { // 结束是下午between = between - 0.5 ;}}// 返回计算后的天数return between;
}