某一个时间点加天数 跳过双休日 和节假日
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;
}