计算两个日期之间的工作日(去掉周末和节假日)

  1 package com.utouu.uphone.commons;
  2
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.ArrayList;
  6 import java.util.Calendar;
  7 import java.util.Date;
  8 import java.util.Iterator;
  9 import java.util.List;
 10
 11 import org.springframework.stereotype.Component;
 12 /**
 13  * 获取工作日
 14  * <br>创建日期:2016年7月21日
 15  * <br><b>Copyright 2016 UTOUU All Rights Reserved</b>
 16  * @author zhushuangshuang
 17  * @since 1.0
 18  * @version 1.0
 19  */
 20 @Component
 21 public class GetWorkDay {
 22     /**
 23     * 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉)
 24     *
 25     * @param start
 26     * -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型
 27     * @param end
 28     * -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型
 29     * @return Long型时间差对象
 30     */
 31     /*public static void main(String[] args) {
 32         GetWorkDay g=new GetWorkDay();
 33         List<Date> initHoliday;
 34         try {
 35             initHoliday = g.initHoliday();
 36             double days = g.getWorkdayTimeInMillisExcWeekendHolidays("2016-06-30 17-12-53","2016-08-30 11-27-50","yyyy-MM-dd HH-mm-ss",initHoliday);
 37             double formateToDay = g.formateToDay(days);
 38             String formatDuring = g.formatDuring(days);
 39              System.out.println(formateToDay);
 40             System.out.println(formatDuring);
 41         } catch (ParseException e) {
 42             // TODO Auto-generated catch block
 43             e.printStackTrace();
 44         }
 45     } */
 46
 47     private double getWorkdayTimeInMillis(long start, long end,
 48         List<Date> listHolidays) {
 49
 50         // 如果起始时间大于结束时间,将二者交换
 51         if (start > end) {
 52             long temp = start;
 53             start = end;
 54             end = temp;
 55         }
 56         // 根据参数获取起始时间与结束时间的日历类型对象
 57         Calendar sdate = Calendar.getInstance();
 58         Calendar edate = Calendar.getInstance();
 59
 60         sdate.setTimeInMillis(start);
 61         edate.setTimeInMillis(end);
 62
 63         // 计算指定时间段内法定节假日天数的毫秒数
 64         long holidays = 0;
 65         if (listHolidays != null) {
 66             holidays = getHolidaysInMillis(start, end, listHolidays);
 67             listHolidays.clear();
 68         }
 69
 70         // 如果两个时间在同一周并且都不是周末日期,则直接返回时间差,增加执行效率
 71         if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR))
 72         && (sdate.get(Calendar.WEEK_OF_YEAR) == edate
 73         .get(Calendar.WEEK_OF_YEAR))
 74         && (sdate.get(Calendar.DAY_OF_WEEK) != 1 && sdate
 75         .get(Calendar.DAY_OF_WEEK) != 7)
 76         && (edate.get(Calendar.DAY_OF_WEEK) != 1 && edate
 77         .get(Calendar.DAY_OF_WEEK) != 7)) {
 78         return new Long(end - start - holidays);
 79         }
 80         // 如果两个时间在同一周并且都是周末日期,则直接返回0
 81         if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR))
 82         && (sdate.get(Calendar.WEEK_OF_YEAR) == edate
 83         .get(Calendar.WEEK_OF_YEAR)-1)
 84         && (sdate.get(Calendar.DAY_OF_WEEK) == 1
 85         || sdate.get(Calendar.DAY_OF_WEEK) == 7)
 86         &&
 87         (edate.get(Calendar.DAY_OF_WEEK) == 1
 88         || edate.get(Calendar.DAY_OF_WEEK) == 7)) {
 89         start=validateStartTime(sdate);
 90         end=validateEndTime(edate);
 91         long result=end - start - holidays;
 92         return new Long(result>0?result:0);
 93         }
 94
 95         start=validateStartTime(sdate);
 96         end=validateEndTime(edate);
 97
 98         // 首先取得起始日期与结束日期的下个周一的日期
 99         Calendar snextM = getNextMonday(sdate);
100         Calendar enextM = getNextMonday(edate);
101
102         // 获取这两个周一之间的实际天数
103         int days = getDaysBetween(snextM, enextM);
104
105         // 获取这两个周一之间的工作日数(两个周一之间的天数肯定能被7整除,并且工作日数量占其中的5/7)
106         int workdays = days / 7 * 5;
107
108         // 计算最终结果,具体为:workdays加上开始时间的时间偏移量,减去结束时间的时间偏移量
109         double a=(double)workdays*24*3600000;
110         double result = (a + calcWorkdayTimeInMillis(sdate, edate, start, end) - holidays);
111        return result > 0 ? result : 0;
112     }
113     /***
114     * 验证开始日期是否合法,如果不合法,并返回修复后的正确日期毫秒数
115     * @param sdate
116     * @return
117     */
118     private long validateStartTime(Calendar sdate){
119         if(sdate.get(Calendar.DAY_OF_WEEK) == 1)//开始日期从周日开始,如果开始时间为周末,自动修复为下周的9:00开始
120         {
121             sdate.add(Calendar.DATE,1);
122             sdate.setTimeInMillis(sdate.getTime().getTime()- //从9点开始
123             (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)+ (sdate.get(Calendar.MINUTE) * 60000)+ (sdate.get(Calendar.SECOND) * 1000)));
124         }else if(sdate.get(Calendar.DAY_OF_WEEK) == 7){//开始日期从周六开始
125                 sdate.add(Calendar.DATE,2);
126                 sdate.setTimeInMillis(
127                 sdate.getTime().getTime()- //从9点开始,如果开始时间为周末,自动修复为下周的9:00开始
128                 (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)
129                + (sdate.get(Calendar.MINUTE) * 60000)
130                + (sdate.get(Calendar.SECOND) * 1000)));
131         }
132             return sdate.getTimeInMillis();
133     }
134
135
136     /***
137     * 验证结束日期是否合法,如果不合法,并返回修复后的正确日期毫秒数
138     * @param sdate
139     * @return
140     */
141     private long validateEndTime(Calendar edate)
142     {
143         if(edate.get(Calendar.DAY_OF_WEEK) == 1)//结束日期是周日,如果结束日期是周六、周末自动修复为这周五18:00
144         {
145         edate.add(Calendar.DATE,-2);
146         edate.setTimeInMillis(
147         edate.getTime().getTime()+
148         (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)
149         + (edate.get(Calendar.MINUTE) * 60000)
150         + (edate.get(Calendar.SECOND) * 1000))));
151         }else if(edate.get(Calendar.DAY_OF_WEEK) == 7){//结束日期是周六,如果结束日期是周六、周末自动修复为这周五18:00
152             edate.add(Calendar.DATE,-1);
153             edate.setTimeInMillis(
154             edate.getTime().getTime()+
155         (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000)
156         + (edate.get(Calendar.MINUTE) * 60000)
157         + (edate.get(Calendar.SECOND) * 1000))));}
158         return edate.getTimeInMillis();
159     }
160     /***
161     * 计算两个日期间的工作日天数,除周六日
162     *
163     * @param sdate
164     * @param edate
165     * @return
166     */
167     private long calcWorkdayTimeInMillis(Calendar sdate, Calendar edate,long start, long end) {
168         // 获取开始时间的偏移量
169         long scharge = 0;
170         if (sdate.get(Calendar.DAY_OF_WEEK) != 1
171         && sdate.get(Calendar.DAY_OF_WEEK) != 7) {
172         // 只有在开始时间为非周末的时候才计算偏移量
173         scharge += (sdate.get(Calendar.HOUR_OF_DAY) * 3600000);
174         scharge += (sdate.get(Calendar.MINUTE) * 60000);
175         scharge += (sdate.get(Calendar.SECOND) * 1000);
176         scharge = ((24 * 3600000) - scharge);
177
178         scharge += ((sdate.getTime().getTime() - start) - (3 * 24 * 3600000));
179         }
180         // (24*3600000=86400000)-((9*3600000+1800000)=34200000)+(3*24*3600000=259200000)-(2*24*3600000)=
181         // 86400000-34200000=52200000
182         // 获取结束时间的偏移量
183         long echarge = 0;
184         if (edate.get(Calendar.DAY_OF_WEEK) != 1
185         && edate.get(Calendar.DAY_OF_WEEK) != (7)) {
186         // 只有在结束时间为非周末的时候才计算偏移量
187         echarge += (edate.get(Calendar.HOUR_OF_DAY) * 3600000);
188         echarge += (edate.get(Calendar.MINUTE) * 60000);
189         echarge += (edate.get(Calendar.SECOND) * 1000);
190         echarge = ((24 * 3600000) - echarge);
191         echarge += (edate.getTime().getTime() - end) - (24 * 3600000);
192         echarge -= (2 * 24 * 3600000);
193         }
194         // (24*3600000=86400000)-(18*3600000=64800000)+(24*3=259200000)
195         if (scharge < 0 || echarge < 0)
196         scharge = echarge = 0;
197         return scharge - echarge;
198     }
199
200     /**
201     * 获取两个时间之内的工作日时间(只去掉两个日期之间的周末时间,法定节假日未去掉)
202     *
203     * @param start
204     * -起始时间,共有3个重载方法,可以传入long型,Long型,与Date型
205     * @param end
206     * -结束时间,共有3个重载方法,可以传入long型,Long型,与Date型
207     * @return Long型时间差对象
208     */
209     public double getWorkdayTimeInMillisExcWeekend(long start, long end) {
210         return getWorkdayTimeInMillis(start, end);
211     }
212
213     /***
214     * 获取两个时间之内的工作日时间(去掉两个日期之间的周末时间,法定节假日时间)
215     *
216     * @param start
217     * @param end
218     * @return
219     */
220     public double getWorkdayTimeInMillisExcWeekendHolidays(String start,String end, String format, List<Date> listHolidays) {
221         SimpleDateFormat sdf = new SimpleDateFormat(format);
222         Date sdate;
223         Date edate;
224         try {
225             sdate = sdf.parse(start);
226             edate = sdf.parse(end);
227             return getWorkdayTimeInMillis(sdate.getTime(), edate.getTime(),
228             listHolidays);
229             } catch (ParseException e) {
230             e.printStackTrace();
231             return new Long(0);
232         }
233     }
234
235     public double getWorkdayTimeInMillis(Long start, Long end) {
236         return getWorkdayTimeInMillis(start.longValue(), end.longValue(), null);
237         }
238
239         public double getWorkdayTimeInMillis(Date start, Date end) {
240         return getWorkdayTimeInMillis(start.getTime(), end.getTime(), null);
241         }
242
243         public double getWorkdayTimeInMillis(String start, String end, String format) {
244             SimpleDateFormat sdf = new SimpleDateFormat(format);
245             Date sdate;
246             Date edate;
247             try {
248                 sdate = sdf.parse(start);
249                 edate = sdf.parse(end);
250                 return getWorkdayTimeInMillis(sdate, edate);
251             } catch (ParseException e) {
252                 e.printStackTrace();
253                 return new Long(0);
254             }
255             }
256
257             private long getHolidaysInMillis(long start, long end,
258                 List<Date> listHolidays) {
259                 Calendar scalendar = Calendar.getInstance();
260                 Calendar ecalendar = Calendar.getInstance();
261                 int daysofH = 0;
262                 try {
263
264                 scalendar.setTimeInMillis(start);
265                 ecalendar.setTimeInMillis(end);
266
267                 if (listHolidays == null)
268                 return new Long(0);
269                 Iterator<Date> iterator = listHolidays.iterator();
270                 while (iterator.hasNext()) {
271                 Calendar ca = Calendar.getInstance();
272                 Date hdate = iterator.next();
273                 ca.setTime(hdate);
274                 if (ca.after(scalendar) && ca.before(ecalendar)) {
275                     daysofH = daysofH + 1;
276                 } else if (ca.getTimeInMillis() == scalendar.getTimeInMillis()) {
277                     daysofH = daysofH + 1;
278                 } else if (ca.getTimeInMillis() == ecalendar.getTimeInMillis()) {
279                     daysofH = daysofH + 1;
280                 }
281                 }
282
283                 } catch (Exception e) {
284                     e.printStackTrace();
285                     return new Long(0);
286                 }
287                    return daysofH * 24 * 3600000;
288          }
289
290
291         private Calendar getNextMonday(Calendar cal) {
292                 int addnum = 9 - cal.get(Calendar.DAY_OF_WEEK);
293                 if (addnum == 8)
294                 addnum = 1;// 周日的情况
295                 cal.add(Calendar.DATE, addnum);
296                 return cal;
297         }
298
299             /**
300             *
301             * @param mss
302             * @param 要转换的毫秒数
303             * @return 该毫秒数转换为 * days * hours * minutes * seconds 后的格式
304             */
305         public String formatDuring(double mss) {
306             long days = (long) (mss / (1000 * 60 * 60 * 24));
307             long hours = (long) ((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
308             long minutes = (long) ((mss % (1000 * 60 * 60)) / (1000 * 60));
309             long seconds = (long) ((mss % (1000 * 60)) / 1000);
310             return days + " days " + hours + " hours " + minutes + " minutes "
311             + seconds + " seconds ";
312             }
313
314             /**
315             * 获取两个日期之间的实际天数,支持跨年
316             * @param start
317             * @param end
318             *
319             */
320         /**
321          * 获得两个日期之间的工作日
322          * @since 1.0
323          * @param mss
324          * @return
325          * <br><b>作者: @author zhushunagshuang</b>
326          * <br>创建时间:2016年7月21日 下午3:12:23
327          */
328         public double formateToDay(double mss){
329             double days = mss / (1000 * 60 * 60 * 24);
330             return days;
331         }
332
333         public int getDaysBetween(Calendar start, Calendar end) {
334             if (start.after(end)) {
335             Calendar swap = start;
336             start = end;
337             end = swap;
338             }
339
340             int days = end.get(Calendar.DAY_OF_YEAR)- start.get(Calendar.DAY_OF_YEAR);
341             int y2 = end.get(Calendar.YEAR);
342             if (start.get(Calendar.YEAR) != y2) {
343                 start = (Calendar) start.clone();
344                 do {
345                     days += start.getActualMaximum(Calendar.DAY_OF_YEAR);
346                     start.add(Calendar.YEAR, 1);
347                 } while (start.get(Calendar.YEAR) != y2);
348
349             }
350             return days;
351         }
352         /**
353          * 手动维护2016年的节假日
354          * @since 1.0
355          * @return
356          * @throws ParseException
357          * <br><b>作者: @author zhushunagshuang</b>
358          * <br>创建时间:2016年7月21日 下午5:12:08
359          */
360         public List<Date> initHoliday() throws ParseException{
361             List<Date> holidays = new ArrayList<Date>();
362             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
363             //元旦
364             holidays.add(sdf.parse("2016-01-01"));
365             holidays.add(sdf.parse("2016-01-02"));
366             holidays.add(sdf.parse("2016-01-03"));
367             //春节
368             holidays.add(sdf.parse("2016-02-07"));
369             holidays.add(sdf.parse("2016-02-08"));
370             holidays.add(sdf.parse("2016-02-09"));
371             holidays.add(sdf.parse("2016-02-10"));
372             holidays.add(sdf.parse("2016-02-11"));
373             holidays.add(sdf.parse("2016-02-12"));
374             holidays.add(sdf.parse("2016-02-13"));
375             //清明节
376             holidays.add(sdf.parse("2016-04-02"));
377             holidays.add(sdf.parse("2016-04-03"));
378             holidays.add(sdf.parse("2016-04-04"));
379             //劳动节
380             holidays.add(sdf.parse("2016-04-30"));
381             holidays.add(sdf.parse("2016-05-01"));
382             holidays.add(sdf.parse("2016-05-02"));
383             //端午节
384             holidays.add(sdf.parse("2016-06-09"));
385             holidays.add(sdf.parse("2016-06-10"));
386             holidays.add(sdf.parse("2016-06-11"));
387             //中秋节
388             holidays.add(sdf.parse("2016-09-15"));
389             holidays.add(sdf.parse("2016-09-16"));
390             holidays.add(sdf.parse("2016-09-17"));
391             //国庆节
392             holidays.add(sdf.parse("2016-10-01"));
393             holidays.add(sdf.parse("2016-10-02"));
394             holidays.add(sdf.parse("2016-10-03"));
395             holidays.add(sdf.parse("2016-10-04"));
396             holidays.add(sdf.parse("2016-10-05"));
397             holidays.add(sdf.parse("2016-10-06"));
398             holidays.add(sdf.parse("2016-10-07"));
399             return holidays;
400         }
401
402 }
403         
时间: 2024-10-08 02:41:55

计算两个日期之间的工作日(去掉周末和节假日)的相关文章

用VBA计算两个日期之间的工作日(去掉周末两天)

最近公司HR和Finance想算员工的工作天数,想让我帮忙写些VBA,自己从网上找了下代码,自己再改改,以下来自网络. 计算两个日期之间的工作日,用VBA,因量大,最好用数组做 Sub kk() Dim arr, i&, j&, m& arr = Sheet2.Range("b3:f4") For i = 1 To UBound(arr) m = 0 For j = arr(i, 1) To arr(i, 3) If Weekday(j) <> 1

计算两个日期之间的工作日天数

最近遇到要求两个日期之间的工作日天数的问题,遂在网上找了下js的代码,参考了下别人的代码,发现写的都有些冗余,于是自己思考,进行了一下简单处理.主要是在循环处理上进行了精简. 对剩余天数的循环,也就可以考虑是对开始日期到剩余天数之间的处理,循环开始日期到剩余天数之间有多少个周六周日(最多只有一个周六或者一个周日),由于当前开始日期在(0-6)之间,也就是当前开始日期的星期对应的数字加上剩余天数(0-6)的循环一定在(0-11)之间,所以0,7代表周日,6代表周六. <html> <hea

计算两个日期之间的工作日

兰大顾的... FUNCTION zget_workdays. *"---------------------------------------------------------------------- *"*"Local Interface: *" IMPORTING *" VALUE(I_DATE1) LIKE SY-DATUM *" VALUE(I_DATE2) LIKE SY-DATUM *" EXPORTING *&qu

mysql 计算两个日期之间的工作日天数

创建透视表t500 建表 CREATE TABLE `t500` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=501 DEFAULT CHARSET=latin1; 插入500条数据 CREATE DEFINER=`json`@`%` PROCEDURE `i500`() BEGIN DECLARE a INT default 1; while a<=500 d

【翻译自mos文章】计算Oracle数据库中两个日期之间的工作日天数

计算两个日期之间的工作日天数(不包括这两个日期,不包括weekend) 参考自: How to Compute Business Days for a Date Range in SQL or PLSQL (Doc ID 1014162.6) 有两个方法: 第一个是 使用sql语句: SQL> SELECT ((TO_NUMBER(TRUNC(to_date('2015-04-22','yyyy-mm-dd'), 'D') - TRUNC(to_date('2015-04-21','yyyy-m

(013)每日SQL学习:确定两个日期之间的工作日天数和计算一年周内各日期次数

1.确定两个日期之间的工作日天数 --确定两个日期之间的工作日天数with x0 as (select to_date('2018-01-01','yyyy-mm-dd') as 日期 from dual union all select to_date('2018-01-15','yyyy-mm-dd') as 日期 from dual ), x1 as --日期并列显示 (select min (日期) 开始日期,max(日期) 结束日期 from x0 ), x2 as --日期之间的天数

计算两个日期之间相差几天(Date类型与String类型互相转换)

一:计算两个日期之间相差几天 1 /** 2 * 3 */ 4 package com.hlcui.date; 5 6 import java.text.ParseException; 7 import java.text.SimpleDateFormat; 8 import java.util.Calendar; 9 import java.util.Date; 10 11 import org.junit.Test; 12 13 /** 14 * @author Administrator

java计算两个日期之间相隔的天数

1 import java.text.ParseException; 2 import java.text.SimpleDateFormat; 3 import java.util.Calendar; 4 import java.util.Date; 5 6 7 public class date { 8 9 /** 10 * @param args 11 * @throws ParseException 12 */ 13 public static void main(String[] arg

Java 根据给定的日期,计算两个日期之间的时间差

计算两个Date之间的时间差,基本思路为把Date转换为ms(微秒),然后计算两个微秒时间差. 时间的兑换规则如下: 1s秒 = 1000ms毫秒 1min分种 = 60s秒 1hours小时 = 60min分钟 1day天 = 24hours小时 package com.qiyadeng.date; import java.text.SimpleDateFormat; import java.util.Date; public class DateDifferentExample { publ