前言
在日常开发中,我们经常需要判断某一天是工作日还是休息日。
遗憾的是,常见工具类库中并没有直接提供"节假日判断"的功能。原因在于:中国的节假日安排由国务院每年统一发布,存在动态性和不确定性。
因此,一个可行的方案是:维护一份节假日数据,并封装成工具类供项目调用 。下面我分享一个基于 Java + JSON + 定时检测
的实现方案。
原理说明
-
数据来源:国务院每年 11 月前后会发布次年的节假日安排;
-
数据格式 :节假日信息经过处理后保存为
JSON 文件
; -
工具类逻辑:
- 启动时加载 2007 年至今的节假日数据;
- 提供方法
isRestDay
/isWorkDay
判断某天状态; - 默认规则:如果当天未配置,则按周六日为休息日。
-
提醒机制 :通过单元测试或定时任务,在 12 月份自动检查下一年节假日文件是否存在,避免遗漏。
代码实现
1. 测试类:检测是否加载节假日数据
java
@Test
void testHolidayStatus() {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
final int monthValue = now.getMonthValue();
// 如果当前时间是12月,则优先检查下一年的节假日数据
int currentYear = monthValue == 12 ? now.getYear() + 1 : now.getYear();
System.out.printf("startYear:%s, currentYear:%s, 一共%s年%n",
HolidayUtil.START_YEAR, currentYear, currentYear - HolidayUtil.START_YEAR + 1);
for (int year = HolidayUtil.START_YEAR; year <= currentYear; year++) {
DateTime holiday = DateUtil.parse(String.format("%s-10-01", year));
if (Objects.isNull(HolidayUtil.getHolidayStatus(holiday))) {
throw new RuntimeException(String.format("当前已到12月,请补充【%s】年的放假文件", year));
}
assertTrue(HolidayUtil.isRestDay(holiday));
}
System.out.println(HolidayUtil.isRestDay(DateUtil.parse("2025-09-28")));
}
2. 工具类:HolidayUtil
java
public class HolidayUtil {
private static final Map<String, Boolean> HOLIDAY_MAP = new HashMap<>();
public static final int START_YEAR = 2007;
static {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
int currentYear = now.getYear();
for (int year = START_YEAR; year <= currentYear; year++) {
loadYear(year);
}
}
@SneakyThrows
public static void loadYear(int year) {
String fileName = String.format("holiday/%d.txt", year);
URL resource = HolidayUtil.class.getClassLoader().getResource(fileName);
if (resource == null) {
throw new RuntimeException("未找到节假日文件: " + fileName);
}
try (InputStream is = new FileInputStream(new File(resource.toURI()))) {
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object>> list = mapper.readValue(is, new TypeReference<>() {});
for (Map<String, Object> item : list) {
HOLIDAY_MAP.put((String) item.get("date"), (Boolean) item.get("holiday"));
}
}
}
public static Boolean getHolidayStatus(DateTime date) {
return HOLIDAY_MAP.get(date.toDateStr());
}
public static boolean isRestDay(DateTime date) {
Boolean status = getHolidayStatus(date);
if (status != null) return status;
return date.dayOfWeekEnum() == DateTime.DayOfWeek.SATURDAY
|| date.dayOfWeekEnum() == DateTime.DayOfWeek.SUNDAY;
}
public static boolean isWorkDay(DateTime date) {
return !isRestDay(date);
}
}
节假日数据格式
节假日数据维护为 JSON 文件
,结构如下:
json
[
{ "date": "2025-01-01", "holiday": true },
{ "date": "2025-01-26", "holiday": false },
{ "date": "2025-02-08", "holiday": false },
{ "date": "2025-05-01", "holiday": true },
{ "date": "2025-09-28", "holiday": false }
]
holiday = true
→ 表示节假日/休息日holiday = false
→ 表示调休上班
检测机制
为了避免忘记维护数据,可以在单元测试或定时任务中加入 文件存在性检查 。
比如在每年 12 月,检查下一年的文件是否存在,如果不存在就抛出异常提醒。
总结
本文实现了一个简易的 节假日判断工具类,其核心思路是:
- 通过维护每年的国务院放假数据(JSON 文件);
- 在工具类中加载并判断日期状态;
- 加入提醒机制,保证节假日数据及时更新。
这个工具可以广泛应用在:
- OA 系统请假审批
- 考勤/排班计算
- 财务/薪资发放逻辑
简单易用,但实用性很强。 🚀