计算加班时间减去午休和晚修时间的实际剩余时间

 

    public static void main(String[] args) {
        // 设置开始时间和结束时间
        String startTimeStr = "2024-05-07 17:00";
        String endTimeStr = "2024-05-07 22:20";

        // 时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        // 将字符串转换为 LocalDateTime 对象
        LocalDateTime startTime = LocalDateTime.parse(startTimeStr, formatter);
        LocalDateTime endTime = LocalDateTime.parse(endTimeStr, formatter);

        // 定义午休时间
        LocalTime wxStartTime = LocalTime.parse("11:40");
        LocalTime wxEndTime = LocalTime.parse("13:30");

        // 定义晚修时间
        LocalTime eveningStartTime = LocalTime.parse("17:30");
        LocalTime eveningEndTime = LocalTime.parse("18:30");

        // 计算总工作分钟数
        long totalMinutes = Duration.between(startTime, endTime).toMinutes();

        // 初始化减去的午休和晚修分钟数
        long deductedMinutes = 0;

        // 处理跨天的时间跨度
        LocalDateTime currentDayStart = startTime;

        // 循环遍历每一天,支持多天
        while (!currentDayStart.toLocalDate().isEqual(endTime.toLocalDate())) {
            LocalDate date = currentDayStart.toLocalDate();

            // 当天的结束时间是午夜
            LocalDateTime currentDayEnd = LocalDateTime.of(date, LocalTime.of(23, 59));

            if (currentDayStart.isBefore(currentDayEnd) && currentDayEnd.isBefore(endTime)) {
                // 在当前日期内,计算午休时间的重叠部分
                LocalDateTime lunchStart = LocalDateTime.of(date, wxStartTime);
                LocalDateTime lunchEnd = LocalDateTime.of(date, wxEndTime);

                deductedMinutes = getDeductedMinutes(currentDayStart, currentDayEnd, deductedMinutes, lunchStart, lunchEnd);

                // 在当前日期内,计算晚修时间的重叠部分
                LocalDateTime eveningStart = LocalDateTime.of(date, eveningStartTime);
                LocalDateTime eveningEnd = LocalDateTime.of(date, eveningEndTime);

                deductedMinutes = getDeductedMinutes(currentDayStart, currentDayEnd, deductedMinutes, eveningStart, eveningEnd);
            }

            currentDayStart = currentDayStart.plusDays(1).with(LocalTime.MIN);
        }

        // 检查最后一天(结束时间所在的那一天)的午休和晚修时间
        LocalDate date = endTime.toLocalDate();
        LocalDateTime lunchStart = LocalDateTime.of(date, wxStartTime);
        LocalDateTime lunchEnd = LocalDateTime.of(date, wxEndTime);
        LocalDateTime eveningStart = LocalDateTime.of(date, eveningStartTime);
        LocalDateTime eveningEnd = LocalDateTime.of(date, eveningEndTime);

        deductedMinutes = getDeductedMinutes(startTime, endTime, deductedMinutes, lunchStart, lunchEnd);

        deductedMinutes = getDeductedMinutes(startTime, endTime, deductedMinutes, eveningStart, eveningEnd);

        // 计算实际工作时间
        long actualWorkMinutes = totalMinutes - deductedMinutes;


        // 将实际工作时间转换为小时的小数形式
        double actualWorkHours = actualWorkMinutes / 60.0;

        // 将实际工作时间保留两位小数
        // 使用 Math.round() 方法将实际工作时间四舍五入到两位小数
        double v = Math.round(actualWorkHours * 100.0) / 100.0;

        // 输出结果
        System.out.println("实际工作时间:" + actualWorkMinutes / 60 + "小时 " + actualWorkMinutes % 60 + "分钟-----" + actualWorkMinutes);
        System.out.println("实际工作时间:" + v + "小时");
    }

    /**
     * 计算重叠部分的分钟数
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param deductedMinutes 已经减去的分钟数
     * @param restTimeStart 休息开始时间
     * @param restTimeEnd 休息结束时间
     * @return 重叠部分的分钟数
     */
    private static long getDeductedMinutes(LocalDateTime startTime, LocalDateTime endTime, long deductedMinutes, LocalDateTime restTimeStart, LocalDateTime restTimeEnd) {
        if (startTime.isBefore(restTimeEnd) && endTime.isAfter(restTimeStart)) {
            LocalDateTime overlapStart = startTime.isAfter(restTimeStart) ? startTime : restTimeStart;
            LocalDateTime overlapEnd = endTime.isBefore(restTimeEnd) ? endTime : restTimeEnd;

            deductedMinutes += Duration.between(overlapStart, overlapEnd).toMinutes();
        }
        return deductedMinutes;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值