接到个任务:
获取到n个工作日后的时间,用于设置截止时间。
处理思路:
判断工作日,这种得弄个节假日表。判断时候,读取数据。
1,设置节假日。
2,设置周末补班。
n个工作日,从传的日期开始判断,
1,先判断如果是节假日。不做处理
2,判断是否是周末,再判断要不要补班。
其它都是工作日。工作日不断叠加。
代码:
HolidayUtils
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用于查询间隔n个工作日(包含法定节假日、双休日、调休)后的日期
* 和查询间隔n个工作日(包含法定节假日、双休日、调休)后的实际间隔的天数
*/
public class HolidayUtils {
private static final Logger logger = LoggerFactory.getLogger(HolidayUtils.class);
private static String HOLIDAY = "holiday";
private static String WORK_WEEKEND_DAY = "workWeekendDay";
/**
* 用于判断间隔n个工作日(排除节假日、周六日包含周末补班数据)后的日期
* @param holidays 节假日数据
* @param workWeekendDays 周末补班数据
* @param today 计算开始时间
* @param invervalWorkDay 间隔工作日
* @return
*/
public static Date getIntervalWorkDate(List<String> holidays, List<String> workWeekendDays, Date today, Integer invervalWorkDay) {
String beginDay = DateUtils.formatDate(today);
Date tomorrow;
String tomorrowStr;
int delay = 1;
boolean workDay;
while(delay <= invervalWorkDay){
//获取明天的日期
workDay = true;
tomorrow = DateUtils.addDay(today, NumberUtils.INTEGER_ONE);
tomorrowStr = DateUtils.formatDate(tomorrow);
//当前日期+1即tomorrow, 先判断是否是节假日,再判断是否是周末,是周末再判断是否是补班, 直到循环间隔天数------不是节假日不是周末并且不是周末补班
if (isHoliday(tomorrowStr, holidays)){
workDay = false;
logger.info("holiday {}: 是节假日", tomorrowStr);
} else if(DateUtils.isWeekend(tomorrow)){//是周末,再判断是不是周末补班
if(!isWorkWeekendDay(tomorrowStr, workWeekendDays)){
workDay = false;
logger.info("rest day {}: 是周末休息日", tomorrowStr);
}else {
logger.info("work weekend day {}: 是周末调休补班", tomorrowStr);
}
} else {
logger.info("work day {}: 是正常工作日", tomorrowStr);
}
if(workDay){ // 工作日,日期加1
delay++;
}
today = tomorrow;
}
logger.info("interval date, {} 后{} 个工作日后,日期为:{}",beginDay, invervalWorkDay, DateUtils.formatDate(today));
return today;
}
/**
* 判断是否是节假日
*/
public static boolean isHoliday(String dateStr, List<String> holidays) {
if(!CollectionUtils.isEmpty(holidays)){
for (String holiday : holidays) {
if (dateStr.equals(holiday)) {
return true;
}
}
}
return false;
}
/**
* 判断是否是周末补班
*/
public static boolean isWorkWeekendDay(String dateStr, List<String> workWeekendDays) {
if(!CollectionUtils.isEmpty(workWeekendDays)){
for (String workWeekendDay : workWeekendDays) {
if (dateStr.equals(workWeekendDay)) {
return true;
}
}
}
return false;
}
/**
* 获取工作日后的间隔天数
* @param holidays 节假日数据
* @param workWeekendDays 周末补班数据
* @param date 日期
* @param intervalWorkDay 间隔工作日
* @return 工作日后的间隔天数
*/
public static Long getIntervalWorkDay(List<String> holidays, List<String> workWeekendDays, Date date, Integer intervalWorkDay) {
Date intervalWorkDate = getIntervalWorkDate(holidays, workWeekendDays, date, intervalWorkDay);
return DateUtils.getDiffDays(date, intervalWorkDate);
}
public static void main(String[] args) {
List<HolidayConfigDTO> holidayDatas = new ArrayList<>();
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-09-29"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-02"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-03"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-04"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-05"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-06"), HOLIDAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-07"), WORK_WEEKEND_DAY));
holidayDatas.add(new HolidayConfigDTO(DateUtils.parseDate("2023-10-08"), WORK_WEEKEND_DAY));
// 节假日集合
List<String> holidays = holidayDatas.stream()
.filter(holiday -> HOLIDAY.equals(holiday.getType()))
.map(holiday -> DateUtils.formatDate(holiday.getHoliday())).collect(Collectors.toList());
// 周末补班日集合
List<String> workWeekenDays = holidayDatas.stream()
.filter(workDay -> WORK_WEEKEND_DAY.equals(workDay.getType()))
.map(workDay -> DateUtils.formatDate(workDay.getHoliday())).collect(Collectors.toList());
Date createDate = DateUtils.parseDate("2023-09-27");
Integer intervalWorkDay = 6;
Date intervalWorkDate = HolidayUtils.getIntervalWorkDate(holidays, workWeekenDays, createDate, intervalWorkDay);
System.out.println(DateUtils.formatDate(intervalWorkDate));
Long diffDays = DateUtils.getDiffDays(createDate, intervalWorkDate);
logger.info("intervalWorkDay {}, realIntervalDay {}", intervalWorkDay, diffDays);
}
}
DateUtils
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class DateUtils {
private static String datePattern = "yyyy-MM-dd";
private static String dateHourPattern = "yyyy-MM-dd HH";
private static String dateTimePattern = "yyyy-MM-dd HH:mm:ss";
private static String dateTimePatternSSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
private static String dateTimeSuffixPattern = "yyyyMMddHHmmss";
private static String zeroTime = " 00:00:00";
private static String endTime = " 23:59:59";
public static String format(Date date, String pattern) {
if (date == null)
return "";
return DateFormatUtils.format(date, pattern);
}
public static String format(Date date, String pattern, TimeZone timeZone) {
if (date == null)
return "";
return DateFormatUtils.format(date, pattern, timeZone);
}
public static String formatDate(Date date) {
if (date == null)
return "";
return DateFormatUtils.format(date, datePattern);
}
public static String formatDate(Date date, TimeZone timeZone) {
if (date == null)
return "";
return DateFormatUtils.format(date, datePattern, timeZone);
}
public static String formatDateTime(Date date) {
if (date == null)
return "";
return DateFormatUtils.format(date, dateTimePattern);
}
public static String formatDateTime(Date date, TimeZone timeZone) {
if (date == null)
return "";
return DateFormatUtils.format(date, dateTimePattern, timeZone);
}
public static Date parseDate(String str) {
if (StringUtils.isBlank(str))
return null;
try {
return org.apache.commons.lang3.time.DateUtils.parseDate(str, datePattern);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static Date parseDateTime(String str) {
if (StringUtils.isBlank(str))
return null;
try {
return org.apache.commons.lang3.time.DateUtils.parseDate(str, dateTimePattern);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static Date parseDateTime(String str, String dateTimePattern) {
if (str == null)
return null;
try {
return org.apache.commons.lang3.time.DateUtils.parseDate(str, Locale.CHINESE, dateTimePattern);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
public static Date formatDateTimeZero(Date date) {
String formatDate = formatDate(date);
return parseDateTime(formatDate + zeroTime);
}
public static Date formatDateTimeEnd(Date date) {
String formatDate = formatDate(date);
return parseDateTime(formatDate + endTime);
}
public static Date getCurDateTime() {
Date date = new Date();
String curDate = DateFormatUtils.format(date, dateTimePatternSSSXXX);
return DateUtils.parseDateTime(curDate, dateTimePatternSSSXXX);
}
public static Date getFirstOfHour(Date date) {
String formatDate = format(date, dateHourPattern);
return parseDateTime(formatDate + ":00:00");
}
public static Date getLastOfHour(Date date) {
String formatDate = format(date, dateHourPattern);
return parseDateTime(formatDate + ":59:59");
}
public static Date getFirstOfDay(Date date) {
String formatDate = format(date, datePattern);
return parseDateTime(formatDate + zeroTime);
}
public static Date getLastOfDay(Date date) {
String formatDate = format(date, datePattern);
return parseDateTime(formatDate + endTime);
}
/**
* 获取指定日期所在月的第一天
* @param date 日期
* @return 所在月的第一天
*/
public static Date getFirstOfMonth(Date date) {
//获取当前月第一天:
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
return formatDateTimeZero(calendar.getTime());
}
/**
* 获取指定日期所在月的第最后一天
* @param date 日期
* @return 最后一天
*/
public static Date getLastOfMonth(Date date) {
//获取当前月最后一天
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
return formatDateTimeEnd(calendar.getTime());
}
/**
* 获取当年的第一天
*/
public static Date getCurrentFirstOfYear() {
Calendar currCal = Calendar.getInstance();
int currentYear = currCal.get(Calendar.YEAR);
return getFirstOfYear(currentYear);
}
/**
* 获取当年的最后一天
*/
public static Date getCurrentLastOfYear() {
Calendar currCal = Calendar.getInstance();
int currentYear = currCal.get(Calendar.YEAR);
return getLastOfYear(currentYear);
}
/**
* 获取某年第一天日期
* @param year 年份
* @return Date
*/
public static Date getFirstOfYear(int year) {
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.YEAR, year);
return calendar.getTime();
}
/**
* 获取某年第一天日期
* @param date 日期
* @return Date
*/
public static Date getFirstOfYear(Date date) {
int year = Integer.parseInt(String.format("%tY", date));
return formatDateTimeZero(getFirstOfYear(year));
}
/**
* 获取某年最后一天日期
* @param year 年份
* @return Date
*/
public static Date getLastOfYear(int year) {
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.YEAR, year);
calendar.roll(Calendar.DAY_OF_YEAR, -1);
return calendar.getTime();
}
/**
* 获取某年最后一天日期
* @param date 日期
* @return Date
*/
public static Date getLastOfYear(Date date) {
int year = Integer.parseInt(String.format("%tY", date));
return formatDateTimeEnd(getLastOfYear(year));
}
/**
* 计算两个日期之间的时间差,到秒
* @param start 开始日期
* @param end 结束日期
* @return Long
*/
public static Long getDiffDatesToSec(Date start, Date end) {
long startTime = start.getTime();
long endTime = end.getTime();
return (endTime - startTime) / 1000;
}
public static Date addDay(Date start, Integer day) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(start);
calendar.add(Calendar.DATE, day);
return calendar.getTime();
}
public static Date addMonth(Date start, Integer month) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(start);
calendar.add(Calendar.MONTH, month);
return calendar.getTime();
}
public static Long getRemainMilOneDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Long seconds = (calendar.getTime().getTime() - date.getTime());
return seconds;
}
public static Long getDiffDays(Date start, Date end) {
Long day = (parseDate(formatDate(end)).getTime() - parseDate(formatDate(start)).getTime())
/ (1000 * 60 * 60 * 24);
return day;
}
public static String getCurrentTimeSuffix() {
Date now = new Date();
return format(now, dateTimeSuffixPattern);
}
/**
* 判断是否是周末
*/
public static boolean isWeekend(Date date) {
Calendar cal = Calendar.getInstance();
assert date != null;
cal.setTime(date);
return cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}
public static void main(String args[]) {
String format = getCurrentTimeSuffix();
System.out.println(format);
}
}
HolidayConfigDTO
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
@Data
@ToString
@ApiModel(value = "节假日配置")
@AllArgsConstructor
public class HolidayConfigDTO {
@ApiModelProperty(value = "节假日")
private Date holiday;
@ApiModelProperty(value = "holiday 节假日, workWeekenDay 周末工作日")
private String type;
}
数据库配置
DROP TABLE IF EXISTS `holiday_config`;
CREATE TABLE `holiday_config` (
`holiday` date DEFAULT NULL,
`type` varchar(20) DEFAULT 'holiday'
COMMENT 'holiday:法定节假日;workWeekenDay 调休补班'
) COMMENT='节假日配置表,需要每年根据法定节假日具体时间更新一次';
总结:
判断n个工作日后,设置一个节假日表。每年维护一次,就很方便了。