思路:根据国家发布的节假日以及调休时间存入数据库表中。判断一个日期是否为节假日先通过数据库表中查询判断,如果数据库表中不能进行判断,那就判断时间是否为星期六或者星期日来判断。
可判断一个时间是否为节假日,统计两个时间区间有多少个工作日,xx个工作日后的日期为
缺陷:因为节假日调休安排,每年国家会发布一次,所以数据库表的记录需要每年新增一次,不然会导致判断是否为节假日不准确。
1、建表
-- ---------------------------- -- Table structure for holiday_time -- ---------------------------- DROP TABLE IF EXISTS `holiday_time`; CREATE TABLE `holiday_time` ( `id` int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\', `year` int(10) DEFAULT NULL COMMENT \'年\', `month` int(2) DEFAULT NULL COMMENT \'月\', `start_time` datetime DEFAULT NULL COMMENT \'开始时间\', `end_time` datetime DEFAULT NULL COMMENT \'结束时间\', `type` int(1) DEFAULT NULL COMMENT \'类型:1、工作日,2节假日\', `content` varchar(255) DEFAULT NULL COMMENT \'备注\', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT=\'假日时间表\'; -- ---------------------------- -- Records of holiday_time -- ---------------------------- INSERT INTO `holiday_time` VALUES (\'1\', \'2018\', \'12\', \'2018-12-29 00:00:00\', \'2018-12-29 23:59:59\', \'1\', \'调休\'); INSERT INTO `holiday_time` VALUES (\'2\', \'2018\', \'12\', \'2018-12-30 00:00:00\', \'2018-12-31 23:59:59\', \'2\', \'元旦\'); INSERT INTO `holiday_time` VALUES (\'3\', \'2019\', \'1\', \'2019-01-01 00:00:00\', \'2019-01-01 23:59:59\', \'2\', \'元旦\'); INSERT INTO `holiday_time` VALUES (\'4\', \'2019\', \'2\', \'2019-02-02 00:00:00\', \'2019-02-03 23:59:59\', \'1\', \'调休\'); INSERT INTO `holiday_time` VALUES (\'5\', \'2019\', \'2\', \'2019-02-04 00:00:00\', \'2019-02-10 23:59:59\', \'2\', \'春节\'); INSERT INTO `holiday_time` VALUES (\'6\', \'2019\', \'4\', \'2019-04-05 00:00:00\', \'2019-04-07 23:59:59\', \'2\', \'清明节\'); INSERT INTO `holiday_time` VALUES (\'7\', \'2019\', \'4\', \'2019-04-28 00:00:00\', \'2019-04-28 23:59:59\', \'1\', \'调休\'); INSERT INTO `holiday_time` VALUES (\'8\', \'2019\', \'5\', \'2019-05-01 00:00:00\', \'2019-05-04 23:59:59\', \'2\', \'劳动节\'); INSERT INTO `holiday_time` VALUES (\'9\', \'2019\', \'5\', \'2019-05-05 00:00:00\', \'2019-05-05 23:59:59\', \'1\', \'调休\'); INSERT INTO `holiday_time` VALUES (\'10\', \'2019\', \'6\', \'2019-06-07 00:00:00\', \'2019-06-09 23:59:59\', \'2\', \'端午节\'); INSERT INTO `holiday_time` VALUES (\'11\', \'2019\', \'9\', \'2019-09-13 00:00:00\', \'2019-09-15 23:59:59\', \'2\', \'中秋节\'); INSERT INTO `holiday_time` VALUES (\'12\', \'2019\', \'9\', \'2019-09-29 00:00:00\', \'2019-09-29 23:59:59\', \'1\', \'调休\'); INSERT INTO `holiday_time` VALUES (\'13\', \'2019\', \'10\', \'2019-10-01 00:00:00\', \'2019-10-07 23:59:59\', \'2\', \'国庆节\'); INSERT INTO `holiday_time` VALUES (\'14\', \'2019\', \'10\', \'2019-10-12 00:00:00\', \'2019-10-12 23:59:59\', \'1\', \'调休\');
2、构建实体类 HolidayTime
import javax.persistence.*; import java.util.Date; import static javax.persistence.GenerationType.IDENTITY; /** * 假日时间表 * */ @Entity @Table(name = "holiday_time") public class HolidayTime { /** * id */ @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "id", unique = true, nullable = false) private Integer id; /** * 年 */ private Integer year; /** * 月 */ private Integer month; /** * 开始时间 */ @Column(name = "start_time") private Date startTime; /** * 结束时间 */ @Column(name = "end_time") private Date endTime; /** * 类型:1、工作日,2节假日 */ private Integer type; /** * 备注 */ private String content; /** * 获取id * * @return id - id */ public Integer getId() { return id; } /** * 设置id * * @param id id */ public void setId(Integer id) { this.id = id; } /** * 获取年 * * @return year - 年 */ public Integer getYear() { return year; } /** * 设置年 * * @param year 年 */ public void setYear(Integer year) { this.year = year; } /** * 获取月 * * @return month - 月 */ public Integer getMonth() { return month; } /** * 设置月 * * @param month 月 */ public void setMonth(Integer month) { this.month = month; } /** * 获取开始时间 * * @return start_time - 开始时间 */ public Date getStartTime() { return startTime; } /** * 设置开始时间 * * @param startTime 开始时间 */ public void setStartTime(Date startTime) { this.startTime = startTime; } /** * 获取结束时间 * * @return end_time - 结束时间 */ public Date getEndTime() { return endTime; } /** * 设置结束时间 * * @param endTime 结束时间 */ public void setEndTime(Date endTime) { this.endTime = endTime; } /** * 获取类型:1、工作日,2节假日 * * @return type - 类型:1、工作日,2节假日 */ public Integer getType() { return type; } /** * 设置类型:1、工作日,2节假日 * * @param type 类型:1、工作日,2节假日 */ public void setType(Integer type) { this.type = type; } /** * 获取备注 * * @return content - 备注 */ public String getContent() { return content; } /** * 设置备注 * * @param content 备注 */ public void setContent(String content) { this.content = content == null ? null : content.trim(); } }
3、工具方法实现 HolidayModule
import com.yscredit.loan.base.entity.common.HolidayTime; import com.yscredit.loan.base.repository.common.HolidayTimeRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; @Component public class HolidayModule { private final Logger logger = LoggerFactory.getLogger(getClass()); private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); @Autowired private HolidayTimeRepository holidayTimeRepository; /** * 统计两个时间区间有多少个工作日 * 注意:startTime必须小于endTime */ public Integer countWorkDay(Date startTime,Date endTime){ Integer num=0; while (!isSameDay(startTime,endTime)){ boolean holiday=isHoliday(startTime); if(holiday){ }else { num=num+1; } startTime=getTomorrow(startTime); } return num; } /** * xx个工作日后的日期为 */ public Date workDaysByNumber(String date,Integer number){ Date dateTime=strParseDate(date); return workDaysByNumber(dateTime,number); } /** * xx个工作日后的日期为 */ public Date workDaysByNumber(Date date,Integer number){ int num=0; while (num!=number){ date=getTomorrow(date); boolean holiday=isHoliday(date); if(holiday){ }else { //工作日 num++; } } return dayEnd(date); } public boolean isHoliday(String date) { Date dateTime= strParseDate(date); return isHoliday(dateTime); } /** * 判断是否是holiday:true-放假,false-工作日 * 先根据表里面的数据判断是否为节假日, * 如果表里面不能判断,再根据是否为星期六星期天判断 */ public boolean isHoliday(Date date) { Calendar calendar = Calendar.getInstance();//日历对象 calendar.setTime(date);//设置当前日期 Integer year=calendar.get(Calendar.YEAR); Integer month=calendar.get(Calendar.MONTH); //根据数据库表判断是否为节假日 // select t from HolidayTime t where t.year=?1 and t.month>=?2 order by t.month List<HolidayTime> holidayTimeList=holidayTimeRepository.findYearList(year,month); Boolean holiday=dataBaseJudge(holidayTimeList, date); if(holiday!=null)return holiday; //如果根据数据库表不能判断节假日,那如果是星期六、星期天就是节假日,否则就不是 if(calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){ return true; } else{ return false; } } //通过假日时间表记录判断是否为工作日或者节假日 private Boolean dataBaseJudge(List<HolidayTime> holidayTimeList,Date date){ if(holidayTimeList==null || holidayTimeList.isEmpty())return null; for(HolidayTime holidayTime:holidayTimeList){ Date startTime=holidayTime.getStartTime(); Date entTime=holidayTime.getEndTime(); while (startTime.before(entTime)){ //匹配日期是否为数据库存放的日期区间 if(isSameDay(startTime,date)){ Integer type=holidayTime.getType(); if(type==1){ //类型为1表示工作日,一般为调休的 return false; }else { //类型为2表示放假时间 return true; } } startTime=getTomorrow(startTime); } } return null; } /** * 获取明天的日期 */ private static Date getTomorrow(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, +1); date = calendar.getTime(); return date; } /** * 判断两个日期是否为同一天 */ private boolean isSameDay(Date day1, Date day2) { String ds1 = sdf.format(day1); String ds2 = sdf.format(day2); if (ds1.equals(ds2)) { return true; } else { return false; } } private Date strParseDate(String date){ try { return sdf.parse(date); } catch (ParseException e) { logger.info("---->>>>日期转换异常"); e.printStackTrace(); return null; } } //当天的结束时间 23:59:59 public static Date dayEnd(Date date) { Calendar cal = Calendar.getInstance(); if (date != null) cal.setTime(date); cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } }