Java批量生成节假日值班表Rota的示例详解
作者:weixin_46244623
本文介绍了一个基于2025年1月真实节假日安排的Java值班排班算法的纯内存实现,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
本文介绍了一个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值班表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
