公司要寫售後的一個功能,用到這個功能,在一個貼吧上找到的,整理一下,
package com.utouu.uphone.commons; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import java.util.List; import org.springframework.stereotype.Component; /** * 獲取工作日 * <br>創建日期:2016年7月21日 * <br><b>Copyright 2016 UTOUU All Rights Reserved</b> * @author zhushuangshuang * @since 1.0 * @version 1.0 */ @Component public class GetWorkDay { /** * 獲取兩個時間之內的工作日時間(只去掉兩個日期之間的周末時間,法定節假日未去掉) * * @param start * -起始時間,共有3個重載方法,可以傳入long型,Long型,與Date型 * @param end * -結束時間,共有3個重載方法,可以傳入long型,Long型,與Date型 * @return Long型時間差對象 */ /*public static void main(String[] args) { GetWorkDay g=new GetWorkDay(); List<Date> initHoliday; try { initHoliday = g.initHoliday(); double days = g.getWorkdayTimeInMillisExcWeekendHolidays("2016-06-30 17-12-53","2016-08-30 11-27-50","yyyy-MM-dd HH-mm-ss",initHoliday); double formateToDay = g.formateToDay(days); String formatDuring = g.formatDuring(days); System.out.println(formateToDay); System.out.println(formatDuring); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } */ private double getWorkdayTimeInMillis(long start, long end, List<Date> listHolidays) { // 如果起始時間大於結束時間,將二者交換 if (start > end) { long temp = start; start = end; end = temp; } // 根據參數獲取起始時間與結束時間的日歷類型對象 Calendar sdate = Calendar.getInstance(); Calendar edate = Calendar.getInstance(); sdate.setTimeInMillis(start); edate.setTimeInMillis(end); // 計算指定時間段內法定節假日天數的毫秒數 long holidays = 0; if (listHolidays != null) { holidays = getHolidaysInMillis(start, end, listHolidays); listHolidays.clear(); } // 如果兩個時間在同一周並且都不是周末日期,則直接返回時間差,增加執行效率 if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR)) && (sdate.get(Calendar.WEEK_OF_YEAR) == edate .get(Calendar.WEEK_OF_YEAR)) && (sdate.get(Calendar.DAY_OF_WEEK) != 1 && sdate .get(Calendar.DAY_OF_WEEK) != 7) && (edate.get(Calendar.DAY_OF_WEEK) != 1 && edate .get(Calendar.DAY_OF_WEEK) != 7)) { return new Long(end - start - holidays); } // 如果兩個時間在同一周並且都是周末日期,則直接返回0 if ((sdate.get(Calendar.YEAR) == edate.get(Calendar.YEAR)) && (sdate.get(Calendar.WEEK_OF_YEAR) == edate .get(Calendar.WEEK_OF_YEAR)-1) && (sdate.get(Calendar.DAY_OF_WEEK) == 1 || sdate.get(Calendar.DAY_OF_WEEK) == 7) && (edate.get(Calendar.DAY_OF_WEEK) == 1 || edate.get(Calendar.DAY_OF_WEEK) == 7)) { start=validateStartTime(sdate); end=validateEndTime(edate); long result=end - start - holidays; return new Long(result>0?result:0); } start=validateStartTime(sdate); end=validateEndTime(edate); // 首先取得起始日期與結束日期的下個周一的日期 Calendar snextM = getNextMonday(sdate); Calendar enextM = getNextMonday(edate); // 獲取這兩個周一之間的實際天數 int days = getDaysBetween(snextM, enextM); // 獲取這兩個周一之間的工作日數(兩個周一之間的天數肯定能被7整除,並且工作日數量占其中的5/7) int workdays = days / 7 * 5; // 計算最終結果,具體為:workdays加上開始時間的時間偏移量,減去結束時間的時間偏移量 double a=(double)workdays*24*3600000; double result = (a + calcWorkdayTimeInMillis(sdate, edate, start, end) - holidays); return result > 0 ? result : 0; } /*** * 驗證開始日期是否合法,如果不合法,並返回修復後的正確日期毫秒數 * @param sdate * @return */ private long validateStartTime(Calendar sdate){ if(sdate.get(Calendar.DAY_OF_WEEK) == 1)//開始日期從周日開始,如果開始時間為周末,自動修復為下周的9:00開始 { sdate.add(Calendar.DATE,1); sdate.setTimeInMillis(sdate.getTime().getTime()- //從9點開始 (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000)+ (sdate.get(Calendar.MINUTE) * 60000)+ (sdate.get(Calendar.SECOND) * 1000))); }else if(sdate.get(Calendar.DAY_OF_WEEK) == 7){//開始日期從周六開始 sdate.add(Calendar.DATE,2); sdate.setTimeInMillis( sdate.getTime().getTime()- //從9點開始,如果開始時間為周末,自動修復為下周的9:00開始 (((sdate.get(Calendar.HOUR_OF_DAY)-9) * 3600000) + (sdate.get(Calendar.MINUTE) * 60000) + (sdate.get(Calendar.SECOND) * 1000))); } return sdate.getTimeInMillis(); } /*** * 驗證結束日期是否合法,如果不合法,並返回修復後的正確日期毫秒數 * @param sdate * @return */ private long validateEndTime(Calendar edate) { if(edate.get(Calendar.DAY_OF_WEEK) == 1)//結束日期是周日,如果結束日期是周六、周末自動修復為這周五18:00 { edate.add(Calendar.DATE,-2); edate.setTimeInMillis( edate.getTime().getTime()+ (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000) + (edate.get(Calendar.MINUTE) * 60000) + (edate.get(Calendar.SECOND) * 1000)))); }else if(edate.get(Calendar.DAY_OF_WEEK) == 7){//結束日期是周六,如果結束日期是周六、周末自動修復為這周五18:00 edate.add(Calendar.DATE,-1); edate.setTimeInMillis( edate.getTime().getTime()+ (18*3600000-((edate.get(Calendar.HOUR_OF_DAY) * 3600000) + (edate.get(Calendar.MINUTE) * 60000) + (edate.get(Calendar.SECOND) * 1000))));} return edate.getTimeInMillis(); } /*** * 計算兩個日期間的工作日天數,除周六日 * * @param sdate * @param edate * @return */ private long calcWorkdayTimeInMillis(Calendar sdate, Calendar edate,long start, long end) { // 獲取開始時間的偏移量 long scharge = 0; if (sdate.get(Calendar.DAY_OF_WEEK) != 1 && sdate.get(Calendar.DAY_OF_WEEK) != 7) { // 只有在開始時間為非周末的時候才計算偏移量 scharge += (sdate.get(Calendar.HOUR_OF_DAY) * 3600000); scharge += (sdate.get(Calendar.MINUTE) * 60000); scharge += (sdate.get(Calendar.SECOND) * 1000); scharge = ((24 * 3600000) - scharge); scharge += ((sdate.getTime().getTime() - start) - (3 * 24 * 3600000)); } // (24*3600000=86400000)-((9*3600000+1800000)=34200000)+(3*24*3600000=259200000)-(2*24*3600000)= // 86400000-34200000=52200000 // 獲取結束時間的偏移量 long echarge = 0; if (edate.get(Calendar.DAY_OF_WEEK) != 1 && edate.get(Calendar.DAY_OF_WEEK) != (7)) { // 只有在結束時間為非周末的時候才計算偏移量 echarge += (edate.get(Calendar.HOUR_OF_DAY) * 3600000); echarge += (edate.get(Calendar.MINUTE) * 60000); echarge += (edate.get(Calendar.SECOND) * 1000); echarge = ((24 * 3600000) - echarge); echarge += (edate.getTime().getTime() - end) - (24 * 3600000); echarge -= (2 * 24 * 3600000); } // (24*3600000=86400000)-(18*3600000=64800000)+(24*3=259200000) if (scharge < 0 || echarge < 0) scharge = echarge = 0; return scharge - echarge; } /** * 獲取兩個時間之內的工作日時間(只去掉兩個日期之間的周末時間,法定節假日未去掉) * * @param start * -起始時間,共有3個重載方法,可以傳入long型,Long型,與Date型 * @param end * -結束時間,共有3個重載方法,可以傳入long型,Long型,與Date型 * @return Long型時間差對象 */ public double getWorkdayTimeInMillisExcWeekend(long start, long end) { return getWorkdayTimeInMillis(start, end); } /*** * 獲取兩個時間之內的工作日時間(去掉兩個日期之間的周末時間,法定節假日時間) * * @param start * @param end * @return */ public double getWorkdayTimeInMillisExcWeekendHolidays(String start,String end, String format, List<Date> listHolidays) { SimpleDateFormat sdf = new SimpleDateFormat(format); Date sdate; Date edate; try { sdate = sdf.parse(start); edate = sdf.parse(end); return getWorkdayTimeInMillis(sdate.getTime(), edate.getTime(), listHolidays); } catch (ParseException e) { e.printStackTrace(); return new Long(0); } } public double getWorkdayTimeInMillis(Long start, Long end) { return getWorkdayTimeInMillis(start.longValue(), end.longValue(), null); } public double getWorkdayTimeInMillis(Date start, Date end) { return getWorkdayTimeInMillis(start.getTime(), end.getTime(), null); } public double getWorkdayTimeInMillis(String start, String end, String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); Date sdate; Date edate; try { sdate = sdf.parse(start); edate = sdf.parse(end); return getWorkdayTimeInMillis(sdate, edate); } catch (ParseException e) { e.printStackTrace(); return new Long(0); } } private long getHolidaysInMillis(long start, long end, List<Date> listHolidays) { Calendar scalendar = Calendar.getInstance(); Calendar ecalendar = Calendar.getInstance(); int daysofH = 0; try { scalendar.setTimeInMillis(start); ecalendar.setTimeInMillis(end); if (listHolidays == null) return new Long(0); Iterator<Date> iterator = listHolidays.iterator(); while (iterator.hasNext()) { Calendar ca = Calendar.getInstance(); Date hdate = iterator.next(); ca.setTime(hdate); if (ca.after(scalendar) && ca.before(ecalendar)) { daysofH = daysofH + 1; } else if (ca.getTimeInMillis() == scalendar.getTimeInMillis()) { daysofH = daysofH + 1; } else if (ca.getTimeInMillis() == ecalendar.getTimeInMillis()) { daysofH = daysofH + 1; } } } catch (Exception e) { e.printStackTrace(); return new Long(0); } return daysofH * 24 * 3600000; } private Calendar getNextMonday(Calendar cal) { int addnum = 9 - cal.get(Calendar.DAY_OF_WEEK); if (addnum == 8) addnum = 1;// 周日的情況 cal.add(Calendar.DATE, addnum); return cal; } /** * * @param mss * @param 要轉換的毫秒數 * @return 該毫秒數轉換為 * days * hours * minutes * seconds 後的格式 */ public String formatDuring(double mss) { long days = (long) (mss / (1000 * 60 * 60 * 24)); long hours = (long) ((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); long minutes = (long) ((mss % (1000 * 60 * 60)) / (1000 * 60)); long seconds = (long) ((mss % (1000 * 60)) / 1000); return days + " days " + hours + " hours " + minutes + " minutes " + seconds + " seconds "; } /** * 獲取兩個日期之間的實際天數,支持跨年 * @param start * @param end * */ /** * 獲得兩個日期之間的工作日 * @since 1.0 * @param mss * @return * <br><b>作者: @author zhushunagshuang</b> * <br>創建時間:2016年7月21日 下午3:12:23 */ public double formateToDay(double mss){ double days = mss / (1000 * 60 * 60 * 24); return days; } public int getDaysBetween(Calendar start, Calendar end) { if (start.after(end)) { Calendar swap = start; start = end; end = swap; } int days = end.get(Calendar.DAY_OF_YEAR)- start.get(Calendar.DAY_OF_YEAR); int y2 = end.get(Calendar.YEAR); if (start.get(Calendar.YEAR) != y2) { start = (Calendar) start.clone(); do { days += start.getActualMaximum(Calendar.DAY_OF_YEAR); start.add(Calendar.YEAR, 1); } while (start.get(Calendar.YEAR) != y2); } return days; } /** * 手動維護2016年的節假日 * @since 1.0 * @return * @throws ParseException * <br><b>作者: @author zhushunagshuang</b> * <br>創建時間:2016年7月21日 下午5:12:08 */ public List<Date> initHoliday() throws ParseException{ List<Date> holidays = new ArrayList<Date>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //元旦 holidays.add(sdf.parse("2016-01-01")); holidays.add(sdf.parse("2016-01-02")); holidays.add(sdf.parse("2016-01-03")); //春節 holidays.add(sdf.parse("2016-02-07")); holidays.add(sdf.parse("2016-02-08")); holidays.add(sdf.parse("2016-02-09")); holidays.add(sdf.parse("2016-02-10")); holidays.add(sdf.parse("2016-02-11")); holidays.add(sdf.parse("2016-02-12")); holidays.add(sdf.parse("2016-02-13")); //清明節 holidays.add(sdf.parse("2016-04-02")); holidays.add(sdf.parse("2016-04-03")); holidays.add(sdf.parse("2016-04-04")); //勞動節 holidays.add(sdf.parse("2016-04-30")); holidays.add(sdf.parse("2016-05-01")); holidays.add(sdf.parse("2016-05-02")); //端午節 holidays.add(sdf.parse("2016-06-09")); holidays.add(sdf.parse("2016-06-10")); holidays.add(sdf.parse("2016-06-11")); //中秋節 holidays.add(sdf.parse("2016-09-15")); holidays.add(sdf.parse("2016-09-16")); holidays.add(sdf.parse("2016-09-17")); //國慶節 holidays.add(sdf.parse("2016-10-01")); holidays.add(sdf.parse("2016-10-02")); holidays.add(sdf.parse("2016-10-03")); holidays.add(sdf.parse("2016-10-04")); holidays.add(sdf.parse("2016-10-05")); holidays.add(sdf.parse("2016-10-06")); holidays.add(sdf.parse("2016-10-07")); return holidays; } }
貼出來。