java獲取n個工作日后的日期, 排除周末和節假日(順延)


一.寫在前面

需求描述

  工作需要獲取n個工作日后的日期, 需要排除weekend和holiday, holiday存在數據庫中, 存入的形式是一個節日有起始日期和截止日期(以下文中有關於節假日的表截圖).

思路解析

  大致為: 根據指定日期獲取它tomorrow的日期, 判斷tomorrow是否是周末和節假日, 如果不是則將tomorrow賦給today繼續循環, 循環n次, 返回的today即是目標結果.

  1.查詢數據庫中的holiday, 存入list(需要注意的是, holiday記錄里startTime和endTime顛倒的臟數據要剔除, startTime在endTime之后的記錄顯然是臟數據)

  2.判斷today是否是周末

  3.判斷today是否是節假日

  4.獲取tomorrow的日期, 判斷是否是weekendholiday, 如果不是則將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, 歡迎留言討論~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM