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值班表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
MyBatis注解方式之@Update/@Delete使用详解
这篇文章主要介绍了MyBatis注解方式之@Update/@Delete使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-11-11


最新评论