一.寫在前面
需求描述
工作需要獲取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(List<String> list) 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<String> 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-13 10個工作日后,即計划激活日期為::2018-09-13
查看上面打印結果符合預期, 下面則是應用的說明.
三.應用
1.首先看一下我數據庫中存放的holiday, 每一個節日都是一個范圍(有開始日期和結束日期)
2.從數據庫中查詢holiday結果集, 遍歷結果集將每一天holiday存到holidayList中
2.1 serviceImpl:
//查詢holiday列表 public List getHolidayList(){ //存放holiday的每一天 List holidayList = new ArrayList(); List<HolidayInfoEntity> list = 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列表 @Override public List getHolidayList() { StringBuilder hql = new StringBuilder(" from HolidayInfoEntity h where h.startTime <= h.endTime "); String hqlQuery = hql.toString(); Query query = getSession().createQuery(hqlQuery); List<HolidayInfoEntity> list = 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, List<String> list, 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<String> 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, 歡迎留言討論~