|
|
@@ -0,0 +1,143 @@
|
|
|
+package com.malk.utils;
|
|
|
+
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+public abstract class UtilHoliday {
|
|
|
+
|
|
|
+ public static void loadHolidayData(int year, Map<Integer, Set<LocalDate>> holidayCache) {
|
|
|
+ if (holidayCache.containsKey(year)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ log.info("开始从 API 加载 {} 年的节假日数据...", year);
|
|
|
+ String url = "https://timor.tech/api/holiday/year/" + year;
|
|
|
+ String response = HttpUtil.get(url);
|
|
|
+
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(response);
|
|
|
+ if (jsonObject.getInteger("code") == 0) {
|
|
|
+ JSONObject holidayObj = jsonObject.getJSONObject("holiday");
|
|
|
+ Set<LocalDate> holidayDates = new HashSet<>();
|
|
|
+
|
|
|
+ // 解析 API 返回的数据
|
|
|
+ for (String key : holidayObj.keySet()) {
|
|
|
+ JSONObject item = holidayObj.getJSONObject(key);
|
|
|
+ String dateStr = item.getString("date"); // 格式通常为 "MM-dd"
|
|
|
+ LocalDate localDate = LocalDate.of(year,
|
|
|
+ Integer.parseInt(dateStr.split("-")[1]),
|
|
|
+ Integer.parseInt(dateStr.split("-")[2]));
|
|
|
+ Boolean isHoliday = item.getBoolean("holiday");
|
|
|
+ if (isHoliday){
|
|
|
+ holidayDates.add(localDate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ holidayCache.put(year, holidayDates);
|
|
|
+ System.out.println(holidayCache);
|
|
|
+ log.info("成功加载 {} 年节假日数据,共计 {} 天", year, holidayDates.size());
|
|
|
+ } else {
|
|
|
+ log.error("节假日 API 返回异常: {}", response);
|
|
|
+ System.out.println("c错误1");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("c错误2");
|
|
|
+ log.error("加载节假日数据失败: {}", e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void loadWorkdayData(int year, Map<Integer, Set<LocalDate>> workdayCache) {
|
|
|
+ if (workdayCache.containsKey(year)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ log.info("开始从 API 加载 {} 年的节假日数据...", year);
|
|
|
+ String url = "https://timor.tech/api/holiday/year/" + year;
|
|
|
+ String response = HttpUtil.get(url);
|
|
|
+
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(response);
|
|
|
+ if (jsonObject.getInteger("code") == 0) {
|
|
|
+ JSONObject holidayObj = jsonObject.getJSONObject("holiday");
|
|
|
+ Set<LocalDate> workdayDates = new HashSet<>();
|
|
|
+
|
|
|
+ // 解析 API 返回的数据
|
|
|
+ for (String key : holidayObj.keySet()) {
|
|
|
+ JSONObject item = holidayObj.getJSONObject(key);
|
|
|
+ String dateStr = item.getString("date"); // 格式通常为 "MM-dd"
|
|
|
+ LocalDate localDate = LocalDate.of(year,
|
|
|
+ Integer.parseInt(dateStr.split("-")[1]),
|
|
|
+ Integer.parseInt(dateStr.split("-")[2]));
|
|
|
+ Boolean isHoliday = item.getBoolean("holiday");
|
|
|
+ if (!isHoliday){
|
|
|
+ workdayDates.add(localDate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ workdayCache.put(year, workdayDates);
|
|
|
+ System.out.println(workdayDates);
|
|
|
+ log.info("成功加载 {} 年调休日数据,共计 {} 天", year, workdayCache.size());
|
|
|
+ } else {
|
|
|
+ log.error("节假日 API 返回异常: {}", response);
|
|
|
+ System.out.println("c错误1");
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println("c错误2");
|
|
|
+ log.error("加载节假日数据失败: {}", e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断指定日期是否为节假日
|
|
|
+ */
|
|
|
+ public static boolean isHoliday(LocalDate date, Map<Integer, Set<LocalDate>> holidayCache) {
|
|
|
+ Set<LocalDate> dates = holidayCache.get(date.getYear());
|
|
|
+ if (dates == null) {
|
|
|
+ loadHolidayData(date.getYear(),holidayCache);
|
|
|
+ dates = holidayCache.getOrDefault(date.getYear(), Collections.emptySet());
|
|
|
+ }
|
|
|
+ return dates.contains(date);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断指定日期是否为工作日
|
|
|
+ * 逻辑:如果是调休补班日 -> 是工作日;如果是法定节假日 -> 不是工作日;否则按周一到周五判断
|
|
|
+ */
|
|
|
+ public static boolean isWorkday(LocalDate date, Map<Integer, Set<LocalDate>> holidayCache, Map<Integer, Set<LocalDate>> workdayCache) {
|
|
|
+ int year = date.getYear();
|
|
|
+ Set<LocalDate> workdays = workdayCache.getOrDefault(year, Collections.emptySet());
|
|
|
+ Set<LocalDate> holidays = holidayCache.getOrDefault(year, Collections.emptySet());
|
|
|
+
|
|
|
+ // 缓存未命中时触发加载
|
|
|
+ if (workdayCache.get(year) == null ) {
|
|
|
+ loadWorkdayData(year, workdayCache);
|
|
|
+ workdays = workdayCache.getOrDefault(year, Collections.emptySet());
|
|
|
+ }
|
|
|
+ // 缓存未命中时触发加载
|
|
|
+ if (holidayCache.get(year) == null) {
|
|
|
+ loadHolidayData(year, holidayCache);
|
|
|
+ holidays = holidayCache.getOrDefault(year, Collections.emptySet());
|
|
|
+ }
|
|
|
+ // 优先判断调休补班日(周末变工作日)
|
|
|
+ if (workdays.contains(date)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // 其次判断法定节假日
|
|
|
+ if (holidays.contains(date)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 最后按常规周末判断(1=周一 ... 7=周日)
|
|
|
+ int dayOfWeek = date.getDayOfWeek().getValue();
|
|
|
+ return dayOfWeek >= 1 && dayOfWeek <= 5;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|