|
@@ -0,0 +1,293 @@
|
|
|
|
+package com.boman.web.core.utils;
|
|
|
|
+
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+
|
|
|
|
+import java.util.Date;
|
|
|
|
+
|
|
|
|
+import static com.boman.common.core.utils.DateUtils.*;
|
|
|
|
+import static com.boman.common.core.utils.obj.ObjectUtils.isEmpty;
|
|
|
|
+import static com.boman.common.core.utils.obj.ObjectUtils.requireNonNull;
|
|
|
|
+import static com.boman.domain.constant.AttendanceRulesConst.*;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @author shiqian
|
|
|
|
+ * @date 2021年08月05日 13:50
|
|
|
|
+ **/
|
|
|
|
+public class LeaveFromUtils {
|
|
|
|
+
|
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(LeaveFromUtils.class);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 功能描述:
|
|
|
|
+ *
|
|
|
|
+ * @param startTime 请假开始时间
|
|
|
|
+ * @param endTime 请假结束时间
|
|
|
|
+ * @param yearMonthDay 递归的时候需要,传的是结束时间当天的yyyyMMdd
|
|
|
|
+ * @param rule 规则
|
|
|
|
+ * @return long 请假的总分钟数
|
|
|
|
+ */
|
|
|
|
+ public static long calcTimes(Date startTime, Date endTime, String yearMonthDay, JSONObject rule) {
|
|
|
|
+ long minutes = 0;
|
|
|
|
+ requireNonNull(startTime, "请假开始时间为空");
|
|
|
|
+ requireNonNull(endTime, "请假结束时间为空");
|
|
|
|
+ requireNonNull(rule, "未配置部门上下班规则");
|
|
|
|
+ if (endTime.before(startTime)) {
|
|
|
|
+ throw new IllegalArgumentException("请假结束时间必须大约开始时间");
|
|
|
|
+ } else if (endTime.equals(startTime)) {
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 递归的时候,这些时间不能以当天时间来算,而应该以请假结束时间所在的那一天来算(递归时使用)
|
|
|
|
+ // 规定上午上班时间 规定上午下班时间 规定下午上班时间 规定下午下班时间
|
|
|
|
+ Date amStart, amEnd, pmStart, pmEnd;
|
|
|
|
+ if (isEmpty(yearMonthDay)) {
|
|
|
|
+ amStart = strToDate(packRuleTime(rule.getString(ATTENDANCE_RULES_START_TIME)), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ amEnd = strToDate(packRuleTime(rule.getString(ATTENDANCE_RULES_END_TIME)), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ pmStart = strToDate(packRuleTime(rule.getString(ATTENDANCE_RULES_START_TIME_PM)), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ pmEnd = strToDate(packRuleTime(rule.getString(ATTENDANCE_RULES_END_TIME_PM)), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ } else {
|
|
|
|
+ String hourAmStart = rule.getString(ATTENDANCE_RULES_START_TIME);
|
|
|
|
+ String hourAmEnd = rule.getString(ATTENDANCE_RULES_END_TIME);
|
|
|
|
+ String hourPmStart = rule.getString(ATTENDANCE_RULES_START_TIME_PM);
|
|
|
|
+ String hourPmEnd = rule.getString(ATTENDANCE_RULES_END_TIME_PM);
|
|
|
|
+ amStart = strToDate(packRuleTime(yearMonthDay, hourAmStart), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ amEnd = strToDate(packRuleTime(yearMonthDay, hourAmEnd), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ pmStart = strToDate(packRuleTime(yearMonthDay, hourPmStart), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ pmEnd = strToDate(packRuleTime(yearMonthDay, hourPmEnd), YYYY_MM_DD_HH_MM_SS);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 一天的开始时间 一天的结束时间
|
|
|
|
+ Date todayStart = getTodayStart(), todayEnd = getTodayEnd();
|
|
|
|
+
|
|
|
|
+ // startTime 00:00 - 9:00
|
|
|
|
+ if (afterEq(startTime, todayStart) && beforeEq(startTime, amStart)) {
|
|
|
|
+ // 9:00 - 12:00
|
|
|
|
+ if (afterEq(endTime, amStart) && beforeEq(endTime, amEnd)) {
|
|
|
|
+ return calcMinutes(amStart, endTime);
|
|
|
|
+ } else if (afterEq(endTime, amEnd) && beforeEq(endTime, pmStart)) {
|
|
|
|
+ return calcMinutes(amStart, amEnd);
|
|
|
|
+ } else if (afterEq(endTime, pmStart) && beforeEq(endTime, pmEnd)) {
|
|
|
|
+ // 14:00 - 17:00
|
|
|
|
+ // 上午总时长
|
|
|
|
+ minutes = calcMinutes(amStart, amEnd);
|
|
|
|
+ // 下午请假时长
|
|
|
|
+ minutes += calcMinutes(pmStart, endTime);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else if (afterEq(endTime, pmEnd) && beforeEq(endTime, todayEnd)) {
|
|
|
|
+ // 17:00 - 23:59 当天(言外之意就是请了一整天假)
|
|
|
|
+ minutes = calcMinutes(amStart, amEnd);
|
|
|
|
+ minutes += calcMinutes(pmStart, pmEnd);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else if (endTime.after(todayEnd)) {
|
|
|
|
+ int dayOfStartTime = getDayFromTime(startTime);
|
|
|
|
+ int dayOfEndTime = getDayFromTime(endTime);
|
|
|
|
+ int days = dayOfEndTime - dayOfStartTime;
|
|
|
|
+ // 一整天请假时长
|
|
|
|
+ minutes = getWholeDayLeaveFrom(amStart, amEnd, pmStart, pmEnd);
|
|
|
|
+
|
|
|
|
+ // 规定的第二天上午(或者 第三天及以后)上班时间
|
|
|
|
+ startTime = amStart;
|
|
|
|
+ startTime = addDays(startTime, days);
|
|
|
|
+
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ if (days != 1) {
|
|
|
|
+ minutes += (days - 1) * minutes;
|
|
|
|
+ }
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else if (afterEq(startTime, amStart) && beforeEq(startTime, amEnd)) {
|
|
|
|
+ // startTime 9:00 - 12:00
|
|
|
|
+ // endTime 9:00 - 12:00
|
|
|
|
+ if (afterEq(endTime, amStart) && beforeEq(endTime, amEnd)) {
|
|
|
|
+ return calcMinutes(startTime, endTime);
|
|
|
|
+ // 12:00 - 14:00之间
|
|
|
|
+ } else if (afterEq(endTime, amEnd) && beforeEq(endTime, pmStart)) {
|
|
|
|
+ return calcMinutes(startTime, amEnd);
|
|
|
|
+ } else if (afterEq(endTime, pmStart) && beforeEq(endTime, pmEnd)) {
|
|
|
|
+ // 14:00 - 17:00
|
|
|
|
+ // 上午总时长
|
|
|
|
+ minutes = calcMinutes(startTime, amEnd);
|
|
|
|
+ // 下午请假时长
|
|
|
|
+ minutes += calcMinutes(pmStart, endTime);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else if (afterEq(endTime, pmEnd) && beforeEq(endTime, todayEnd)) {
|
|
|
|
+ // 17:00 - 23:59 当天(言外之意就是请了一整天假)
|
|
|
|
+ minutes = calcMinutes(startTime, amEnd);
|
|
|
|
+ minutes += calcMinutes(pmStart, pmEnd);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else if (endTime.after(todayEnd)) {
|
|
|
|
+ int dayOfStartTime = getDayFromTime(startTime);
|
|
|
|
+ int dayOfEndTime = getDayFromTime(endTime);
|
|
|
|
+ int days = dayOfEndTime - dayOfStartTime;
|
|
|
|
+ // 头一天请假时长
|
|
|
|
+ minutes = getWholeDayLeaveFrom(startTime, amEnd, pmStart, pmEnd);
|
|
|
|
+
|
|
|
|
+ // 规定的第二天上午(或者 第三天及以后)上班时间
|
|
|
|
+ startTime = amStart;
|
|
|
|
+ startTime = addDays(startTime, days);
|
|
|
|
+
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ if (days == 1) {
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else {
|
|
|
|
+ // 一整天请假时长
|
|
|
|
+ minutes += (days - 1) * getWholeDayLeaveFrom(amStart, amEnd, pmStart, pmEnd);
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (afterEq(startTime, amEnd) && beforeEq(startTime, pmStart)) {
|
|
|
|
+ // startTime 12:00 - 14:00
|
|
|
|
+ if (afterEq(endTime, pmStart) && beforeEq(endTime, pmEnd)) {
|
|
|
|
+ // 14:00 - 17:00
|
|
|
|
+ return calcMinutes(pmStart, endTime);
|
|
|
|
+ } else if (afterEq(endTime, pmEnd) && beforeEq(endTime, todayEnd)) {
|
|
|
|
+ // 17:00 - 23:59
|
|
|
|
+ return calcMinutes(pmStart, pmEnd);
|
|
|
|
+ } else if (endTime.after(todayEnd)) {
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ int dayOfStartTime = getDayFromTime(startTime);
|
|
|
|
+ int dayOfEndTime = getDayFromTime(endTime);
|
|
|
|
+ int days = dayOfEndTime - dayOfStartTime;
|
|
|
|
+ // 头一天请假时长
|
|
|
|
+ minutes = getWholeDayLeaveFrom(null, null, pmStart, pmEnd);
|
|
|
|
+
|
|
|
|
+ // 规定的第二天上午(或者 第三天及以后)上班时间
|
|
|
|
+ startTime = amStart;
|
|
|
|
+ startTime = addDays(startTime, days);
|
|
|
|
+
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ if (days == 1) {
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ } else {
|
|
|
|
+ minutes += (days - 1) * getWholeDayLeaveFrom(amStart, amEnd, pmStart, pmEnd);
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (afterEq(startTime, pmStart) && beforeEq(startTime, pmEnd)) {
|
|
|
|
+ // startTime 14:00 - 17:00
|
|
|
|
+ if (afterEq(endTime, pmStart) && beforeEq(endTime, pmEnd)) {
|
|
|
|
+ // 14:00 - 17:00
|
|
|
|
+ return calcMinutes(startTime, endTime);
|
|
|
|
+ } else if (afterEq(endTime, pmEnd) && beforeEq(endTime, todayEnd)) {
|
|
|
|
+ // 17:00 - 23:59
|
|
|
|
+ return calcMinutes(startTime, pmEnd);
|
|
|
|
+ } else if (endTime.after(todayEnd)) {
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ int dayOfStartTime = getDayFromTime(startTime);
|
|
|
|
+ int dayOfEndTime = getDayFromTime(endTime);
|
|
|
|
+ int days = dayOfEndTime - dayOfStartTime;
|
|
|
|
+ // 头一天请假时长
|
|
|
|
+ minutes = getWholeDayLeaveFrom(null, null, startTime, pmEnd);
|
|
|
|
+
|
|
|
|
+ // 规定的第二天上午(或者 第三天及以后)上班时间
|
|
|
|
+ startTime = amStart;
|
|
|
|
+ startTime = addDays(startTime, days);
|
|
|
|
+
|
|
|
|
+ // 请假到第二天
|
|
|
|
+ if (days != 1) {
|
|
|
|
+ minutes += (days - 1) * getWholeDayLeaveFrom(amStart, amEnd, pmStart, pmEnd);
|
|
|
|
+ }
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+ } else if (afterEq(startTime, pmEnd) && beforeEq(startTime, todayEnd)) {
|
|
|
|
+ // startTime 17:00 - 23:59 实际就等于是第二天的上班时间开始算请假时长
|
|
|
|
+ // 规定的第二天上午(或者 第三天及以后)上班时间
|
|
|
|
+ int tomorrowStartTime = getDayFromTime(startTime);
|
|
|
|
+ int dayOfEndTime = getDayFromTime(endTime);
|
|
|
|
+ int days = dayOfEndTime - tomorrowStartTime;
|
|
|
|
+
|
|
|
|
+ if (days == 1) {
|
|
|
|
+ startTime = amStart;
|
|
|
|
+ startTime = addDays(startTime, 1);
|
|
|
|
+ return calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ } else {
|
|
|
|
+ minutes += calcTimes(startTime, endTime, getYearMonthDayFromTime(endTime), rule);
|
|
|
|
+ minutes += (days - 1) * getWholeDayLeaveFrom(amStart, amEnd, pmStart, pmEnd);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static boolean beforeEq(Date one, Date another) {
|
|
|
|
+ return (one.before(another) || one.equals(another));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ public static boolean afterEq(Date one, Date another) {
|
|
|
|
+ return (one.after(another) || one.equals(another));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static String packTimes(long minutes) {
|
|
|
|
+ long hours = minutes / 60;
|
|
|
|
+ long minute = minutes % 60;
|
|
|
|
+ String h = hours + "小时";
|
|
|
|
+ return minute <= 0 ? h : h + minute + "分钟";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static String packRuleTime(String time) {
|
|
|
|
+ String yyyyMmdd = getDate();
|
|
|
|
+ return yyyyMmdd + " " + time + ":00";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static String packRuleTime(String yyyyMmdd, String hour) {
|
|
|
|
+ return yyyyMmdd + " " + hour + ":00";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 功能描述: 2021-11-10 15:15:15 => 10
|
|
|
|
+ *
|
|
|
|
+ * @param time 2021-11-10 15:15:15
|
|
|
|
+ * @return 时间中的日期(day)
|
|
|
|
+ */
|
|
|
|
+ public static int getDayFromTime(Date time) {
|
|
|
|
+ String strTime = dateTime1(time);
|
|
|
|
+ String substring = strTime.substring(8, 10);
|
|
|
|
+ return Integer.parseInt(substring);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 功能描述: (amEnd - amStart) + (pmEnd - pmStart) 总请假时长
|
|
|
|
+ *
|
|
|
|
+ * @param amStart 规定上午上班时间
|
|
|
|
+ * @param amEnd 规定上午下班时间
|
|
|
|
+ * @param pmStart 规定下午上班时间
|
|
|
|
+ * @param pmEnd 规定下午上班时间
|
|
|
|
+ * @return 总请假时长
|
|
|
|
+ */
|
|
|
|
+ public static long getWholeDayLeaveFrom(Date amStart, Date amEnd, Date pmStart, Date pmEnd) {
|
|
|
|
+ long minutes = 0;
|
|
|
|
+ if (amStart != null && amEnd != null) {
|
|
|
|
+ minutes = calcMinutes(amStart, amEnd);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ minutes += calcMinutes(pmStart, pmEnd);
|
|
|
|
+ return minutes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 功能描述: 2021-08-06 16:10:24 => 2021-08-06
|
|
|
|
+ *
|
|
|
|
+ * @param time time 2021-08-06 16:10:24
|
|
|
|
+ * @return 2021-08-06
|
|
|
|
+ */
|
|
|
|
+ public static String getYearMonthDayFromTime(Date time) {
|
|
|
|
+ String strTime = dateTime1(time);
|
|
|
|
+ return strTime.substring(0, 10);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|