Java批量生成节假日值班表Rota的示例详解
本文介绍了一个Java值班排班算法的纯内存实现,主要基于2025年1月真实节假日安排
算法核心逻辑包括:
1) 定义排班和节假日实体类
2) 实现排班方法,考虑节假日、周末和补班日
3) 特殊处理月底双人值班规则(仅在需要值班的日期生效)
算法输出展示了2025年1月的正确排班结果,包括元旦、周末和春节假期的值班人员分配,该实现无需数据库,完全在内存中模拟,适用于节假日敏感的值班排班场景,
一、2025 年 1 月真实节假日说明(重要)
根据公布的节假日安排(以示例简化):
| 日期 | 说明 |
|---|---|
| 2025-01-01 | 元旦(休息) |
| 2025-01-26 | 周日补班 |
| 2025-01-28 ~ 01-31 | 春节(休息) |
注意:
- 01-31(星期五)虽然是工作日,但因春节属于法定节假日,应值班
- 月底双人值班只能发生在“本来就需要值班的日期”
二、模拟实体类(不变)
Rota
class Rota {
LocalDate date;
List<String> users;
String week;
String holidayType; // 0-普通 1-节假日 2-补班
String remark;
@Override
public String toString() {
return date + " " + week + " -> " + users + " [" + remark + "]";
}
}
Holidays
class Holidays {
LocalDate date;
String name;
boolean offDay; // true=休息 false=补班
Holidays(LocalDate date, String name, boolean offDay) {
this.date = date;
this.name = name;
this.offDay = offDay;
}
}
三、修正后的核心排班方法(关键修改点已标注)
public static List<Rota> batchInsertRota(
LocalDate startDate,
LocalDate endDate,
List<String> employees,
boolean twoDutyAtMonthEnd,
List<Holidays> holidaysList
) {
Set<LocalDate> holidayDates = holidaysList.stream()
.filter(h -> h.offDay)
.map(h -> h.date)
.collect(Collectors.toSet());
Set<LocalDate> weekendWorkDates = holidaysList.stream()
.filter(h -> !h.offDay)
.map(h -> h.date)
.collect(Collectors.toSet());
Map<String, LocalDate> lastDuty = new HashMap<>();
employees.forEach(e -> lastDuty.put(e, startDate.minusDays(1)));
List<String> dutyQueue = new ArrayList<>(employees);
List<Rota> result = new ArrayList<>();
LocalDate current = startDate;
while (!current.isAfter(endDate)) {
LocalDate lastDayOfMonth = current.with(TemporalAdjusters.lastDayOfMonth());
boolean isWeekend = current.getDayOfWeek() == DayOfWeek.SATURDAY
|| current.getDayOfWeek() == DayOfWeek.SUNDAY;
boolean isHoliday = holidayDates.contains(current);
boolean isWeekendWork = weekendWorkDates.contains(current);
// 是否“本来就需要值班”
boolean needDutyDay = (isWeekend || isHoliday) && !isWeekendWork;
if (needDutyDay) {
List<String> dutyUsers = new ArrayList<>();
String user1 = Collections.min(dutyQueue, Comparator.comparing(lastDuty::get));
dutyQueue.remove(user1);
lastDuty.put(user1, current);
dutyUsers.add(user1);
// 月底双人:仅在“已是值班日”的前提下
if (twoDutyAtMonthEnd &&
ChronoUnit.DAYS.between(current, lastDayOfMonth) <= 1 &&
!dutyQueue.isEmpty()) {
String user2 = Collections.min(dutyQueue, Comparator.comparing(lastDuty::get));
dutyQueue.remove(user2);
lastDuty.put(user2, current);
dutyUsers.add(user2);
}
Rota rota = new Rota();
rota.date = current;
rota.users = dutyUsers;
rota.week = "星期" + "一二三四五六日".charAt(current.getDayOfWeek().getValue() - 1);
if (isHoliday) {
rota.holidayType = "1";
rota.remark = holidaysList.stream()
.filter(h -> h.date.equals(current))
.map(h -> h.name)
.findFirst().orElse("节假日");
} else {
rota.holidayType = "0";
rota.remark = "周末";
}
result.add(rota);
dutyQueue.addAll(dutyUsers);
}
current = current.plusDays(1);
}
return result;
}
四、Demo 主方法(真实节假日数据)
public static void main(String[] args) {
LocalDate start = LocalDate.of(2025, 1, 1);
LocalDate end = LocalDate.of(2025, 1, 31);
List<String> employees = Arrays.asList(
"张三", "李四", "王五", "赵六"
);
// 真实 2025 年 1 月节假日(示例)
List<Holidays> holidays = Arrays.asList(
new Holidays(LocalDate.of(2025, 1, 1), "元旦", true),
new Holidays(LocalDate.of(2025, 1, 26), "春节调休补班", false),
new Holidays(LocalDate.of(2025, 1, 28), "春节", true),
new Holidays(LocalDate.of(2025, 1, 29), "春节", true),
new Holidays(LocalDate.of(2025, 1, 30), "春节", true),
new Holidays(LocalDate.of(2025, 1, 31), "春节", true)
);
List<Rota> rotaList = batchInsertRota(
start,
end,
employees,
true,
holidays
);
rotaList.forEach(System.out::println);
}
五、最终正确 & 真实的控制台输出
2025-01-01 星期三 -> [张三] [元旦]
2025-01-04 星期六 -> [李四] [周末]
2025-01-05 星期日 -> [王五] [周末]
2025-01-11 星期六 -> [赵六] [周末]
2025-01-12 星期日 -> [张三] [周末]
2025-01-18 星期六 -> [李四] [周末]
2025-01-19 星期日 -> [王五] [周末]
2025-01-25 星期六 -> [赵六] [周末]
2025-01-28 星期二 -> [张三] [春节]
2025-01-29 星期三 -> [李四] [春节]
2025-01-30 星期四 -> [王五, 赵六] [春节]
2025-01-31 星期五 -> [张三, 李四] [春节]
到此这篇关于Java批量生成节假日值班表Rota的示例详解的文章就介绍到这了,更多相关Java值班表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
java.net.ConnectException异常的正确解决方法(亲测有效!)
java.net.ConnectException异常是与网络相关的最常见的Java异常之一,建立从客户端应用程序到服务器的TCP连接时,我们可能会遇到它,这篇文章主要给大家介绍了关于java.net.ConnectException异常的正确解决方法,需要的朋友可以参考下2024-01-01
idea报错:程序包org.springframework.web.bind.annotation不存在
在用本地的maven仓库的时候会org.springframework.web.bind.annotation不存在的错误,本文就详细的介绍一下解决方法,感兴趣的可以了解下2023-08-08
Java并发编程必备之Synchronized关键字深入解析
本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种使用方式:修饰代码块、修饰普通方法和修饰静态方法,感兴趣的朋友一起看看吧2025-04-04


最新评论