一.说在前面
需求:
工作需要获取n个工作日后的日期, 需要排除weekend和holiday, holiday存在数据库中, 存入的形式是一个节日有起始日期和截止日期(以下文中有关于节假日的表截图).
思路:
大致为: 根据指定日期获取它tomorrow的日期, 判断tomorrow是否是周末和节假日, 如果不是则将tomorrow赋给today继续循环, 循环n次, 返回的today即是目标结果.
1.查询数据库中的holiday, 存入list(需要注意的是, holiday记录里startTime和endTime颠倒的脏数据要剔除, startTime在endTime后面的记录显然是脏数据)
2.判断today是否是周末
3.判断today是否是节假日
4.获取tomorrow的日期, 判断是否是weekend和holiday, 如果不是则将tomorrow赋给today继续循环, 循环n次, 返回today
(这里的today是指指定日期. 如:获取今天以后第10个工作日的日期 今天的日期就是指定日期).
工具类如何使用?
使用方法见博文末尾说明.
二.以下为测试代码(测试时日期为2018-08-28):
package dong.test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Calendar;import java.util.Date;import java.util.List;/** * Created by liangyadong on 2018/8/28 0028. */public class HolidayTest { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); public static void main(String[] args) throws ParseException { //查询数据库中holiday,遍历存入list(表中每条记录存放的是假期的起止日期,遍历每条结果,并将其中的每一天都存入holiday的list中),以下为模拟假期 List holidayList = new ArrayList(); holidayList.add("2018-08-29"); holidayList.add("2018-08-30"); holidayList.add("2018-10-01"); holidayList.add("2018-10-02"); holidayList.add("2018-10-03"); holidayList.add("2018-10-04"); holidayList.add("2018-10-05"); holidayList.add("2018-10-06"); holidayList.add("2018-10-07"); //获取计划激活日期 Date scheduleActiveDate = getScheduleActiveDate(holidayList); System.out.println("10个工作日后,即计划激活日期为::" + sdf.format(scheduleActiveDate)); } //获取计划激活日期 public static Date getScheduleActiveDate(Listlist) throws ParseException {// java.sql.Date currentDate = new java.sql.Date(System.currentTimeMillis());//获取当前日期2018-08-26 Date today = new Date();//Mon Aug 27 00:09:29 CST 2018 Date tomorrow = null; int delay = 1; int num = 10;//根据需要设置,这个值就是业务需要的n个工作日 while(delay <= num){ tomorrow = getTomorrow(today); //当前日期+1即tomorrow,判断是否是节假日,同时要判断是否是周末,都不是则将scheduleActiveDate日期+1,直到循环num次即可 if(!isWeekend(sdf.format(tomorrow)) && !isHoliday(sdf.format(tomorrow),list)){ delay++; today = tomorrow; } else if (isWeekend(sdf.format(tomorrow))){// tomorrow = getTomorrow(tomorrow); today = tomorrow; System.out.println(sdf.format(tomorrow) + "::是周末"); } else if (isHoliday(sdf.format(tomorrow),list)){// tomorrow = getTomorrow(tomorrow); today = tomorrow; System.out.println(sdf.format(tomorrow) + "::是节假日"); } } System.out.println("10个工作日后,即计划激活日期为::" + sdf.format(today)); return today; } /** * 获取明天的日期 * * @param date * @return */ public static Date getTomorrow(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, +1); date = calendar.getTime(); return date; } /** * 判断是否是weekend * * @param sdate * @return * @throws ParseException */ public static boolean isWeekend(String sdate) throws ParseException { Date date = sdf.parse(sdate); Calendar cal = Calendar.getInstance(); cal.setTime(date); if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){ return true; } else{ return false; } } /** * 判断是否是holiday * * @param sdate * @param list * @return * @throws ParseException */ public static boolean isHoliday(String sdate, List list) throws ParseException { if(list.size() > 0){ for(int i = 0; i < list.size(); i++){ if(sdate.equals(list.get(i))){ return true; } } } return false; }}
输出main方法的执行结果:
2018-08-29::是节假日2018-08-30::是节假日2018-09-01::是周末2018-09-02::是周末2018-09-08::是周末2018-09-09::是周末10个工作日后,即计划激活日期为::2018-09-1310个工作日后,即计划激活日期为::2018-09-13
查看上面打印结果符合预期, 下面则是应用的说明.
三.应用
1.首先看一下我数据库中存放的holiday, 每一个节日都是一个范围(有开始日期和结束日期)
2.从数据库中查询holiday结果集, 遍历结果集将每一天holiday存到holidayList中:
2.1 serviceImpl:
//查询holiday列表public List getHolidayList(){ //存放holiday的每一天 List holidayList = new ArrayList(); Listlist = customerManageDao.getHolidayList(); //遍历holidayList if(list!=null&&list.size()>0){ for(HolidayInfoEntity holidayInfoEntity : list){ Date startTime = holidayInfoEntity.getStartTime(); Date endTime = holidayInfoEntity.getEndTime(); SimpleDateFormat sdf = PersDateUtils.getSdf(PersDateUtils.FORMAT_DATE_SPLIT); String sstartTime = sdf.format(startTime); String sendTime = sdf.format(endTime); Date tomorrow = HolidayUtils.getTomorrow(startTime); if(!sstartTime.equals(sendTime)){ holidayList.add(sstartTime); while(!sdf.format(tomorrow).equals(sendTime)){ tomorrow = HolidayUtils.getTomorrow(startTime); holidayList.add(sdf.format(tomorrow)); startTime = tomorrow; } }else{ holidayList.add(sstartTime); } } } return holidayList;}
2.2 daoImpl:(在这一步筛选符合逻辑的holiday, 即startTime小于endTime的)
//获取holiday列表@Overridepublic List getHolidayList() { StringBuilder hql = new StringBuilder(" from HolidayInfoEntity h where h.startTime <= h.endTime "); String hqlQuery = hql.toString(); Query query = getSession().createQuery(hqlQuery); Listlist = query.list(); return list;}
2.3 debug查看查询到的节假日:
3.调用HolidayUtils中的getScheduleActiveDate传入正确的参数, 返回值即是排除节假日和周末后的指定n个工作日后的日期.(HolidayUtils如下)
=====================傲娇的分割线: 封装到工具类内方便直接调用=====================
HolidayUtils.java
package com.ppms.utils;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.List;/** * Created by liangyadong on 2018/8/28 0028. */public class HolidayUtils { private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); /** * 获取计划激活日期 * @param today opening date * @param list holidayList * @param num num个工作日后 * @return * @throws ParseException */ public static Date getScheduleActiveDate(Date today, Listlist, int num) throws ParseException { Date tomorrow = null; int delay = 1; while(delay <= num){ tomorrow = getTomorrow(today); //当前日期+1,判断是否是节假日,不是的同时要判断是否是周末,都不是则scheduleActiveDate日期+1 if(!isWeekend(sdf.format(tomorrow)) && !isHoliday(sdf.format(tomorrow),list)){ delay++; today = tomorrow; } else if (isWeekend(sdf.format(tomorrow))){ today = tomorrow; } else if (isHoliday(sdf.format(tomorrow),list)){ today = tomorrow; } } return today; } /** * 获取tomorrow的日期 * * @param date * @return */ public static Date getTomorrow(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, +1); date = calendar.getTime(); return date; } /** * 判断是否是weekend * * @param sdate * @return * @throws ParseException */ public static boolean isWeekend(String sdate) throws ParseException { Date date = sdf.parse(sdate); Calendar cal = Calendar.getInstance(); cal.setTime(date); if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){ return true; } else{ return false; } } /** * 判断是否是holiday * * @param sdate * @param list * @return * @throws ParseException */ public static boolean isHoliday(String sdate, List list) throws ParseException { if(list.size() > 0){ for(int i = 0; i < list.size(); i++){ if(sdate.equals(list.get(i))){ return true; } } } return false; }}
PersDateUtils.java
package com.ppms.utils;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;/** * Created by yadongliang on 2018/7/2 0002. */public class PersDateUtils { public static final String FORMAT_DATE_SPLIT = "yyyy-MM-dd"; public static final String FORMAT_DATE_NONE = "yyyyMMdd"; public static final String FORMAT_DATE_TIME = "yyyy-MM-dd HH:mm:ss:SSS"; public static final String FORMAT_FULL_DATE_TIME = "yyyyMMddHHmmssSSS"; public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; //获取指定格式 public static SimpleDateFormat getSdf(String pattern) { return new SimpleDateFormat(pattern); } //获取系统当前时间 public static Date getDate() { return new Date(); } //获取当前日历 public static Calendar getCalendar() { return Calendar.getInstance(); } //获取指定格式的日期sDate public static String getPatternDate(String pattern, Date date){ return getSdf(pattern).format(date); } //字符串转日期 public static Date str2Date(String str, SimpleDateFormat sdf) { if (null == str || "".equals(str)) { return null; } Date date = null; try { date = sdf.parse(str); return date; } catch (ParseException e) { e.printStackTrace(); } return null; }}
使用说明:
将HolidayUtils.java和PersDateUtils.java拷贝到自己项目中, 调用HolidayUtils中的getScheduleActiveDate()传入正确的参数, 返回值即是目标日期.
Date getScheduleActiveDate(Date today, List<String> list, int num)
参数说明:
Date today: 指定日期 格式 yyyy-MM-dd
List<String> list: 业务内定义的节假日的list 格式 yyyy-MM-dd
int num: 指定天数
例如:
获取今天(2018-08-28)起 10天后的日期, 节假日从数据库中查询并存入到holidayList中, 标红的参数传入方法中即可.
思路基本上这样, 逻辑不是很严谨, 如果bug, 欢迎讨论.