zoukankan      html  css  js  c++  java
  • 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, 欢迎留言讨论~

  • 相关阅读:
    第四章 sysrepo共享内存机制
    第四章 Sysrepo连接与会话
    NETCONF协议详解
    yang模型中rpc_NETCONF、YANG、ncclient理论和实战(上)
    DELPHI 中关于ACM组件的ACMWaveIn延迟问题解决方法
    下载源码和控件的好地方
    Delphi网络摄像头简单程序
    Delphi取局域网上所有的SQL服务器名称
    TPaintBox的前世今生
    linux alpine 安装慢、apk add慢,更换国内源
  • 原文地址:https://www.cnblogs.com/yadongliang/p/9549349.html
Copyright © 2011-2022 走看看