判断请假时间去除周末及节假日

公司业务需求,在请假时自动跳过周六周日以及节假日。通过statisticsOfLeaveTime方法,传入请假开始的时间以及请假结束的时间,则可自动统计调休时间。

代码整体逻辑就为拿到请假开始和结束时间,分三种情况进行计算请假时长,第一种情况为请假一天,开始和结束时间均为一天,第二种情况为请假连续两天,第三种情况为请假超过2天。

请假一天时,分为包含午休和不包含午休两种情况,包含午休时需要减去午休时间,不包含午休时直接求时间的数据差即可。

请假两天时,需要分别单独计算第一天和第二天的时间和,第一天请假结束时间就设置为下班时间,第二天请假开始时间就设置为上班时间。

请假三天及以上时,单独求出请假第一天和最后一天的时间,再循环期间的日期判断是否在周末或节假日内,如果在周末或节假日内则跳过时间计算,如果不是周末或节假日则加上一天的请假时间。

以下代码中重点部分都存在注释,其中的周末周日规则是前往数据库查询公司规定的工作日时间,若不在这期间内则作为周末时间,其中节假日时间也是前往数据库查询的公司规定的节假日时间范围,如果在这个范围内则做为节假日时间。

公司一天上班7.5小时,但是请假一天要按8小时计算,所以在一天请假时长计算时添加了如果分钟数达到一天7.5小时的话设置为8小时的分钟数,公司人性化请假少于5分钟的时长不计算,所以返回时做了时间计算,多于5分钟部分算为一小时,少于5分钟部分不作计算。

最后,此方法传入的开始时间和结束时间都是使用SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");进行格式化的时间,如果没有格式话会报异常。

    //上班时间
    static LocalTime workDayStartTime = LocalTime.of(9, 0);
    //下班时间
    static LocalTime workDayEndTime = LocalTime.of(18, 0);
    //午休开始时间
    static LocalTime workDayNoonStartTime = LocalTime.of(12, 0);
    //午休结束时间
    static LocalTime workDayNoonEndTime = LocalTime.of(13, 30);

/**
     * 获取请假时长,排除周六周日及节假日
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    @Override
    public Integer statisticsOfLeaveTime(String beginTime, String endTime) throws ParseException {
        LocalDateTime startDateTime = LocalDateTime.parse(beginTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        LocalDateTime endDateTime = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        LocalDate startDate = startDateTime.toLocalDate();
        LocalDate endDate = endDateTime.toLocalDate();
        //结束请假当天的工作开始时间
        LocalDateTime endWorkStartDateTime = LocalDateTime.of(endDate, workDayStartTime);
        //结束请假当天的工作结束时间
        LocalDateTime workEndDateTime = LocalDateTime.of(endDate, workDayEndTime);
        //开始请假当天的工作开始时间
        LocalDateTime workDayStartDateTime = LocalDateTime.of(startDate, workDayStartTime);
        //开始工作当天的工作结束时间
        LocalDateTime workDayEndDateTime = LocalDateTime.of(endDate, workDayEndTime);
        //两个if判断请假开始时间和结束时间是否在工作时间内,在工作时间外则赋值为工作时间
        if (startDateTime.isBefore(workDayStartDateTime)) {
            startDateTime = workDayStartDateTime;
        }
        if (endDateTime.isAfter(workDayEndDateTime)) {
            endDateTime = workDayEndDateTime;
        }
        //判断结束请假时间,如果在结束当天的上班时间之前,赋值为上班时间
        if (endDateTime.isBefore(endWorkStartDateTime)) {
            endDateTime = endWorkStartDateTime;
        }
        //返回时间总数(分钟)
        long leaveHours = 0;
        //获取请假天数间隔,0为一条,1为连续两天,否则为连续多头请假
        long sumDate = endDate.toEpochDay() - startDate.toEpochDay();
        if (sumDate == 0) {
            leaveHours = sumOneDay(startDateTime, endDateTime);
        } else if (sumDate == 1) {
            //分别获取两天的时间
            leaveHours += sumOneDay(startDateTime, workEndDateTime);
            leaveHours += sumOneDay(endWorkStartDateTime, endDateTime);
        } else {
            //获取请假开始那天和请假结束那天时间
            leaveHours += sumOneDay(startDateTime, workEndDateTime);
            leaveHours += sumOneDay(endWorkStartDateTime, endDateTime);
            //循环请假中间时间,不在假期内则增加一条请假时间
            for (LocalDate date = startDate.plusDays(1); !date.isAfter(endDate.plusDays(-1)); date = date.plusDays(1)) {
                if (isHoliday(date)) {
                    continue;
                }
                leaveHours += 480;
            }
        }
        //返回请假时长,将分钟转化为小时,超过5分钟则计为一小时
        return toHours(leaveHours);
    }


    /**
     * 计算请假一天的请假时长
     */
    public int sumOneDay(LocalDateTime startDateTime, LocalDateTime endDateTime) {
        int leaveHours = 0;
        LocalDate startDate = startDateTime.toLocalDate();
        LocalDate endDate = endDateTime.toLocalDate();
        //获取当天午休时间
        LocalDateTime workDayNoonStartDateTime = LocalDateTime.of(startDate, workDayNoonStartTime);
        LocalDateTime workDayNoonEndDateTime = LocalDateTime.of(endDate, workDayNoonEndTime);
        //请假时间段包含午休进if
        if (startDateTime.isBefore(workDayNoonEndDateTime) && endDateTime.isAfter(workDayNoonStartDateTime)) {
            //判断请假开始时间是否在午休开始时间前,在午休开始时间之后则不用计算上午请假时间
            LocalDateTime leaveStartDateTime = startDateTime.isBefore(workDayNoonStartDateTime) ? startDateTime : null;
            //判断请假结束时间是否在午休结束时间前,在午休结束时间之前则不用计算下午请假时间
            LocalDateTime leaveEndDateTime = endDateTime.isAfter(workDayNoonEndDateTime) ? endDateTime : null;
            if (leaveStartDateTime != null) {
                leaveHours += Duration.between(leaveStartDateTime, workDayNoonStartDateTime).toMinutes();
            }
            if (leaveEndDateTime != null) {
                leaveHours += Duration.between(workDayNoonEndDateTime, leaveEndDateTime).toMinutes();
            }
        } else {
            leaveHours += Duration.between(startDateTime, endDateTime).toMinutes();
        }
        //如果刚刚好一天都请假了则算为8小时
        if (leaveHours == 450) {
            leaveHours = 480;
        }
        return leaveHours;
    }

    /**
     * 是否为放假时间判断
     */
    public boolean isHoliday(LocalDate date) throws ParseException {
        Boolean is = false;
        //获取当前年
        Integer curyear = DateUtils.getYear(new Date());
        //获取当前年考勤规则
        OaSignRule rule = ruleService.queryFirstOne(curyear);
        //获取考勤规则中的工作时间
        String workingDays = rule.getWorkingDays();
        Date date1 = Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);
        //判断当前天是否在考勤规则中的工作时间
        if (!StringUtils.isEmpty(workingDays)) {
            List list = Arrays.asList(workingDays.split(","));
            String week = String.valueOf(cal.get(Calendar.DAY_OF_WEEK) - 1);
            if (!list.contains(week)) {
                return true;
            }
        }
        //判断当前天是否在设置的节假日里
        Long currentDateTime = date1.getTime();
        is = checkToDay(currentDateTime, rule.getHolidayYuanDan(), is);
        is = checkToDay(currentDateTime, rule.getHolidayChunJie(), is);
        is = checkToDay(currentDateTime, rule.getHolidayQingMing(), is);
        is = checkToDay(currentDateTime, rule.getHolidayLaoDong(), is);
        is = checkToDay(currentDateTime, rule.getHolidayDuanWu(), is);
        is = checkToDay(currentDateTime, rule.getHolidayZhongQiu(), is);
        is = checkToDay(currentDateTime, rule.getHolidayGuoQing(), is);
        is = checkToDay(currentDateTime, rule.getHolidayOther(), is);
        return is;
    }

    /**
     * 判断是否为假期
     */
    public boolean checkToDay(Long currentDate, String holiday, Boolean is) throws ParseException {
        if (is) {
            return true;
        }
        if (!StringUtils.isEmpty(holiday)) {
            String[] arr = holiday.split(",");
            long beginTime = DateUtils.parseDate(arr[0], "yyyy-MM-dd").getTime();
            long endTime = DateUtils.parseDate(arr[1], "yyyy-MM-dd").getTime();
            if (currentDate >= beginTime && currentDate <= endTime) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将分钟转化为小时,超过五分钟算为一个小时
     */
    public Integer toHours(long minutes) {
        int moreMinutes = (int) minutes % 60;
        if (moreMinutes <= 5) {
            return (int) Math.floor((double) minutes / 60);
        } else {
            return (int) Math.ceil((double) minutes / 60);
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值