因为业务需求,要对请假时间进行计算,也就是用户选定一个开始时间,在选定一个结束时间,你要给用户展示一个他请假的时长,这个时长肯定是除开节假日,双休,其中考虑到放假后的调休,中午午休,以及用户提交请假所处的时间段。
翻了翻网上的一些带佬的代码(毕竟码农的精华就在CV嘛),恩,有重合部分,但无法完全满足业务需求,所以还是需要自己动手做部分整合,最关键是部分代码需要调用外部接口,也把整合的代码放出。

第一个工具类:

package com.api.leave.utils;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;/*** 请假计算(小时)* 1.除去 节假日* 2.除去 其他规定的 非工作时间(有具体的  实行者指定)* 3.考虑一点 其他不上班时间 有些公司的特别* @author fengjing**/
public class HolidayDateUtil {/*** 节假日查询接口* 使用方法 url+yyyyMMdd*///时间格式化
public final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public final static SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");/*** 从公认网站上获取 节假日信息* @param url 获取节假日的 公认网站 url="网站地址"+时间 时间格式yyyyMMdd* @param url* @return 工作日对应结果为 0, 休息日对应结果为 1, 节假日对应的结果为 2, 网站失效-1, 数据格式改变-2*/
public static String getHoliday(String date) {ChineseCalendarUtils cc = new ChineseCalendarUtils();try {return cc.checkDate(date);} catch (Exception e) {e.printStackTrace();}return null;
}/*** 判断某年某月有多少天* @param year 年  "yyyy"* @param moun 月 "m"* @return*/
public static int daysMonth(int year,int moun){switch(moun){case 0: return 31;case 1: return ((year%4==0&&year%100!=0)||year%400==0)?29:28;case 2: return 31;case 3: return 30;case 4: return 31;case 5: return 30;case 6: return 31;case 7: return 31;case 8: return 30;case 9: return 31;case 10: return 30;case 11: return 31;default: return 0;}
}
/*** 通过时间秒毫秒数判断两个时间的间隔* @param tiny 开始时间* @param large结束时间* @return 返回几天*/
public static int differentDaysByMillisecond(Date tiny,Date large){if(format1.format(tiny).equals(format1.format(large))){return 0;}Calendar c1 = Calendar.getInstance();Calendar c2 = Calendar.getInstance();c1.setTime(tiny);c2.setTime(large);int result = c2.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);/*Double why = Double.valueOf((large.getTime() - tiny.getTime()))/(1000*3600*24);double d = Math.ceil(why);*/return result;
}/*** 通过时间秒毫秒数判断两个时间的间隔* @param tiny 开始时间* @param large结束时间* @return 返回几小时*/
public static double differentHoursByMillisecond(Date tiny,Date large){double hours = ((double) ((large.getTime() - tiny.getTime())) / (1000*3600));return hours;
}/*** 时间格式yyyy-MM-dd HH:mm:ss* @param start 请假开始时间 yyyy-MM-dd HH:mm:ss* @param end 请假结束时间 yyyy-MM-dd HH:mm:ss* @param startM 上班早晨开始时间 HH:mm:ss* @param endE   上班早晨结束时间 HH:mm:ss* @param startAf 上班下午开始时间 HH:mm:ss* @param endAf      上班下午结束时间 HH:mm:ss* @return*/
public double calculateTimeHour(String start,String end,String startM,String endE,String startAf,String endAf){if(start!=null&&end!=null&&startM!=null&&endE!=null&&startAf!=null&&endAf!=null){//确保时间格式正确和值存在try {Date dataStart = HolidayDateUtil.format.parse(start);Date dataEnd = HolidayDateUtil.format.parse(end);double hours = 0;int monthDays = -1;int yearTime = dataStart.getYear()+1900;int mounthTime = dataStart.getMonth();int dataTime = dataStart.getDate();double lunchBreak;int interval = HolidayDateUtil.differentDaysByMillisecond(dataStart,dataEnd);//判断这年这月有多少天monthDays = HolidayDateUtil.daysMonth(yearTime,mounthTime);//第一天请假开始时间String startday = start.substring(start.lastIndexOf(" ")+1,start.length()-1);//最后一天请假结束时间String endday = end.substring(end.lastIndexOf(" ")+1,end.length()-1);double totalDay = 0;//累积总共请假多少天for(int i=0;i<=interval;i++){if(interval==0){//间隔0天 也就是 请假在一天之内if(!"0".equals(HolidayDateUtil.getHoliday(yearTime+"-"+(((mounthTime+1))>=10?(mounthTime+1):"0"+(mounthTime+1))+"-"+(dataTime>10?dataTime:"0"+dataTime)))){System.out.println(""+yearTime+(((mounthTime+1))>10?(mounthTime+1):"0"+(mounthTime+1))+(dataTime>10?dataTime:"0"+dataTime)+"非工作日期不需要计算");return 0;}String s = start.substring(0,10)+" "+endE;String s1 = start.substring(0,10)+" "+startAf;String s2 = start.substring(0,10)+" "+startM;String s3 = start.substring(0,10)+" "+endAf;Date dataMorning = HolidayDateUtil.format.parse(s2);Date dataAfternoon = HolidayDateUtil.format.parse(s3);Date dataCenter1 = HolidayDateUtil.format.parse(s);Date dataCenter2 = HolidayDateUtil.format.parse(s1);//开始时间在9点前 结束时间:①9点前 ②9点到12点 ③12点到1点 ④1点到6点 ⑤6点后if(dataStart.compareTo(dataMorning) <= 0){if(dataEnd.compareTo(dataMorning) <= 0){hours = 0;lunchBreak = 0;}else if(dataEnd.compareTo(dataMorning) > 0 && dataEnd.compareTo(dataCenter1) <= 0){hours = differentHoursByMillisecond(dataMorning,dataEnd);lunchBreak = 0;}else if(dataEnd.compareTo(dataCenter1) > 0 && dataEnd.compareTo(dataCenter2) <= 0){hours = differentHoursByMillisecond(dataMorning,dataCenter1);lunchBreak = 0;}else if(dataEnd.compareTo(dataCenter2) > 0 && dataEnd.compareTo(dataAfternoon) <= 0){hours = differentHoursByMillisecond(dataMorning,dataEnd);lunchBreak = 1;}else{hours = 8;lunchBreak = 0;}}//开始时间在9点到12点 结束时间:②9点到12点 ③12点到1点 ④1点到6点 ⑤6点后else if(dataStart.compareTo(dataMorning) > 0 && dataStart.compareTo(dataCenter1) <= 0){if(dataEnd.compareTo(dataMorning) > 0 && dataEnd.compareTo(dataCenter1) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 0;}else if(dataEnd.compareTo(dataCenter1) > 0 && dataEnd.compareTo(dataCenter2) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = differentHoursByMillisecond(dataCenter1,dataEnd);}else if(dataEnd.compareTo(dataCenter2) > 0 && dataEnd.compareTo(dataAfternoon) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 1;}else{hours = differentHoursByMillisecond(dataStart,dataAfternoon);lunchBreak = 1;}}//开始时间在12点到1点 结束时间:③12点到1点 ④1点到6点 ⑤6点后else if(dataStart.compareTo(dataCenter1) > 0 && (dataStart.compareTo(dataCenter2)) <= 0){if(dataEnd.compareTo(dataCenter1) > 0 && dataEnd.compareTo(dataCenter2) <= 0){hours = 0;lunchBreak = 0;}else if(dataEnd.compareTo(dataCenter2) > 0 && dataEnd.compareTo(dataAfternoon) <= 0){hours = differentHoursByMillisecond(dataCenter2,dataEnd);lunchBreak = 0;}else{hours = differentHoursByMillisecond(dataStart,dataAfternoon);lunchBreak = differentHoursByMillisecond(dataStart,dataCenter2);}}//开始时间在1点到6点 结束时间: ④1点到6点 ⑤6点后else if(dataStart.compareTo(dataCenter2) >0 && dataStart.compareTo(dataAfternoon) <= 0){if(dataEnd.compareTo(dataCenter2) > 0 && dataEnd.compareTo(dataAfternoon) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 0;}else{hours = differentHoursByMillisecond(dataStart,dataAfternoon);lunchBreak = 0;}}//开始时间在6点后else{hours = 0;lunchBreak = 0;}}else{//间隔超过一天dataTime +=(i==0?0:1);if(dataTime>monthDays){mounthTime ++;dataTime=1;if(mounthTime>11){yearTime++;mounthTime=0;dataTime=1;}monthDays = HolidayDateUtil.daysMonth(yearTime,mounthTime);}//判断是否是节假日if(!"0".equals(HolidayDateUtil.getHoliday(yearTime+"-"+(((mounthTime+1))>=10?(mounthTime+1):"0"+(mounthTime+1))+"-"+(dataTime>10?dataTime:"0"+dataTime)))){System.out.println(""+yearTime+(((mounthTime+1))>10?(mounthTime+1):"0"+(mounthTime+1))+(dataTime>10?dataTime:"0"+dataTime)+"非工作日期不需要计算");continue;}String s1 = yearTime+"-"+(((mounthTime+1))>=10?(mounthTime+1):"0"+(mounthTime+1))+"-"+(dataTime>=10?dataTime:"0"+dataTime)+" "+(i==0?startday:startM);String s2 = yearTime+"-"+(((mounthTime+1))>=10?(mounthTime+1):"0"+(mounthTime+1))+"-"+(dataTime>=10?dataTime:"0"+dataTime)+" "+(i==interval?endday:endAf);Date dateMorning = HolidayDateUtil.format.parse(s1.substring(0,10)+" "+startM);Date dateAfternoon = HolidayDateUtil.format.parse(s1.substring(0,10)+" "+endAf);Date dateCenter1 = HolidayDateUtil.format.parse(s1.substring(0,10)+" "+endE);Date dateCenter2 = HolidayDateUtil.format.parse(s1.substring(0,10)+" "+startAf);dataStart = HolidayDateUtil.format.parse(s1);dataEnd = HolidayDateUtil.format.parse(s2);//第一天 dataEnd为6点 判断开始时间 ①9点前 ②9点到12点 ③12点到1点 ④ 1点到6点 ⑤ 6点之后if(i == 0){if(dataStart.compareTo(dateMorning) <= 0){hours = 8;lunchBreak = 0;}else if(dataStart .compareTo(dateMorning) > 0 && dataStart.compareTo(dateCenter1) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 1;}else if(dataStart.compareTo(dateCenter1) > 0 && dataStart.compareTo(dateCenter2) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = differentHoursByMillisecond(dateCenter1,dataStart);}else if(dataStart.compareTo(dateCenter2) > 0 && dataStart.compareTo(dateAfternoon) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 0;}else{hours = 0;lunchBreak = 0;}//中间天 hours 为8 lunchBreak为0}else if( i != 0 && i != interval){hours = 8;lunchBreak = 0;//最后一天 dataStart为9点 判断结束时间 ①9点前 ②9点到12点 ③12点到1点 ④ 1点到6点 ⑤ 6点之后}else{if(dataEnd.compareTo(dateMorning) <= 0){hours = 0;lunchBreak = 0;}else if(dataEnd .compareTo(dateMorning) > 0 && dataEnd.compareTo(dateCenter1) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 0;}else if(dataEnd.compareTo(dateCenter1) > 0 && dataEnd.compareTo(dateCenter2) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = differentHoursByMillisecond(dateCenter1,dataEnd);}else if(dataEnd.compareTo(dateCenter2) > 0 && dataEnd.compareTo(dateAfternoon) <= 0){hours = differentHoursByMillisecond(dataStart,dataEnd);lunchBreak = 1;}else{hours = 8;lunchBreak = 0;}}}System.out.println(yearTime+"-"+(((mounthTime+1))>10?(mounthTime+1):"0"+(mounthTime+1))+"-"+(dataTime>10?dataTime:"0"+dataTime)+" 请假:"+(hours-lunchBreak)+"小时");totalDay+=hours-lunchBreak;}System.out.println(totalDay);return totalDay;} catch (ParseException e) {e.printStackTrace();}}return -1;
}/*** 累积请假共多少天* @param totalDay* @return totalDay < 24小时按小时算   totalDay >= 24小时按天算*/
public String totalDay(double totalDay){if(totalDay > 24){return (totalDay/24) + "天";}else{return totalDay + "小时";}
}public static void main(String args[]) throws IOException{HolidayDateUtil qj= new HolidayDateUtil();//测试qj.calculateTimeHour("2019-9-01 09:00:00","2019-10-09 12:00:00","09:00:00","12:00:00","13:00:00","18:00:00");
}
}

第二个工具类:

package com.api.leave.utils;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;/*** @author  qyw* @description  日期日历工具类* @date Created in 21:01 2019/1/31**/
public class ChineseCalendarUtils {// 法律规定的放假日期private List<String> lawHolidays   = Arrays.asList("2019-9-13", "2019-9-14","2019-09-15", "2019-10-01", "2019-10-02", "2019-10-03", "2019-10-04","2019-10-05", "2019-10-06", "2019-10-07");// 由于放假需要额外工作的周末private List<String> extraWorkdays = Arrays.asList("2019-09-16", "2019-09-29", "2019-10-12", "2019-10-08");/*** @author  qyw* @description  判断是否是法定假日* @date Created in 21:03 2019/1/31**/public boolean isLawHoliday(String calendar) throws Exception {ChineseCalendarUtils.isValidDate(calendar);if (lawHolidays.contains(calendar)) {return true;}return false;}/*** @author  qyw* @description  判断是否是周末* @date Created in 21:03 2019/1/31**/public boolean isWeekends(String calendar) throws Exception {ChineseCalendarUtils.isValidDate(calendar);// 先将字符串类型的日期转换为Calendar类型SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd");Date             date = sdf.parse(calendar);Calendar         ca   = Calendar.getInstance();ca.setTime(date);if (ca.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY|| ca.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {return true;}return false;}/*** @author  qyw* @description  判断是否是需要额外补班的周末* @date Created in 21:06 2019/1/31**/public boolean isExtraWorkday(String calendar) throws Exception {ChineseCalendarUtils.isValidDate(calendar);if (extraWorkdays.contains(calendar)) {return true;}return false;}/*** @author  qyw* @description  判断是否是休息日(包含法定节假日和不需要补班的周末)* @date Created in 21:06 2019/1/31**/public boolean isHoliday(String calendar) throws Exception {ChineseCalendarUtils.isValidDate(calendar);// 首先法定节假日必定是休息日if (this.isLawHoliday(calendar)) {return true;}// 排除法定节假日外的非周末必定是工作日if (!this.isWeekends(calendar)) {return false;}// 所有周末中只有非补班的才是休息日if (this.isExtraWorkday(calendar)) {return false;}return true;}/*** @author  qyw* @description  校验字符串是否为指定的日期格式,含逻辑严格校验,2007/02/30返回false* @date Created in 21:06 2019/1/31**/private static boolean isValidDate(String str) {boolean convertSuccess = true;// 指定日期格式为四位年/两位月份/两位日期,注意yyyy-MM-dd区分大小写;SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");try {// 设置lenient为false.// 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01format.setLenient(false);format.parse(str);} catch (ParseException e) {convertSuccess = false;}return convertSuccess;}public String checkDate(String date) throws Exception {if(isHoliday(date)){return "-1";}else{return "0";}
}
}

两个工具类配合使用就行,篇幅较长,建议CV到idea上阅读,支持2019全年度请假时间计算,如需支持其他年份,需要再行录入部分数据。

请假时间计算(支持任何时间段)相关推荐

  1. 请假时间计算----开始时间不是17点之后算一天,排除周日和节假日

    public String calLeaveDays(Date startTime, Date endTime, Integer vacateType) {// Integer vacateType; ...

  2. java后台 计算请假时间(判断了周六周末和法定节假日和国家调休)

    目录 1.假设上班时间如下: 2.请假时间计算方式: 3.请假可能存在的情况: 4.实现思路: 5.代码奉上,只需传入时间参数 1.假设上班时间如下: 上班时间为:08:30:00 中午休息时间为:1 ...

  3. 关于请假申请的时间计算

    最近在优化一个办公系统,需要计算请假时间 首先要实现请假时间的计算,需要以下几步 第一步.首先我们要知道时间表(我们以最常用的 上午上班时间(09:00 - 12:00)下午(13:00 - 18:0 ...

  4. js中计算一个时间点加上一个时间段后的时间

    在实际的项目中,我们常常有这样的需求,计算某个时间点加上某个时间段后(几天几小时几分钟)的时间.如: 2016-04-05 09:29:15 要加上2天4小时5分钟后的时间: 即:2016-04-07 ...

  5. java 算出下一个工作日_Java 计算一段时间段内除去周六日、节假日的工作日数———超详细(全)...

    Java 计算一段时间段内除去周六日.节假日的工作日数'' 实现功能提要: 本文章记录的是某段时间的起止时间段内的工作日,既是除去周六周日以及节假日日期的工作日数: 注释比较多,因为怕自己忘记,写的可 ...

  6. Java 计算一段时间段内除去周六日、节假日的工作日数———超详细(全)

    Java 计算一段时间段内除去周六日.节假日的工作日数'' 1.前端界面简介 2.后台处理代码 3.注: <END> 实现功能提要: 本文章记录的是某段时间的起止时间段内的工作日,既是除去 ...

  7. Moment.js js 时间计算

    Moment.js中文文档系列之八时间段(Durations) 创建时间段:duration() 人性化:humanize() 毫秒:milliseconds() 秒:seconds() 分:minu ...

  8. 判断请假时间去除周末及节假日

    公司业务需求,在请假时自动跳过周六周日以及节假日.通过statisticsOfLeaveTime方法,传入请假开始的时间以及请假结束的时间,则可自动统计调休时间. 代码整体逻辑就为拿到请假开始和结束时 ...

  9. python-opencv时间计算,视频物体追踪标记

    程序运行的时间计算 **# -*- coding: utf-8 -*- """ @author: Andrew """ import cv2 ...

  10. sql两个时间计算时间差_Java 8时间类,越用越香

    为什么会在Jdk8中加入很多时间类 非线程安全 java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一. Date date = new Date(); ...

最新文章

  1. recv java_用于TCP套接字编程的Recv函数
  2. 干货回顾丨深度学习性能提升的诀窍
  3. 文件流习题8.3 8.4
  4. go-zero:微服务框架
  5. 当当网首页——CSS代码
  6. java学习(67):匿名内部类
  7. Spring操作Redis
  8. Magento教程 17:Magento功能导览(1) 会员功能
  9. 外媒:三星电子预计三季度营收创新高是得益于半导体业务
  10. java 服务注册中心_服务治理的含义和java最流行的微服务框架服务治理注册中心的搭建...
  11. python3x程序设计基础周元哲_Python 3 x程序设计基础
  12. 蓝厂为什么着急推出vivo X23?只因vivo NEX叫好不叫座
  13. 【笔记 】weex POST请求 body数据服务器获取不到
  14. 如何写软件设计文档[转]
  15. JAVA基础——关键字与保留字——标识符——进制转换
  16. 基因组+转录组助力油菜种子油含量自然变异的遗传研究
  17. 原腾讯QQ空间负责人,T13专家,黄希彤被爆近期被裁员,裁员原因令人唏嘘。。...
  18. Qt5 源代码自动跳转
  19. 深入剖析Spring(一)——IoC的基本概念(从面向对象角度介绍)
  20. vue-有初始化动画的节点进度条的实现

热门文章

  1. 免费不限速不限存储的网盘推荐
  2. ImageNet中1000类目标的编号所对应的具体类别
  3. KMP算法的应用——碱基序列匹配
  4. 输入100以内含7或7倍数的数
  5. script什么意思中文翻译成,script中文是什么意思
  6. Java将字符串中的中文数字转化成阿拉伯数字或阿拉伯数字转化成中文数字
  7. 具有定时功能的八路数显抢答器的设计
  8. wps图表横纵坐标怎么设置_用WPS的excel插入图表怎样快速设置横纵坐标轴
  9. 不错的json在线编辑器
  10. 手把手教你用Python分析微信聊天内容