一、背景描述
数据库中存储节假日,其数据库存储节假日内容为:①周一到周5放假的节假日日期(isweek=false) ②周六、周日补假的节假日日期(isweek = true)。现有需求,给定一个日期和工作日,返回工作日之后的日期。(注意:有不能把数据库中所有数据一次性全部读入的情况限制)isweek:数据库中的一个字段,标识是周一至周五,还是周六周日
二、代码说明
1.根据日期,返回days个工作日后的日期与现在日期的差值,此过程不考虑,节假日
代码如下(示例):
/**
* 根据日期,返回days个工作日后的日期,此过程不考虑,节假日
* @param date
* @param days
* @return
*/
private int getRollWeekDays(Date date,int days){
int realRollDay = 0;
//判断第一天是不是周末或周日
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
//先判断是否为周末
int currentWeek = calendar.get(Calendar.DAY_OF_WEEK);
if (currentWeek == Calendar.SUNDAY || currentWeek == Calendar.SATURDAY) {
//如果是周六则滚到周日,每周的开始
realRollDay = currentWeek / 7;
//将日期滚到到周一
currentWeek = Calendar.SUNDAY;
}
//获取当前距离周一的时间差(2=1+1,第一个1是平衡系统的,第二个1是减去今天的)
int diffValue = currentWeek - Calendar.MONDAY;
//只有周末情况 (周末 + days) 第一个表示几个工作日;第二个计算会跨过的周末
realRollDay += days + (days + diffValue) / 5 * 2;
return realRollDay;
}
2.给定一个数字days(表示天数) 返回从现在开始的days以后的那天日期
代码如下(示例):
```java
/**
* 给定一个数字days(表示天数)
* 返回从现在开始的days以后的那天日期
*
* @param date
* @param days
* @return
*/
@Override
public Date getAfterDate(Date date, Integer days) {
//设计一个标识,需要滚动的日期数
int realRollDay = 0;
//获取days工作日后的日期,不考虑days
realRollDay = getRollWeekDays(date,days);
//查询数据库,获取这段时间内的放假日期,和补假日期 (放假 - 补假)为需要补充的日期
List<HolidayConfig> holidayConfigList = null;
//得到起始时间---将时分秒不化为
Date startDate = DateUtil.afterDateByDay(date,1);
//结束时间(不含放假的日期和补假日期)---- 这个比较难确定,(可能会涉及到某年之后
Date endDate = DateUtil.afterDateByDay(date, realRollDay);
do {
String startDateStr = TimeUtil.date2Str(startDate,TimeUtil.FORMAT_DATE);
String endDateStr = TimeUtil.date2Str(endDate,TimeUtil.FORMAT_DATE);
holidayConfigList = holidayConfigMapper.selectScopeByString(startDateStr, endDateStr);
if (CollectionUtil.isNotEmpty(holidayConfigList)) {
//对数据进行过滤,如果isweek等于0则加1,否则减1,---- tempCount 等价于工作日
int tempWeekDayCount = 0;
//统计补假日期
tempWeekDayCount = (int) holidayConfigList.stream().filter(v -> v.getIsWeekend()).count() * -1;
tempWeekDayCount += (int) holidayConfigList.stream().filter(v -> !v.getIsWeekend()).count();
//先获得滚动realrollDay后的日期的,tempWeekDayCount 实质是与 days工作日是等量关系
int tempRollDay = getRollWeekDays(DateUtil.afterDateByDay(date,realRollDay),tempWeekDayCount);
//将放假日期加入(用正数表示放假,负数表示补假)
realRollDay += tempRollDay;
//确定下一个时间范围的起始时间和终止时间
startDate = DateUtil.afterDateByDay(endDate,1);
endDate = DateUtil.afterDateByDay(date, realRollDay);
}
} while (CollectionUtil.isNotEmpty(holidayConfigList));
//求解总共需要后移多少天(周末 + 工作日 - 周末补假)
Date afterDate = DateUtil.afterDateByDay(date, realRollDay);
return afterDate;
}
总结
对于明显有规律的,并且数据量比较大的情况,可以考虑通过取余数,或除法等方法进行统计,计算,减少循环次数