diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/WorkDaysUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/WorkDaysUtils.java index 6aa60593c..49c0d30eb 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/WorkDaysUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/WorkDaysUtils.java @@ -1,9 +1,12 @@ package org.dromara.common.core.utils; +import cn.hutool.core.collection.CollUtil; import lombok.AccessLevel; import lombok.NoArgsConstructor; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; /** * 工作日工具类 @@ -13,7 +16,12 @@ import java.util.*; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class WorkDaysUtils { - private static final Map DAYS_IN_YEARS = new HashMap<>(); + private static final Map DAYS_IN_YEARS = new ConcurrentHashMap<>(); + private static final ReentrantLock LOCK = new ReentrantLock(); + //工作日 + public static final int WORKDAY = 0; + //休息日 + public static final int RESTDAY = 1; /** * 根据开始日期和工作日数计算截止日期 @@ -34,7 +42,7 @@ public class WorkDaysUtils { // 循环找到指定的工作日数 while (workDays > 0) { // 检查当前日期是否是工作日 - if (daysArray[endIndex] == 0) { + if (daysArray[endIndex] == WORKDAY) { workDays--; } // 结束条件:工作日数为零 @@ -79,7 +87,7 @@ public class WorkDaysUtils { //开始日期年份天 Integer[] daysArray = daysInYear(startYear); for (int i = getDayOfYearIndex(start); i <= getDayOfYearIndex(end); i++) { - if (daysArray[i] == 0) { + if (daysArray[i] == WORKDAY) { workDays++; } } @@ -88,7 +96,7 @@ public class WorkDaysUtils { Integer[] startYearDaysArray = daysInYear(startYear); int startIndex = getDayOfYearIndex(start); for (int i = startIndex; i < startYearDaysArray.length; i++) { - if (startYearDaysArray[i] == 0) { + if (startYearDaysArray[i] == WORKDAY) { workDays++; } } @@ -97,7 +105,7 @@ public class WorkDaysUtils { Integer[] endYearDaysArray = daysInYear(endYear); int endIndex = getDayOfYearIndex(end); for (int i = 0; i <= endIndex; i++) { - if (endYearDaysArray[i] == 0) { + if (endYearDaysArray[i] == WORKDAY) { workDays++; } } @@ -106,7 +114,7 @@ public class WorkDaysUtils { for (int year = startYear + 1; year < endYear; year++) { Integer[] fullYearDaysArray = daysInYear(year); for (Integer integer : fullYearDaysArray) { - if (integer == 0) { + if (integer == WORKDAY) { workDays++; } } @@ -115,6 +123,13 @@ public class WorkDaysUtils { return workDays; } + /** + * 清空所有年份的数据 + */ + public static void clearAllData() { + DAYS_IN_YEARS.clear(); + } + /** * 获取指定年份的天数数组。如果指定年份的数据不存在,则生成并缓存数据 * @@ -122,13 +137,25 @@ public class WorkDaysUtils { * @return 表示一年中每一天的状态数组,0 表示工作日,1 表示周末 */ private static Integer[] daysInYear(Integer year) { + // 先检查缓存 if (DAYS_IN_YEARS.containsKey(year)) { return DAYS_IN_YEARS.get(year); - } else { + } + + // 如果缓存中不存在,则进行加锁 + LOCK.lock(); + try { + // 再次检查缓存,防止在等待锁期间其他线程已经生成了数据 + if (DAYS_IN_YEARS.containsKey(year)) { + return DAYS_IN_YEARS.get(year); + } + // 如果年份数据不存在,则生成指定年份的数据 Integer[] daysArray = generateDaysArray(year); DAYS_IN_YEARS.put(year, daysArray); return daysArray; + } finally { + LOCK.unlock(); } } @@ -147,64 +174,36 @@ public class WorkDaysUtils { for (int i = 0; i < daysInYear; i++) { int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - daysArray[i] = (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) ? 1 : 0; + daysArray[i] = (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) ? RESTDAY : WORKDAY; calendar.add(Calendar.DAY_OF_MONTH, 1); } - - // 将工作日设置为休息日(假设用于标记节假日) - markWorkdaysAsRestdays(daysArray, new ArrayList<>()); - // 将休息日设置为工作日(假设用于标记补班的工作日) - markRestdaysAsWorkdays(daysArray, new ArrayList<>()); + //设置为工作日(假设用于标记补班的工作日) + updateDaysArray(daysArray, Collections.emptyList(), WORKDAY); + //设置为休息日(假设用于标记节假日) + updateDaysArray(daysArray, Collections.emptyList(), RESTDAY); return daysArray; } /** - * 将工作日设置为休息日(假设用于标记节假日) + * 根据日期下标更新 daysArray,将对应下标的值改为指定值 * - * @param daysArray 原始的天数数组 - * @param holidays 节假日日期列表 - * @return 更新后的天数数组 + * @param daysArray 原始的天数数组 + * @param days 要修改的日期列表 + * @param valueToSet 休息日用 1,工作日用 0 */ - private static Integer[] markWorkdaysAsRestdays(Integer[] daysArray, List holidays) { - return updateDaysArray(daysArray, holidays, true); - } - - /** - * 将休息日设置为工作日(假设用于标记补班的工作日) - * - * @param daysArray 原始的天数数组 - * @param holidays 休息日日期列表 - * @return 更新后的天数数组 - */ - private static Integer[] markRestdaysAsWorkdays(Integer[] daysArray, List holidays) { - return updateDaysArray(daysArray, holidays, false); - } - - /** - * 根据节假日下标更新 daysArray,将对应下标的值改为指定值 - * - * @param daysArray 原始的天数数组 - * @param holidays 节假日日期列表 - * @param isHoliday 是否为节假日,如果为 true 则表示节假日;如果为 false 则表示工作日 - * @return 更新后的天数数组 - */ - private static Integer[] updateDaysArray(Integer[] daysArray, List holidays, Boolean isHoliday) { - if (holidays == null || holidays.isEmpty()) { - return daysArray; + private static void updateDaysArray(Integer[] daysArray, List days, int valueToSet) { + if (CollUtil.isEmpty(days)) { + return; } - // 节假日用 1,工作日用 0 - int valueToSet = isHoliday ? 1 : 0; - - // 遍历节假日下标数组,将对应的 daysArray 元素设置为1 - for (Date holiday : holidays) { + // 遍历日期下标数组,将对应的 daysArray 元素设置为1 + for (Date holiday : days) { int index = getDayOfYearIndex(holiday); // 确保下标在有效范围内 if (index >= 0 && index < daysArray.length) { daysArray[index] = valueToSet; } } - return daysArray; } /**