工作日节假日调休日休息日的判断API-holiday
工作日节假日调休日休息日的判断API-holiday
1. 背景
从2019年开始接一个需求,调单设置超期反馈时间T+2及邮件发送时间T+1都需要排除休息日;之前一个接口http://api.goseek.cn/ 是可以获取到全年每一天的性质四种<后续介绍>;但是2020年需要更新数据了,这个页面就打不开了,开始想法自己实现,并想做成静态工具类。
2. 设计思路
若没有节假日,则只分为工作日和周末;国务院每年11或12月份公布下一年的节假日及调休日;由于这些日子比较少且是固定的,因此只需要将这些保存下来,通过代码逻辑就可以判断出一年中每一天的性质。
性质分成四种:
# 某一天的性质分成四种: # 0. 正常工作日为0,Weekday # 1. 正常周六日为1,Weekend # 2. 法定节假日为2,holiday # 3. 周六日调休补班为3,makeUp4Rest
*网: http://www.gov.cn/zhengce/content/2019-11/21/content_5454164.htm
经国务院批准,现将2020年元旦、春节、清明节、劳动节、端午节、国庆节和中秋节放假调休日期的具体安排通知如下。
一、元旦:2020年1月1日放假,共1天。
二、春节:1月24日至30日放假调休,共7天。1月19日(星期日)、2月1日(星期六)上班。
三、清明节:4月4日至6日放假调休,共3天。
四、劳动节:5月1日至5日放假调休,共5天。4月26日(星期日)、5月9日(星期六)上班。
五、端午节:6月25日至27日放假调休,共3天。6月28日(星期日)上班。
六、国庆节、中秋节:10月1日至8日放假调休,共8天。9月27日(星期日)、10月10日(星期六)上班。
##实现方式:
# 正常情况下,根据周六日即可获取正常工作日和周六日;
# 由于法定节假日及调休补班的日子比较少,将两种手动保存下来,作为排除即可。
# 2020年法定节假日
holiday_2020=0101,0124,0125,0126,0127,0128,0129,0130,0125,0125,0125,0125,0125,0125,0404,0405,0406,0501,0502,0503,0504,0505,0625,0627,1001,1002,1003,1004,1005,1006,1007,1008
# 2020年调休补班
makeUp4Rest_2020=0119,0201,0426,0509,0628,0927,1010
# 2021年法定节假日
#holiday_2021=
# 2021年调休补班
#makeUp4Rest_2021=
我采用的是将这些日期存放在配置文件中holiday.properties中,key后缀为年份,代码中动态去加载。
为了做成静态工具类WorkingDay,这里通过静态代码块将properties文件中的配置信息解析成两个Set集合:
//节假日
private static Set<String> holidaySet;
//调休补班
private static Set<String> makeUp4RestSet;
static {
try {
ClassPathResource cpr = new ClassPathResource("holiday.properties");
Properties properties = new Properties();
properties.load(cpr.getInputStream());
int year = new DateTime().getYear();
String holidayStr = (String) properties.get("holiday_" + year);
holidaySet = new HashSet<>(Arrays.asList(
StringUtils.split(holidayStr, ',')));
String makeUp4RestStr = (String) properties.get("makeUp4Rest_" + year);
makeUp4RestSet =
new HashSet<>(Arrays.asList(StringUtils.split(makeUp4RestStr, ',')));
logger.info("加载节假日配置文件得到holidaySet={},
makeUp4RestSet={}", holidaySet, makeUp4RestSet);
} catch (IOException e) {
logger.error("加载节假日配置文件holiday.properties出现异常:", e);
}
}
WorkingDay工具类的API:
//是否工作日
public static boolean isWorkingDay(Date date){}
//判断date的性质返回Enum或code
public DateTypeEnum judgeDateTypeEnum(Date date) {}
public Integer judgeDateTypeCode(Date date) {}
//获取与date相隔一定工作日的日期(days<0向前,days>0向后)
public static Date plusWorkingDay(Date date, Integer days){}
3. 总结
配置信息也可以存放在数据库中,当然也可以直接定义在代码中。当然更改数据库是最灵活的,不需要更新代码和重启服务器。
每年国务院发布一次节假日及调休信息后,只需要添加配置就可以了,后缀是需要配置的年份。
附件:
1. WorkingDay.java
import com.jd.common.util.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 工作日实现类
*
* @Author zhaohong
* @Date 2020/4/14 18:18
*/
public class WorkingDay {
private static Logger logger = LoggerFactory.getLogger(WorkingDay.class);
//节假日
private static Set<String> holidaySet;
//调休补班
private static Set<String> makeUp4RestSet;
static {
try {
ClassPathResource cpr = new ClassPathResource("holiday.properties");
Properties properties = new Properties();
properties.load(cpr.getInputStream());
int year = new DateTime().getYear();
String holidayStr = (String) properties.get("holiday_" + year);
holidaySet = new HashSet<>(Arrays.asList(StringUtils.split(holidayStr, ',')));
String makeUp4RestStr = (String) properties.get("makeUp4Rest_" + year);
makeUp4RestSet = new HashSet<>(Arrays.asList(StringUtils.split(makeUp4RestStr, ',')));
logger.info("加载节假日配置文件得到holidaySet={},makeUp4RestSet={}", holidaySet, makeUp4RestSet);
} catch (IOException e) {
logger.error("加载节假日配置文件holiday.properties出现异常:", e);
}
}
/**
* 获取与date相隔days个工作日
*
* @param date null默认为当前时间
* @param days null返回date
* @return
*/
public static Date plusWorkingDay(Date date, Integer days) {
if (date == null) {
date = new Date();
}
if (days == null || days.intValue() == 0) {
//days == 0时返回date
return date;
}
int daysAbs = Math.abs(days);
//days> 0,1;days<0,-1
int plusNum = days / daysAbs;
DateTime dateTime = new DateTime(date);
while (daysAbs > 0) {
dateTime = dateTime.plusDays(plusNum);
if (isWorkingDay(dateTime.toDate())) {
daysAbs--;
}
}
return dateTime.toDate();
}
/**
* 是否是工作日(需要工作的日子):包括调休补班
* # 某一天的性质分成四种:
* # 0. 正常工作日为0,Weekday
* # 1. 正常周六日为1,Weekend
* # 2. 法定节假日为2,holiday
* # 3. 周六日调休补班为3,makeUp4Rest
*
* @param date
* @return
*/
public static boolean isWorkingDay(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
String monDay = sdf.format(date);
//是否是节假日
if (holidaySet.contains(monDay)) {
return false;
}
//非节假日
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
//周日1---周六7
int week = calendar.get(Calendar.DAY_OF_WEEK);
//排除节假日之外的工作日必须工作;需要调休补班的周六日需要工作
if ((week > 1 && week < 7) || makeUp4RestSet.contains(monDay)) {
return true;
}
return false;
}
/**
* 取date的性质返回code 0/1/2/3
*
* @param date
* @return
*/
public Integer judgeDateTypeCode(Date date) {
DateTypeEnum dateTypeEnum = judgeDateTypeEnum(date);
return dateTypeEnum != null ? dateTypeEnum.getCode() : null;
}
/**
* 获取date的性质返回枚举类型
*
* @param date
* @return
*/
public DateTypeEnum judgeDateTypeEnum(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
String monDay = sdf.format(date);
//是否是节假日
if (holidaySet.contains(monDay)) {
return DateTypeEnum.HOLIDAY;
}
//调休补班日
if (makeUp4RestSet.contains(monDay)) {
return DateTypeEnum.MAKE_UP_4_REST;
}
//
//非节假日
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
//周日1---周六7
int week = calendar.get(Calendar.DAY_OF_WEEK);
if (week > 1 && week < 7) {
return DateTypeEnum.NORMAL_WEEKDAY;
}
return DateTypeEnum.NORMAL_WEEKEND;
}
/**
* 某一天的性质分成四种:
* 0. 正常工作日为0,Weekday
* 1. 正常周六日为1,Weekend
* 2. 法定节假日为2,holiday
* 3. 周六日调休补班为3,makeUp4Rest
*/
public enum DateTypeEnum {
NORMAL_WEEKDAY(0, "正常工作日"),
NORMAL_WEEKEND(1, "正常周六日"),
HOLIDAY(2, "节假日"),
MAKE_UP_4_REST(3, "调休补班日");//原是周六日才会需要补班
DateTypeEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
private int code;
private String desc;
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
}
2. holiday.properties文件
# 2020年法定节假日
holiday_2020=0101,0124,0125,0126,0127,0128,0129,0130,0125,0125,0125,0125,0125,0125,0404,0405,0406,0501,0502,0503,0504,0505,0625,0627,1001,1002,1003,1004,1005,1006,1007,1008
# 2020年调休补班
makeUp4Rest_2020=0119,0201,0426,0509,0628,0927,1010
# 2021年法定节假日
#holiday_2021=
# 2021年调休补班
#makeUp4Rest_2021=