绪论
请假时长计算和每月工作天数计算其实六月份开发OA系统时就已经写出来了,只是一直没时间去整理,其实最近也很忙,毕竟年底要清一些开发任务。不过感觉自己今年博客写的太少了,所以这些日子基本每天都在加班,就是为了给自己抽出时间写一点博客。
逻辑
- 获取开始时间到结束时间之间所有的日期集合,去掉周末(list1)。
- 获取法定节假日(list2)、获取调休(list3)、获取部门作息时间。
- 删除时间区间中的所有法定节假日 list1.removeAll(list2)。
- 添加开始时间到结束时间之间的所有调休日期。
- 去重。
- 计算。
代码
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)