1.思路:
<1>. 维持一个特殊的工作日数组(周六、周日工作),一个特殊的休息日数组(周一到周五休息)。
<2>. 以24小时(一个工作日)为基本单位,遍历日历,遇到工作日,period 减少24小时,直到period减少为0;
<4>. 工作日判断逻辑:周一到周五,如果不是特殊的休息日,为工作日; 周六和周日,如果是特殊的工作日,则为工作日。
2.具体实现:
package com.fengyurong.demo;
/**
* @author fengyurong
* @date 2020-04-14 15:39
*/
@Data
@Component
public class Holiday {
/**
* 特殊的工作日(星期六、日工作)
*/
private static final List<String> SPECIAL_WORK_DAYS = Arrays.asList(
"20200119", "20200201", "20200426", "20200509", "20200628",
"20200927", "20201010");
/**
* 特殊的休息日(星期一到五休息)
*/
private static final List<String> SPECIAL_REST_DAYS = Arrays.asList(
"20200101", "20200124", "20200127", "20200128", "20200129", "20200130",
"20200406", "20200501", "20200504", "20200505", "20200625", "20200626",
"20201001", "20201002", "20201005", "20201006", "20201007", "20201008");
/**
* 获取 period秒 后的 工作日 时间戳
*
* @param baseTime 基础时间 (秒级时间戳)
* @param period 增加时间 (秒级时间戳)
* @return
*/
public int getStampAfterPeriod(int baseTime, int period) {
if (period == 0) {
return baseTime;
}
//获取日期实例
Calendar calendar = Calendar.getInstance();
//初始化日期实例为入参的基础时间
calendar.setTimeInMillis(baseTime*1000L);
//获取period的绝对值,period的正负 用来判断是基础时间以前还是以后的时间
int daysAbs = Math.abs(period);
//一天的秒数
int daySecond = 24 * 60 * 60;
//定义每次增加的秒数,以24小时为基本单位
int step = 0;
//周六日
List<Integer> weekend = Arrays.asList(Calendar.SATURDAY,Calendar.SUNDAY);
while (step <= daysAbs) {
//如果period小于24小时,则步数等于period
step = daysAbs < daySecond ? daysAbs : daySecond;
//给基础时间 增加 step 秒
calendar.add(Calendar.SECOND, step);
//解析时间为 yyyyMMdd 格式,用来比对特殊的工作日或休息日
String calendarStr = DateFormatUtils.format(calendar.getTime(), "yyyyMMdd");
if (weekend.contains(calendar.get(Calendar.DAY_OF_WEEK)) && SPECIAL_WORK_DAYS.contains(calendarStr)) {
// 周六日 上班 就算1个工作日
daysAbs -= step;
} else if(!weekend.contains(calendar.get(Calendar.DAY_OF_WEEK)) && !SPECIAL_REST_DAYS.contains(calendarStr)) {
// 周一到周五 不休息 就算1个工作日
daysAbs -= step;
}
}
//返回秒级时间戳
return (int)(calendar.getTimeInMillis() / 1000);
}
}