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 ...
随机推荐
- 在springboot项目中使用mybatis 集成 Sharding-JDBC
前段时间写了篇如何使用Sharding-JDBC进行分库分表的例子,相信能够感受到Sharding-JDBC的强大了,而且使用配置都非常干净.官方支持的功能还包括读写分离.分布式主键.强制路由等.这里 ...
- Ubuntu环境变量解析
在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /e ...
- kaggle预测
两个预测kaggle比赛 一 .https://www.kaggle.com/c/web-traffic-time-series-forecasting/overview Arthur Suilin• ...
- 【Python】使用geopy由经纬度找地理信息
from geopy.geocoders import Nominatim geolocator = Nominatim() location = geolocator.reverse("3 ...
- 使用Genymotion模拟器或者手机运行ionic4程序
1.使用命令行 #添加android, 如果是ios ,设置ioscordova platform add android #编译成apkionic build #开启cordova run andr ...
- asp.net 定时执行任务代码 定时采集数据
using System; using System.Data; using System.Configuration; using System.Collections; using System. ...
- VS2015 之 常用快捷键
调试执行 F5,终止调试执行 Shift+F5 启动执行 Ctrl+F5 查找下一个 F3,查找上一个 Shift+F3 附加到进程 Ctrl+Alt+P,逐过程 F10,逐语句执行 F11 切换断点 ...
- IDEA 之 Error during artifact deployment. See server log for details
IDEA版本:2017.1.1 Tomcat版本:8.5,9.0 问题描述:安装最新版本的IDEA 2017.1.1版本,创建默认的 Web Application(3.1) 项目,配置 Applic ...
- 微信小程序 - 骨架屏
骨架屏 - “与其等待网络加载,不如提前给点暗示” 注:不适用复杂交互效果 演示 示例解释以及使用全在index.wxml中,观看需了解组件使用. 示例下载:微信小程序-骨架屏演示
- C++ 第十课:标准c时间与日期函数
asctime() 时间文本格式 clock() 返回自程序开始运行所经过的时间 ctime() 返回特定格式时间 difftime() 两时刻的间隔 gmtime() 返回指向当前格林威治时间的指针 ...