一.写在前面

需求描述

  工作需要获取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)起 天后的日期, 节假日从数据库中查询并存入到holidayList中, 标红的参数传入方法中即可.

思路基本上这样, 逻辑不是很严谨, 如果有bug, 欢迎留言讨论~

java获取n个工作日后的日期, 排除周末和节假日(顺延)的更多相关文章

  1. java获取当前年份、月份和日期字符串等

    Java获取当前年份.月份和日期是通过Calendar类的实例对象来获取的. 首先创建一个Calendar类的实例对象,Calendar类属于java.util包. Calendar calendar ...

  2. N个工作日后的日期

    这里对特殊日期采用了模拟的方式,在实际开发中当然这些数据是从数据库中读取,调用方法时 只需传入开始时间(一般当前) 和N(代表N个工作日) /// <summary> /// 获取时间 / ...

  3. java获取上周任意一天的日期

    /** * 获取上周周几的日期,默认一周从周一开始 * @param dayOfWeek * @param weekOffset * @return */ public static Date get ...

  4. JAVA获取当前年份,月份、日期、小时、分钟、秒等

    import java.util.Calendar; public class Main { public static void main(String[] args) { Calendar cal ...

  5. JAVA获取当前日期指定天数之后的日期

    /** * 获取day天之后的日期 * @param day 天数 * @return */ public static String getDate(int day){ Calendar calen ...

  6. java获取一段字符串里符合日期的正则表达式的字符串

    import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test3 { public static v ...

  7. python 递归计算若干工作日后的日期

    import datetime # 根据第一次计算出来的休息日数,计算还需要的工作日数.(递归调用) def get_next_date(self, start_date, weekend_days) ...

  8. 【原创】java 获取十个工作日之前或之后的日期(算当天)-完美解决-费元星

    [原创]java 获取十个工作日之后的日期(算当天)-完美解决-费元星(仅考虑星期六星期天) /** * * 根据开始日期 ,需要的工作日天数 ,计算工作截止日期,并返回截止日期 * @param s ...

  9. java获取当天,前天,明天,本周,本月,本年的开始日期时间和结束日期时间

    package demoone; import java.sql.Timestamp; import java.text.ParseException; import java.text.Simple ...

随机推荐

  1. 超酷实用的jQuery焦点图赏析及源码

    焦点图应用在现代网页中使用十分广泛,有注重简单小巧的,也有注重华丽美观的,大部分jQuery焦点图都可以滑动和切换图片,并且在切换图片时产生不同的动画特效.今天我们要分享一些超酷而且实用的jQuery ...

  2. Annotation Type EnableTransactionManagement

    http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Ena ...

  3. JAVA-MyBatis ORM

    MyBatis 的前身就是 iBatis .是一个数据持久层(ORM)框架. iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架.iBATIS提供的持久 ...

  4. Linux动态链接库的使用

    1.前言 在实际开发过程中,各个模块之间会涉及到一些通用的功能,比如读写文件,查找.排序.为了减少代码的冗余,提高代码的质量,可以将这些通用的部分提取出来,做出公共的模块库.通过动态链接库可以实现多个 ...

  5. Linux反编译

    转自:http://bbs.pediy.com/showthread.php?threadid=11315 一个简单的linux crackme的逆向前言    最不喜欢的就是写破解教程,酒后一时冲动 ...

  6. IIS 7.5: HOW TO ENABLE TLS 1.1 AND TLS 1.2

    In IIS 7.5, which is installed on Windows 2008 R2 servers, only SSL 3.0 and TLS 1.0 are enabled for ...

  7. pycharm下设置自己的模板

    在File---settings---File and Code Templates---Python script 脚本里添加: #!usr/bin/env python #-*- coding:u ...

  8. ThinkPHP3.0启动过程

    以Blog举例载入项目入口文件    D:\wamp\www\Examples\Blog\index.php        定义常量        APP_NAME,Blog        APP_P ...

  9. @TargetAPI + 版本判断实现高低API版本兼容

    安卓开发中,在低版本SDK使用高版本的API会报错.一般处理方法是换一种实现方法,或者在高版本SDK中使用高版本API,低版本SDK中使用效果可能会差点的折衷方案:后者可以用如下技巧来实现. 步骤 S ...

  10. ArcMap工具箱参数名称的Bug

    已经忍了很久了,今天一定要说一说,强大的 ArcGIS居然还存在这种Bug问题.如下图所示:使用了追加工具,有三个要素图层,且三个数据与目标数据不是同一数据,但它们的名称一致,这样执行,将会出现&qu ...