請假時長計算和每月工作天數計算

緒論

請假時長計算和每月工作天數計算其實六月份開發OA系統時就已經寫出來了,只是一直沒時間去整理,其實最近也很忙,畢竟年底要清一些開發任務。不過感覺自己今年博客寫的太少了,所以這些日子基本每天都在加班,就是爲了給自己抽出時間寫一點博客。

邏輯

  1. 獲取開始時間到結束時間之間所有的日期集合,去掉週末(list1)。
  2. 獲取法定節假日(list2)、獲取調休(list3)、獲取部門作息時間。
  3. 刪除時間區間中的所有法定節假日 list1.removeAll(list2)。
  4. 添加開始時間到結束時間之間的所有調休日期。
  5. 去重。
  6. 計算。

代碼

MyData .java

package com.config;

// 基礎數據類,可從數據庫獲取
public class MyData {

	// 假期
	public static String[] holiday1 = { 
			"2018-01-01", // 元旦
			"2018-02-15", // 春節
			"2018-02-16", // 春節
			"2018-02-17", // 春節
			"2018-02-18", // 春節
			"2018-02-19", // 春節
			"2018-02-20", // 春節
			"2018-02-21", // 春節
			"2018-04-05", // 清明節
			"2018-04-06", // 清明節
			"2018-04-07", // 清明節
			"2018-04-29", // 勞動節
			"2018-04-30", // 勞動節
			"2018-05-01", // 勞動節
			"2018-06-16", // 端午節
			"2018-06-17", // 端午節
			"2018-06-18", // 端午節
			"2018-09-22", // 中秋節
			"2018-09-23", // 中秋節
			"2018-09-24", // 中秋節
			"2018-10-01", // 國慶節
			"2018-10-02", // 國慶節
			"2018-10-03", // 國慶節
			"2018-10-04", // 國慶節
			"2018-10-05", // 國慶節
			"2018-10-06", // 國慶節
			"2018-10-07", // 國慶節
			"2018-12-31", // 元旦
			"2019-01-01" // 元旦
	};

	// 調休
	public static String[] holiday2 = { 
			"2018-02-11", // 春節_調休
			"2018-02-24", // 春節_調休
			"2018-04-08", // 清明_節調休
			"2018-04-28", // 勞動_節調休
			"2018-09-29", // 國慶節_調休
			"2018-09-30", // 國慶節_調休
			"2018-12-29"  // 元旦_調休
	};

	// 作息時間1
	public static String[] workTime1 = { 
			"08:30", // 上午上班時間
			"12:00", // 上午下班時間
			"13:00", // 下午上班時間
			"17:30"  // 下午下班時間
	};

	// 作息時間2
	public static String[] workTime2 = { 
			"09:00", // 上午上班時間
			"12:00", // 上午下班時間
			"13:00", // 下午上班時間
			"18:00"  // 下午下班時間
	};
}

DateUtils.java

package com.utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.config.MyData;

// 時間處理工作類
public class DateUtils {

	/**
	 * 定義常見的時間格式
	 */
	private static String[] dateFormat = { 
			"yyyy-MM-dd HH:mm:ss", // 0
			"yyyy/MM/dd HH:mm:ss", // 1
			"yyyy年MM月dd日HH時mm分ss秒", // 2
			"yyyy-MM-dd", // 3
			"yyyy/MM/dd", // 4
			"yy-MM-dd", // 5
			"yy/MM/dd", // 6
			"yyyy年MM月dd日", // 7
			"HH:mm:ss", // 8
			"yyyyMMddHHmmss", // 9
			"yyyyMMdd", // 10
			"yyyy.MM.dd", // 11
			"yy.MM.dd", // 12
			"MM月dd日HH時mm分", // 13
			"yyyy年MM月dd日 HH:mm:ss", // 14
			"yyyy-MM-dd HH:mm", // 15
			"yyMMdd" // 16
	};

	/**
	 * 去重
	 * 
	 * @param str
	 * @return
	 */
	public static List<String> removal(List<String> str) {
		Set<String> s = new HashSet<String>(str);
		str.clear();
		str.addAll(s);
		return str;
	}

	/**
	 * 獲取兩個日期之間的所有日期,去掉週末
	 * 
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static List<String> getDates(String startDate, String endDate) {
		List<String> result = new ArrayList<String>();
		Calendar startDay = Calendar.getInstance();
		Calendar endDay = Calendar.getInstance();

		startDay.setTime(StringToDate(startDate, 3));
		endDay.setTime(StringToDate(endDate, 3));

		while (startDay.before(endDay)) {
			int week = startDay.get(Calendar.DAY_OF_WEEK);
			if (7 != week && 1 != week) {
				result.add(dateToString(startDay.getTime(), 3));
			}
			startDay.add(Calendar.DAY_OF_YEAR, 1);
		}
		// 驗證結束日期是否是週六週日
		int week = endDay.get(Calendar.DAY_OF_WEEK);
		if (7 != week && 1 != week) {
			result.add(dateToString(endDay.getTime(), 3));
		}

		return result;
	}

	/**
	 * 字符串轉時間
	 * 
	 * @param dateStr
	 * @param index
	 * @return
	 */
	public static Date StringToDate(String dateStr, int index) {
		DateFormat df = null;
		try {
			df = new SimpleDateFormat(dateFormat[index]);
			return df.parse(dateStr);
		} catch (Exception aioe) {
			return null;
		}
	}

	/**
	 * 時間轉字符串
	 * 
	 * @param date
	 * @param index
	 * @return
	 */
	public static String dateToString(Date date, int index) {
		if (date == null) {
			return null;
		}
		return new SimpleDateFormat(dateFormat[index]).format(date);
	}

	/**
	 * 獲取法定節假日或者調休
	 * 
	 * @param num
	 * @return
	 */
	public static List<String> holiday(int num) {
		if (num == 2) {
			return Arrays.asList(MyData.holiday2);
		} else {
			return Arrays.asList(MyData.holiday1);
		}
	}

	/**
	 * 獲取不同部門工作時間
	 * 
	 * @param num
	 * @return
	 */
	public static String[] workTime(int num) {
		if (num == 2) {
			return MyData.workTime2;
		} else {
			return MyData.workTime1;
		}
	}

	/**
	 * 查詢每個月的工作時間(天)
	 *
	 * @return
	 */
	public static double queryMonthDay(String day) {
		List<String> result = new ArrayList<String>();
		Calendar Day = Calendar.getInstance();
		Day.setTime(StringToDate(day, 3));
		// 獲取該月天數
		int dayNum = Day.getActualMaximum(Calendar.DAY_OF_MONTH);
		// 月開始
		String st = day.substring(0, 8) + "01";
		// 月結束
		String en = day.substring(0, 8) + dayNum;
		// 月份數據集合
		for (int i = 1; i < dayNum + 1; i++) {
			String d = day.substring(0, 8) + ((i < 10) ? "0" + i : "" + i);
			// 去掉週末
			Calendar startDay = Calendar.getInstance();
			startDay.setTime(StringToDate(d, 3));
			int week = startDay.get(Calendar.DAY_OF_WEEK);
			if (7 != week && 1 != week) {
				result.add(d);
			}
		}

		// 獲取法定節假日
		List<String> fdList = holiday(1);
		// 獲取調休
		List<String> txList = holiday(2);
		// 添加時間段中間應該上班的時間
		for (String s : txList) {
			if (s.compareTo(st) >= 0 && s.compareTo(en) <= 0) {
				result.add(s);
			}
		}
		// 去除中間所有的法定假期
		result.removeAll(fdList);
		// 去重
		result = removal(result);
		return result.size();
	}
}

LeaveManage.java

package com.leave;

import java.util.Date;
import java.util.List;

import com.utils.DateUtils;

// 請假時長處理計算
public class LeaveManage {
	public static final LeaveManage manage = new LeaveManage();

	// 判斷時間大小
	public double pdTime(String startTime, String endTime, int login) {
		int num = startTime.compareTo(endTime);
		if (num > 0) {
			return calculationTime(endTime, startTime, login);
		} else if (num < 0) {
			return calculationTime(startTime, endTime, login);
		} else {
			return 0;
		}
	}

	public double calculationTime(String startTime, String endTime, int login) {
		// 獲取startTime和endTime之間的所有日期,去掉週六週日
		List<String> list = DateUtils.getDates(startTime, endTime);
		// 獲取法定節假日
		List<String> fdList = DateUtils.holiday(1);
		// 獲取調休
		List<String> txList = DateUtils.holiday(2);
		// 上班時間
		String[] workTime = DateUtils.workTime(login);
		// 刪除時間區間中的所有法定節假日
		list.removeAll(fdList);
		String st = startTime.substring(0, 10);
		String en = endTime.substring(0, 10);
		for (String s : txList) {
			if (s.compareTo(st) >= 0 && s.compareTo(en) <= 0) {
				// 添加時間區間中的所有調休日期
				list.add(s);
			}
		}
		// 去重
		list = DateUtils.removal(list);
		// 開始當天上午上班時間、上午下班時間、下午上班時間、下午下班時間
		String amWorkYes = startTime.substring(0, 11) + workTime[0];
		String amWorkNo = startTime.substring(0, 11) + workTime[1];
		String pmWorkYes = startTime.substring(0, 11) + workTime[2];
		String pmWorkNo = startTime.substring(0, 11) + workTime[3];

		// 結束當天上午上班時間、上午下班時間、下午上班時間、下午下班時間
		String amWorkYesEnd = endTime.substring(0, 11) + workTime[0];
		String amWorkNoEnd = endTime.substring(0, 11) + workTime[1];
		String pmWorkYesEnd = endTime.substring(0, 11) + workTime[2];
		String pmWorkNoEnd = endTime.substring(0, 11) + workTime[3];

		double time = 0;

		if (list.size() == 0) {
			// 申請日期是法定節假日
			return time;
		} else if (list.size() == 1) {
			// 請假一天
			if (startTime.compareTo(pmWorkNo) > 0) {
				return time;
			}
			if (endTime.compareTo(amWorkYes) < 0) {
				return time;
			}
			if (startTime.compareTo(amWorkNo) >= 0 && endTime.compareTo(pmWorkYes) <= 0) {
				return time;
			}
			if (startTime.compareTo(amWorkYes) < 0) {
				startTime = amWorkYes;
			}
			if (endTime.compareTo(pmWorkNo) > 0) {
				endTime = pmWorkNo;
			}
			if (startTime.compareTo(amWorkNo) >= 0 && startTime.compareTo(pmWorkYes) <= 0) {
				startTime = pmWorkYes;
			}
			if (endTime.compareTo(amWorkNo) >= 0 && endTime.compareTo(pmWorkYes) <= 0) {
				endTime = amWorkNo;
			}
			Date start = DateUtils.StringToDate(startTime, 15); // 0或者15
			Date end = DateUtils.StringToDate(endTime, 15);

			// 三種情況,1:請假時間全在上午,2:請假時間全在下午,3:包含午休時間
			if (startTime.compareTo(amWorkYes) >= 0 && endTime.compareTo(amWorkNo) <= 0) {
				double minute = (end.getTime() - start.getTime()) / (1000 * 60);
				time = minute / (8 * 60);
			} else if (startTime.compareTo(pmWorkYes) >= 0 && endTime.compareTo(pmWorkNo) <= 0) {
				double minute = (end.getTime() - start.getTime()) / (1000 * 60);
				time = minute / (8 * 60);
			} else if (startTime.compareTo(amWorkNo) < 0 && endTime.compareTo(pmWorkYes) > 0) {
				double minute = (end.getTime() - start.getTime()) / (1000 * 60) - 60;
				time = minute / (8 * 60);
			}
			return time;
		} else {
			// 處理請假多天的情況
			// 申請開始時間處理
			if (list.contains(st)) {
				if (startTime.compareTo(amWorkYes) < 0) {
					startTime = amWorkYes;
				}
				if (startTime.compareTo(pmWorkNo) > 0) {
					startTime = pmWorkNo;
				}
				if (startTime.compareTo(amWorkNo) >= 0 && startTime.compareTo(pmWorkYes) <= 0) {
					startTime = pmWorkYes;
				}
				Date start = DateUtils.StringToDate(startTime, 15); // 0或者15
				Date end = DateUtils.StringToDate(pmWorkNo, 15);
				if (startTime.compareTo(amWorkNo) < 0) {
					// 減去中午一小時
					double t = (end.getTime() - start.getTime()) / (1000 * 60) - 60;
					time = time + t / (8 * 60);
				} else {
					double t = (end.getTime() - start.getTime()) / (1000 * 60);
					time = time + t / (8 * 60);
				}
				list.remove(st);
			}
			// 申請結束時間處理
			if (list.contains(en)) {
				if (endTime.compareTo(amWorkYesEnd) < 0) {
					endTime = amWorkYesEnd;
				}
				if (endTime.compareTo(pmWorkNoEnd) > 0) {
					endTime = pmWorkNoEnd;
				}

				if (endTime.compareTo(amWorkNoEnd) >= 0 && endTime.compareTo(pmWorkYesEnd) <= 0) {
					endTime = amWorkNoEnd;
				}

				Date end = DateUtils.StringToDate(endTime, 15);// 0或者15
				Date start = DateUtils.StringToDate(amWorkYesEnd, 15);
				if (endTime.compareTo(pmWorkYesEnd) > 0) {
					double t = (end.getTime() - start.getTime()) / (1000 * 60) - 60;
					time = time + t / (8 * 60);
				} else {
					double t = (end.getTime() - start.getTime()) / (1000 * 60);
					time = time + t / (8 * 60);
				}
				list.remove(en);
			}
			// 天數計算集合中剩下的個數就可以
			time = time + list.size();
			return time;
		}
	}
}

Main.java

package com.leave;

import com.utils.DateUtils;

public class Main {
	static LeaveManage manage = LeaveManage.manage;

	public static void main(String[] args) {
		System.out.println("1、正常工作日請假:" + manage.calculationTime("2018-12-21 08:30", "2018-12-24 17:30", 1));
		System.out.println("2、帶調休請假:" + manage.calculationTime("2018-12-27 08:30", "2018-12-29 17:30", 1));
		System.out.println("3、法定節假日請假:" + manage.calculationTime("2018-09-24 08:30", "2018-09-26 17:30", 1));
		System.out.println("4、跨年請假:" + manage.calculationTime("2018-12-29 08:30", "2019-01-02 17:30", 1));

		System.out.println("2018年01月上班天數:" + DateUtils.queryMonthDay("2018-01-10"));
		System.out.println("2018年02月上班天數:" + DateUtils.queryMonthDay("2018-02-10"));
		System.out.println("2018年03月上班天數:" + DateUtils.queryMonthDay("2018-03-10"));
		System.out.println("2018年04月上班天數:" + DateUtils.queryMonthDay("2018-04-10"));
		System.out.println("2018年05月上班天數:" + DateUtils.queryMonthDay("2018-05-10"));
		System.out.println("2018年06月上班天數:" + DateUtils.queryMonthDay("2018-06-10"));
		System.out.println("2018年07月上班天數:" + DateUtils.queryMonthDay("2018-07-10"));
		System.out.println("2018年08月上班天數:" + DateUtils.queryMonthDay("2018-08-10"));
		System.out.println("2018年09月上班天數:" + DateUtils.queryMonthDay("2018-09-10"));
		System.out.println("2018年10月上班天數:" + DateUtils.queryMonthDay("2018-10-10"));
		System.out.println("2018年11月上班天數:" + DateUtils.queryMonthDay("2018-11-10"));
		System.out.println("2018年12月上班天數:" + DateUtils.queryMonthDay("2018-12-10"));
	}

}

結果

在這裏插入圖片描述

由於源碼涉及到的內容比較多,無法粘貼出來,所以又新寫了一遍。其中法定節假日和調休可以用SQL語句(用開始和結束時間約束)從數據庫獲取,對於不同作息時間的員工,可以實現單獨處理。

源代碼下載地址

(若有什麼錯誤,請留言指正,3Q)

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