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的日期, 判断是否是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个工作日后的日期, 排除周末和节假日(顺延)的更多相关文章
- java获取当前年份、月份和日期字符串等
Java获取当前年份.月份和日期是通过Calendar类的实例对象来获取的. 首先创建一个Calendar类的实例对象,Calendar类属于java.util包. Calendar calendar ...
- N个工作日后的日期
这里对特殊日期采用了模拟的方式,在实际开发中当然这些数据是从数据库中读取,调用方法时 只需传入开始时间(一般当前) 和N(代表N个工作日) /// <summary> /// 获取时间 / ...
- java获取上周任意一天的日期
/** * 获取上周周几的日期,默认一周从周一开始 * @param dayOfWeek * @param weekOffset * @return */ public static Date get ...
- JAVA获取当前年份,月份、日期、小时、分钟、秒等
import java.util.Calendar; public class Main { public static void main(String[] args) { Calendar cal ...
- JAVA获取当前日期指定天数之后的日期
/** * 获取day天之后的日期 * @param day 天数 * @return */ public static String getDate(int day){ Calendar calen ...
- java获取一段字符串里符合日期的正则表达式的字符串
import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test3 { public static v ...
- python 递归计算若干工作日后的日期
import datetime # 根据第一次计算出来的休息日数,计算还需要的工作日数.(递归调用) def get_next_date(self, start_date, weekend_days) ...
- 【原创】java 获取十个工作日之前或之后的日期(算当天)-完美解决-费元星
[原创]java 获取十个工作日之后的日期(算当天)-完美解决-费元星(仅考虑星期六星期天) /** * * 根据开始日期 ,需要的工作日天数 ,计算工作截止日期,并返回截止日期 * @param s ...
- java获取当天,前天,明天,本周,本月,本年的开始日期时间和结束日期时间
package demoone; import java.sql.Timestamp; import java.text.ParseException; import java.text.Simple ...
随机推荐
- 自定义View 可清除内容、设置图标、下划线的输入框 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- java 利用HttpURLConnection方式获取restful格式的服务数据
/** * @Author: * @Description:利用HttpURLConnection方式获取restful格式的服务数据 * @Date: */ private static List& ...
- mke2fs 制作ext2文件系统image
方法1: 利用/dev/ram1: linux下有很多ram,我们用ram1,首先把ram1格式化成ext2文件系统[root@gucuiwen babylinux]# sudo mkfs.ext ...
- artTemplate 简洁语法版
引用简洁语法的引擎版本,例如: <script src="dist/template.js"></script> 下载 表达式 {{ 与 }} 符号包裹起来 ...
- iOS中文API之UITouch详解
UITouch 对象用于位置. 大小. 运动和一根手指在屏幕上为某一特定事件的力度.触摸的力度是从开始在 iOS 9 支持 3D 的触摸的设备上可用.你可以通过UIEvent对象传递给响应者对象访问. ...
- Python requests如何将第一个请求得到的 cookie 通过 POST 提交给第二个请求
#coding=utf-8 import requests import json url_login, url_test = "http://192.168.0.162/login&quo ...
- C++ 函数适配器
1.考虑下面的需求,在一个int的vector中,找出一个比5的元素,容易想到的解决办法,定义一个方法对象,使用模板,如下:vector<int>::iterator iter = fin ...
- phpstudy 开启apache反向代理
vhosts.conf 1 2 3 4 5 6 7 8 9 10 11 <VirtualHost *:8080> ServerAdmin webmaster@dummy-host.exam ...
- thinkphp3错误:syntax error, unexpected 'list' (T_LIST), expecting identifier (T_STRING)
syntax error, unexpected 'list' (T_LIST), expecting identifier (T_STRING) 出现这个错误的原因是,list是php的一个函数,系 ...
- JavaScript String 对象常用方法
<script type="text/javascript"> //concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串. var str = &q ...