某一个时间点加天数 跳过双休日 和节假日

0、创建节假日表


SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for jsh_holiday
-- ----------------------------
DROP TABLE IF EXISTS `jsh_holiday`;
CREATE TABLE `jsh_holiday`  (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `holiday` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `tenant_id` int NULL DEFAULT NULL,
  `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 882 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

1、获取当年所有的国家节假日存在一个表中 通过接口
https://timor.tech/api/holiday/year/2024

public BaseResponseInfo initHolidays() throws UnirestException {
        BaseResponseInfo res = new BaseResponseInfo();
        // ... 添加其他节假日
        HttpResponse response = Unirest.get("https://timor.tech/api/holiday/year/2024")
                .header("X-Access-Token", "af0d9c6e6f3d4e04b79e7c7d5b54c306_63")
                .header("Content-Type", "application/json").asString();
        Object body = response.getBody();
        JSONObject jsonObject = JSONObject.parseObject(body.toString());
        if (jsonObject.get("holiday") != null) {
            JSONObject json = JSON.parseObject(jsonObject.get("holiday").toString());
            for (Map.Entry<String, Object> entry : json.entrySet()) {
                Holiday holiday = new Holiday();
                holiday.setHoliday("2024-" + entry.getKey());
                JSONObject value = JSON.parseObject(entry.getValue().toString());
                holiday.setType(value.get("holiday").toString());
                holidayMapper.insert(holiday);
            }
        }
        res.data = null;
        res.code = 200;
        return res;
    }

2、工具类中封装好一个通用方法 跳过双休及假日的方法

//传入参数跳过及假日
    public static LocalDate calculateEndDate2(LocalDate startDate, int workDays, Map<String, String> holidays) {
        int count = 0;
        LocalDate date = startDate;
        date = date.minusDays(1);

        while (count < workDays) {
            date = date.plusDays(1);
            // 检查是否是周末
            if (date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY) {
                // 检查是否是节假日
                String formattedDate = date.toString();

                if (!holidays.containsKey(formattedDate)) {
                    count++;
                }
            } else {
                //遇到周末刚好补办
                String formattedDate = date.toString();
                //是不是周末补办 存在节假日表里面 并且是补办的状态
                if (holidays.containsKey(formattedDate) && !"true".equals(holidays.get(formattedDate))) {
                    count++;
                }
            }
        }
        return date;
    }

3、业务代码

public BaseResponseInfo autoSchedulingEndTime1(@RequestBody JSONObject jsonObject) throws ParseException, UnirestException {
        BaseResponseInfo res = new BaseResponseInfo();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 定义节假日,格式为 "YYYY-MM-DD"
        Map<String, String> holidays = this.getHoliday();

        String startTime = jsonObject.get("startTime").toString(); //开始时间
        BigDecimal quantity = BigDecimal.valueOf(Double.valueOf(jsonObject.get("quantity").toString())); //数量
        BigDecimal beat = BigDecimal.valueOf(Double.valueOf(jsonObject.get("beat").toString()));//节拍
        BigDecimal person = BigDecimal.valueOf(Double.valueOf(jsonObject.get("person").toString()));//人员
        String offferTime = jsonObject.get("offferTime").toString();//交货时间
        Long day = DateUtils.daysBetween(LocalDate.parse(sdf.format(sdf.parse(startTime))), LocalDate.parse(sdf.format(sdf.parse(offferTime)))); //为啥要加1就是他算的差值 是从当天开始的
        // 需要计算的工作日天数
        BigDecimal workDays = BigDecimal.ZERO;
        BigDecimal overtime = BigDecimal.ZERO;

        //数量/节拍/人员 需要的工作天数
        workDays = (quantity.divide(beat, 0, RoundingMode.CEILING).divide(person, 0, RoundingMode.CEILING)).setScale(0, RoundingMode.CEILING); //除不进 向上取整
        //正常需要的工作时长
        overtime = workDays.multiply(new BigDecimal(8)).divide(BigDecimal.valueOf((day + 1)), 2, RoundingMode.HALF_UP); //保留两位小数
        Date parse = sdf.parse(startTime);
        String format_start = sdf.format(parse);
        // 开始日期
        LocalDate startDate = LocalDate.parse(format_start);

        LocalDate endDate = DateUtils.calculateEndDate2(startDate, workDays.intValue(), holidays); //结束时间
        System.out.println("结束日期是: " + endDate);
        JSONObject json = new JSONObject();
        //减去工作时间长都为8小时 为负数的情况下就是说明开始时间和交付时间很充裕 不需要加班
        if (overtime.subtract(new BigDecimal(8)).doubleValue()<0){
            json.put("overtime", "0");  //加班时间
            json.put("totaltime", "8"); //总时长
        }else {
            json.put("overtime", overtime.subtract(new BigDecimal(8)));
            json.put("totaltime", overtime);
        }
        json.put("workTime", "8"); //工作时间
        json.put("endDate", endDate); //结束时间
        res.data = json;
        res.code = 200;
        return res;

    }

4、计算两个时间段差值

 //两个时间段的差值
    public static Long daysBetween(LocalDate startDate, LocalDate endDate) {
        long daysBetween = ChronoUnit.DAYS.between(startDate, endDate);
        return daysBetween;
    }
posted @ 2024-10-28 09:08  泡泡大可爱  阅读(7)  评论(0编辑  收藏  举报