一、节假日数据维护、
这里采用Apollo配置中心、可以实时更新
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* @author 傲寒
* @date 2023/1/9
*/
@Configuration
@Data
public class HolidayProperties {
/**
* 节假日配置可从政府官网获取
* <p>
* <a href="http://www.gov.cn/fuwu/2022-12/08/content_5730853.htm">http://www.gov.cn/fuwu/2022-12/08/content_5730853.htm</a>
* <p>
* jsonConfig 如下=
* <p>
* {
* "2023":{
* "holiday":["01-01~01-02","01-21~01-27","04-05~04-05","04-29~05-03","06-22~06-24","09-29~10-06"],
* "weekday":["01-28","01-29","04-23","05-06","06-25","10-07","10-08"]
* }
* }
*
* galaxy.holiday.json.config = jsonConfig
*/
@Value("${galaxy.holiday.json-config}")
private String holidayJson;
}
二、工具类
其中**DateUtil**
使用的hutool
,**Json**
使用的Jackson
package com.huize.galaxy.util;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.text.MessageFormat;
import java.util.*;
/**
* 节假日工具类
* <p>
* #节假日配置可从政府官网获取
* <p>
* <a href="http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm">http://www.gov.cn/zhengce/content/2021-10/25/content_5644835.htm</a>
*
* @author 傲寒
* @date 2023/1/9
*/
@Component
public class HolidayUtils implements ApplicationRunner, ApplicationContextAware {
private static final String MONTH_DAY_FORMAT = "MM-dd";
private static final String DATE_SPLIT = "~";
private static final int ZERO = 0;
private static final int ONE = 1;
private static final String HOLIDAY_AND_VACATIONS = "节假日";
private static final String MAKE_UP_SHIFT = "补班";
private static final String WEEKEND = "周末";
private static final String WEEKDAY = "工作日";
private ApplicationContext applicationContext = null;
private static HolidayProperties holidayProperties;
private static final ObjectMapper mapper = new ObjectMapper();
static {
mapper.setSerializationInclusion(Include.NON_NULL);
//设置输入时忽略JSON字符串中存在而Java对象实际没有的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* 是工作日
* 是否为工作日
*
* @param date 当地日期
* @return boolean
*/
public static boolean isWeekday(Date date) {
return getHolidayAndVacations(date).isWeekDay();
}
/**
* 节日和假期
* 1、如果为节假日:false
* 2、如果为补班日:true
* 3、如果为周末:false,否则true
*
* @param localDate 当地日期
* @return type:节假日/补班/周末/工作日,isWeekDay:工作日/补班-true,节假日/周末-false
*/
public static HolidayRes getHolidayAndVacations(Date localDate) {
int year = DateUtil.year(localDate);
HolidayModel holidayModel = getConfig(year);
String monthDay = DateUtil.format(localDate, MONTH_DAY_FORMAT);
//是否为节假日
List<String> holidayList = holidayModel.getHoliday();
if (CollUtil.isNotEmpty(holidayList)) {
for (String holiday : holidayList) {
String[] dateArr = holiday.split(DATE_SPLIT);
String start = dateArr[ZERO];
String end = dateArr[ONE];
if (monthDay.compareTo(start) >= ZERO && end.compareTo(monthDay) >= ZERO) {
return new HolidayRes(HOLIDAY_AND_VACATIONS, false);
}
}
}
//是否为调休日
List<String> weekdayList = holidayModel.getWeekday();
for (String weekday : weekdayList) {
if (monthDay.compareTo(weekday) == ZERO) {
return new HolidayRes(MAKE_UP_SHIFT, true);
}
}
//是否为周末
boolean isWeekend = isWeeks(localDate);
if (isWeekend) {
return new HolidayRes(WEEKEND, false);
}
return new HolidayRes(WEEKDAY, true);
}
/**
* 判断指定时间是否是周末
*
* @param date 指定的时间
* @return true:是周末,false:非周末
*/
public static boolean isWeeks(Date date) {
boolean isWeek;
isWeek = (getWeek(date) - ONE == ZERO || getWeek(date) - ONE == ZERO);
return isWeek;
}
/**
* 求出指定时间那天是星期几
*
* @param date 指定的时间
* @return 1-7
*/
public static int getWeek(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.DAY_OF_WEEK);
}
/**
* 获取配置
*
* @param year 年
* @return {@link HolidayModel}
*/
private static HolidayModel getConfig(@NonNull int year) {
Map<Integer, HolidayModel> configMap = json2Object(holidayProperties.getHolidayJson(), new TypeReference<Map<Integer, HolidayModel>>() {
});
if (Objects.isNull(configMap)) {
throw new IllegalArgumentException("未配置年度的节假日安排,请联系员导入");
}
HolidayModel holidayModel = configMap.get(year);
if (Objects.isNull(holidayModel)) {
throw new IllegalArgumentException(MessageFormat.format("[{0}]年还未配置年度的节假日安排,请联系员导入", year));
}
return holidayModel;
}
@Override
public void run(ApplicationArguments args) {
holidayProperties = applicationContext.getBean(HolidayProperties.class);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Assert.notNull(applicationContext, "applicationContext不存在");
this.applicationContext = applicationContext;
}
/**
* json2对象
*
* @param json json
* @param tr tr
* @return {@link T}
*/
private static <T> T json2Object(String json, TypeReference<T> tr) {
if (!StringUtils.hasLength(json)) {
return null;
}
T t = null;
try {
t = mapper.readValue(json, tr);
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
}
解析节假日model
/**
* @author 傲寒
* @date 2023/1/9
*/
@Data
public class HolidayModel {
/**
* 节假日配置,为区间,如果只有一天,也要写成MM-DD~MM-DD的格式
*/
private List<String> holiday;
/**
* 工作日配置,为单个值,且格式需要为MM-dd
*/
private List<String> weekday;
}
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author 傲寒
* @date 2023/1/9
*/
@Data
@AllArgsConstructor
public class HolidayRes {
/**
* 类型
*/
private String type;
/**
* 是否是工作日
*/
private boolean isWeekDay;
}