java 計算工作時間除去節假日,雙休日

package common.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public class CalculateHours {
	SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); //這裏的格式可以自己設置 
	//設置上班時間:該處時間可以根據實際情況進行調整
	int abh = 9;//上午上班時間,小時
	int abm = 00;//上午上班時間,分鐘
	int aeh = 12;//上午下班時間,小時
	int aem = 0;//上午下班時間,分鐘
	int pbh = 13;//下午上班時間,小時
	int pbm = 00;//下午上班時間,分鐘
	int peh = 18;//下午下班時間,小時
	int pem = 0;//下午下班時間,分鐘
	float h1 = abh+(float)abm/60;
	float h2 = aeh+(float)aem/60;
	float h3 = pbh+(float)pbm/60;
	float h4 = peh+(float)pem/60;
	float hoursPerDay = h2-h1+(h4-h3);//每天上班小時數
	int daysPerWeek = 5;//每週工作天數
	long milsecPerDay = 1000*60*60*24;//每天的毫秒數
	float hoursPerWeek = hoursPerDay*daysPerWeek;//每星期小時數
	public float calculateHours(String beginTime, String endTime){
		//對輸入的字符串形式的時間進行轉換
		Date t1 = stringToDate(beginTime);//真實開始時間
		Date t2 = stringToDate(endTime);//真實結束時間
		//對時間進行預處理
		t1 = processBeginTime(t1);
		t2 = processEndTime(t2);
		//若開始時間晚於結束時間,返回0
		if(t1.getTime()>t2.getTime()){
			return 0;
		}
		//開始時間到結束時間的完整星期數
		int weekCount = (int) ((t2.getTime()-t1.getTime())/(milsecPerDay*7));
		float totalHours = 0;
		totalHours += weekCount * hoursPerWeek;
		//調整結束時間,使開始時間和結束時間在一個星期的週期之內
		t2.setTime(t2.getTime()-weekCount*7*milsecPerDay);
		int dayCounts = 0;//記錄開始時間和結束時間之間工作日天數
		//調整開始時間,使得開始時間和結束時間在同一天,或者相鄰的工作日內。
		while(t1.getTime()<=t2.getTime()){
			Date temp = new Date(t1.getTime()+milsecPerDay);
			temp = processBeginTime(temp);
			temp.setHours(t1.getHours());
			temp.setMinutes(t1.getMinutes());
			if(temp.getTime()>t2.getTime()){
				break;
			}else{
				t1 = temp;
				dayCounts++;
			}
		}
		totalHours += dayCounts * hoursPerDay;
		float hh1 = t1.getHours() + (float)t1.getMinutes()/60;
		float hh2 = t2.getHours() + (float)t2.getMinutes()/60;
		//處理開始結束是同一天的情況
		if(t1.getDay()==t2.getDay()){
			float tt = 0;
			tt = hh2 - hh1;
			if(hh1>=h1&&hh1<=h2&&hh2>=h3){
				tt = tt - (h3-h2);
			}
			totalHours += tt;
		}else{
			//處理開始結束不是同一天的情況
			float tt1 = h4 - hh1;
			float tt2 = hh2 - h1;
			if(hh1<=h2){
				tt1 = tt1 - (h3-h2);
			}
			if(hh2>=h3){
				tt2 = tt2 - (h3-h2);
			}
			totalHours += (tt1 + tt2);
		}
		return totalHours;
	}

	/**
	 * 格式化輸出時間: yyyy-mm-dd hh:mm:ss 星期x
	 * @param t
	 * @return
	 */
	private String printDate(Date t) {
		String str;
		String xingqi = null;
		switch (t.getDay()) {
		case 0:
			xingqi = "星期天";
			break;
		case 1:
			xingqi = "星期一";
			break;
		case 2:
			xingqi = "星期二";
			break;
		case 3:
			xingqi = "星期三";
			break;
		case 4:
			xingqi = "星期四";
			break;
		case 5:
			xingqi = "星期五";
			break;
		case 6:
			xingqi = "星期六";
			break;
		default:
			break;
		}
		str = format.format(t)+"  "+xingqi;
		return str;
	}

	/**
	 * 對結束時間進行預處理,使其處於工作日內的工作時間段內
	 * @param t
	 * @return
	 */
	private Date processEndTime(Date t) {
		float h = t.getHours() + (float)t.getMinutes()/60;
		//若結束時間晚於下午下班時間,將其設置爲下午下班時間
		if(h>=h4){
			t.setHours(peh);
			t.setMinutes(pem);
		}else {
			//若結束時間介於中午休息時間,那麼設置爲上午下班時間
			if(h>=h2&&h<=h3){
				t.setHours(aeh);
				t.setMinutes(aem);
			}else{
				//若結束時間早於上午上班時間,日期向前推一天,並將時間設置爲下午下班時間
				if(t.getHours()<=h1){
					t.setTime(t.getTime()-milsecPerDay);
					t.setHours(peh);
					t.setMinutes(pem);
				}
			}
		}
		//若結束時間是週末,那麼將結束時間向前推移到最近的工作日的下午下班時間
		if(t.getDay()==0){
			t.setTime(t.getTime()-milsecPerDay*(t.getDay()==6?1:2));
			t.setHours(peh);
			t.setMinutes(pem);
		}
		if(t.getDay()==6){
			t.setTime(t.getTime()-milsecPerDay*(t.getDay()==6?1:2));
			t.setHours(peh);
			t.setMinutes(pem);
		}
		return t;
	}
	/**
	 * 對開始時間進行預處理
	 * @param t1
	 * @return
	 */
	private Date processBeginTime(Date t) {
		float h = t.getHours() + (float)t.getMinutes()/60;
		//若開始時間晚於下午下班時間,將開始時間向後推一天
		if(h>=h4){
			t.setTime(t.getTime()+milsecPerDay);
			t.setHours(abh);
			t.setMinutes(abm);
		}else {
			//若開始時間介於中午休息時間,那麼設置爲下午上班時間
			if(h>=h2&&h<=h3){
				t.setHours(pbh);
				t.setMinutes(pbm);
			}else{
				//若開始時間早於上午上班時間,將hour設置爲上午上班時間
				if(t.getHours()<=h1){
					t.setHours(abh);
					t.setMinutes(abm);
				}
			}
		}
		//若開始時間是週末,那麼將開始時間向後推移到最近的工作日的上午上班時間
		if(t.getDay()==0){
			t.setTime(t.getTime()+milsecPerDay*(t.getDay()==6?2:1));
			t.setHours(abh);
			t.setMinutes(abm);
		}if(t.getDay()==6){
			t.setTime(t.getTime()+milsecPerDay*(t.getDay()==6?2:1));
			t.setHours(abh);
			t.setMinutes(abm);
		}
		return t;
	}

	/**
	 * 將字符串形式的時間轉換成Date形式的時間
	 * @param time
	 * @return
	 */
	private Date stringToDate(String time){
		try {
			return format.parse(time);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 去除週末節假日工作小時
	 * @param beginTime
	 * @param endTime
	 * @return
	 * @throws ParseException
	 */
	public static float CalculateHour(String beginTime,String endTime) throws ParseException{
		CalculateHours ch = new CalculateHours();
		float a=ch.calculateHours(beginTime, endTime);  
		Calendar startDay = Calendar.getInstance();
		  Calendar endDay = Calendar.getInstance();
		  startDay.setTime(FORMATTER.parse(beginTime));
		  endDay.setTime(FORMATTER.parse(endTime));
		String[] workday=printDay(startDay, endDay);
	    String[] holiday = new String[]{"01-01","01-02","01-03","05-01","05-02","05-03","10-01","10-02",
	    		"10-03","10-04","10-05","10-06","02-08","02-09","02-10"};
	    Calendar now = Calendar.getInstance();  
        int year=now.get(Calendar.YEAR); //獲取當前年份
	    List<String> list = new ArrayList<String>();
	    for (String string : holiday) {
			string=year+"-"+string;
			list.add(string);
		}
	    String[] arr = list.toArray(new String[0]);
	    int holidays = arrContrast(workday, arr); 
	    int holidayHous=holidays*8;
		float  b   =  (float)(Math.round(a*10))/10;
		float workHours=b-holidayHous;
		return workHours;
	}
	public static void main(String[] args) throws ParseException {
		String beginTime = "2018-6-1 9:00:00";  
		String endTime = "2018-6-4 10:10:00";  
		CalculateHours ch = new CalculateHours();
		float b=ch.calculateHours(beginTime, endTime);
		System.out.println(b);
		float a=CalculateHours.CalculateHour(beginTime, endTime);
		System.out.println(a);
	}
	/**
     * 去除數組中相同日期
     * @param arr1
     * @param arr2
     * @return
     */
    private static int arrContrast(String[] arr1, String[] arr2){
    	int count=0;
	    List<String> list = new LinkedList<String>();
	    for (String str : arr1) { //處理第一個數組,list裏面的值爲1,2,3,4
		    if (!list.contains(str)) {
		    list.add(str);
		    }
	    }
	    for (String str : arr2) { //如果第二個數組存在和第一個數組相同的值,就刪除
		    if(list.contains(str)){
		    list.remove(str);
		    ++count;
		    }
	    }
	    return count;
    }
    private static final DateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
    private static String[] printDay(Calendar startDay, Calendar endDay) {
		  List<String> list = new ArrayList<String>();
		  // 給出的日期開始日比終了日大則不執行打印
		  if (startDay.compareTo(endDay) >= 0) {
		   return new String[]{};
		  }
	  // 現在打印中的日期
	  Calendar currentPrintDay = startDay;
	  while (true) {
	   // 日期加一
	   currentPrintDay.add(Calendar.DATE, 1);
	   // 日期加一後判斷是否達到終了日,達到則終止打印
	   if (currentPrintDay.compareTo(endDay) == 0) {
	    break;
	   }
	   list.add(FORMATTER.format(currentPrintDay.getTime()));
	  }
	   String[] arr = list.toArray(new String[0]);
	   return arr;
	 }
}

  main方法中的執行結果爲:


代碼中都有註釋,可自行根據需要進行調節



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章