前言
给定开始时间 结束时间 以及指定时间 计算总加班费 节假日计算在内
一站式解决,复制粘贴10分钟做完
准备
首先要明确节假日概念,我们需要一个API来告诉我们那天是节假日,每年12月国家节日办会发布下一年的放假安排。
阅读此文章 先获取节假日
节假日日历API
计算
application.yml
# 节假日 appcode 为密钥 链接每天可以调用100 超过收费
holiday:
url: https://api.topthink.com/calendar/month
appcode: AppCode 官网注册获取 https://docs.topthink.com/think-api/1835086
OvertimePayUtil
package com.picc.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.picc.dao.HolidayArrayMapper;
import com.picc.pojo.Holiday;
import com.picc.wechat.SendWeChatMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Repository;
import org.springframework.web.client.RestTemplate;
import java.util.*;
/**
* 计算司机加班费
* @Author ZhangLe
* @Date 2024/05/14 10:04
*/
@Repository
public class OvertimePayUtil {
//工作时间 注:赶时间就把不需要的费用改为0 需要的写上 不急的话拿着看 慢慢改
private String morningBegin = "07:30";//上午开始时间前 20
private double morningPrice = 20;
private String noonEnd = "12:30";//上午结束时间后 40
private double noonPrice = 40;
private String nightBegin = "22:00";//下午开始时间后 40
private double nightPrice = 40;
private double jiejiariPrice = 100;
@Value("${holiday.url}")
private String holidayUrl;
@Value("${holiday.appcode}")
private String appCode;
@Autowired
private SendWeChatMsg sendWeChatMsg;
@Autowired
private HolidayArrayMapper holidayArrayMapper;
@Autowired
private RestTemplate restTemplate;
/**
*
* @param startTime 2021-01-08 17:39:09 标准时间格式
* @param endTime
* @return
*/
public double OvertimePay(String startTime ,String endTime ){
if(!IFNull.strNotNull(startTime)||!IFNull.strNotNull(endTime)){
return 0;
}
//判断是否符合标准时间格式 自定义
if(startTime.length()!=19||endTime.length()!=19){
return 0;
}
double sum=0;
long day = DateUtil.dateLagByDay(startTime, endTime);
//开始结束 同一天
if(day==0){
sum+= today(startTime,endTime);
}else {
//n-1 天为全天加班费
sum+=(manyday(startTime,endTime));
}
return sum;
}
/**
* 处理同一天订单
* @param startTime 2021-01-08 17:39:09 标准时间格式
* @param endTime 2021-01-08 17:39:09 标准时间格式
* @return
*/
public double today(String startTime,String endTime){
double sum=0;
String[] start = startTime.split(" ");
//发车计算
boolean Sevenoclock = DateUtil.hourMinuteCompare(start[1], morningBegin);
if(Sevenoclock){
sum+=morningPrice;
}
String[] end = endTime.split(" ");
boolean twelve = DateUtil.hourMinuteCompare(end[1], noonEnd);
if(!twelve){
sum+=noonPrice;
}
boolean night = DateUtil.hourMinuteCompare(end[1], nightBegin);
if(!night){
sum+=nightPrice;
}
//查询当天是否为节假日
sum+=dateIfJiejiari(start[0]);
return sum;
}
/**
* 多天计算处理
* @param startTime 2021-01-08 17:39:09 标准时间格式
* @return
*/
public double manyday(String startTime,String endTime){
double sum=0;
sum = dateIfPayPositive(startTime);
sum+=dateIfPayNegative(endTime);
//获取区间内的每一天
List<String> days = DateUtil.handleRangeDate(startTime, endTime);
if(days!=null&&days.size()>0){
int size = days.size();
//三天以上包括三天计算全天加班工资
double dayprice=0;
跳过当天 和最后一天 防止重复计算
if(size>2){
dayprice=morningPrice+noonPrice+nightPrice;
}
sum+=(dayprice*(size-2));
for (int i = 0; i < size; i++) {
sum+=dateIfJiejiari(days.get(i));
}
}
return sum;
}
/**
* 查询当天是否为节假日 或工作日
* @param date
* @return
*/
public double dateIfJiejiari(String date){
double sum=0;
int i = DateUtil.ifDateWeekend(date);
//查询当天是否为节假日
Integer jiejiari = holidayArrayMapper.findHolidayByDate3(date);
if(jiejiari==null){
//工作日上班
if(i==0||i==6){
sum+=jiejiariPrice;
}
}else if(jiejiari==1){
sum+=jiejiariPrice;
}else if(jiejiari==2){
//补班
sum+=(morningPrice+noonPrice+nightPrice);
}
return sum;
}
/**
* 当前日期是否符合加班费条件 正算
* @param date
* @return
*/
public double dateIfPayPositive(String date){
double sum=0;
String[] start = date.split(" ");
//发车计算 按照倒序早中晚执行
boolean Sevenoclock = DateUtil.hourMinuteCompare(start[1], morningBegin);
if(Sevenoclock){
return sum+=(noonPrice+morningPrice+nightPrice);
}
boolean twelve = DateUtil.hourMinuteCompare(start[1], noonEnd);
if(twelve){
return sum+=(noonPrice+nightPrice);
}
boolean night = DateUtil.hourMinuteCompare(start[1], nightBegin);
if(night){
return sum+=nightPrice;
}
return sum;
} /**
* 当前日期是否符合加班费条件 反算
* @param date
* @return
*/
public double dateIfPayNegative(String date){
double sum=0;
String[] start = date.split(" ");
//发车计算 按照倒序晚中早执行
boolean night = DateUtil.hourMinuteCompare(start[1], nightBegin);
if(!night){
return sum+=(noonPrice+morningPrice+nightPrice);
}
boolean twelve = DateUtil.hourMinuteCompare(start[1], noonEnd);
if(!twelve){
return sum+=(noonPrice+morningPrice);
}
//当前时间比中午规定时间小直接放回加班工资 不做校验
return sum+=morningPrice;
}
/**
* 每月更新节假日
*/
public void holiday(){
String ny = DateUtil.getNY();
Map<String, String> map = new HashMap<>();
map.put("yearMonth",ny);
List<Holiday> holidays = new ArrayList<>();
try {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", appCode);
HttpEntity<Map> requestEntity = new HttpEntity<>(map, headers);
String post =restTemplate.postForEntity(holidayUrl,requestEntity,String.class).getBody();
if(!IFNull.strNotNull(post)||!post.contains("\"code\":0")){
return;
}
map.clear();
JSONObject holidayJson = JSON.parseObject(post);
JSONObject data = holidayJson.getJSONObject("data");
List<JSONObject> holiday_array = JSON.parseArray(data.getString("holiday_array"), JSONObject.class);
for (JSONObject holiday : holiday_array) {
List<JSONObject> list = JSON.parseArray(holiday.getString("list"), JSONObject.class);
for (JSONObject jsonObject : list) {
String date = jsonObject.getString("date");
String status = jsonObject.getString("status");
Holiday holiday1 = new Holiday();
if("1".equals(status)){
//节假日日期:名称
holiday1.setHolidayDate(DateUtil.parseDate(date));
holiday1.setDesc(holiday.getString("name"));
holiday1.setStatus(1);
}else {
//调休工作日时间:备注
holiday1.setHolidayDate(DateUtil.parseDate(date));
holiday1.setDesc(holiday.getString("desc"));
holiday1.setStatus(2);
}
int holidayByDate = holidayArrayMapper.findHolidayByDate2(date);
if(holidayByDate==0){
holidays.add(holiday1);
}else {
System.out.println("重复节假日"+holiday1);
}
}
}
} catch (Exception e) {
e.printStackTrace();
return;
}
//存储
if(holidays.size()>0){
int i = holidayArrayMapper.insertHoliday(holidays);
System.out.println(i);
}
}
}
日期工具类
package com.picc.utils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* @Author ZhangLe
* @Date 2020/9/27 15:21
*/
public class DateUtil {
private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static final DateFormat df2 = new SimpleDateFormat("yyyy-MM-dd");
private static final DateFormat df3 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分");
private static final DateFormat df4 = new SimpleDateFormat("yyyy-M");
private static final DateFormat df5= new SimpleDateFormat("yyyy-M-d");
private static final Calendar calendar = Calendar.getInstance();
/**
* 返回当前时间
*
* @return
*/
public static String getTime() {
Date date = new Date();
String format = df.format(date);
return format;
}
/**
* 获取两个时间差值 几天几时几分几秒
*
* @param startTime
* @param endTime
* @return
*/
public static String dateDifference(String startTime, String endTime) {
String str = "";
try {
Date start = df.parse(startTime);
Date end = df.parse(endTime);
//除以1000是为了转换成秒
long between = (end.getTime() - start.getTime()) / 1000;
long day = between / (24 * 3600);
long hour = between % (24 * 3600) / 3600;
long minute = between % 3600 / 60;
long second = between % 60;
System.out.println(between % 60);
str = day + "天" + hour + "小时" + minute + "分" + second + "秒";
} catch (ParseException e) {
e.printStackTrace();
}
return str;
}
/**
* 加天数
*
* @param date
* @param days
* @return
*/
public static String addDays(Date date, int days) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE, days);
return df2.format(cal.getTime());
}
/**
* 转换时间为年月日
*
* @param date
* @return
*/
public static String formatDay(Date date) {
return df2.format(date);
}
/**
* 获取两个时间差值 几天几时几分几秒
*
* @param startTime
* @param endTime
* @return
*/
public static String dateDifferenceByDf2(String startTime, String endTime) {
String str = "";
try {
Date start = df2.parse(startTime);
Date end = df2.parse(endTime);
//除以1000是为了转换成秒
long between = (end.getTime() - start.getTime()) / 1000;
long day = between / (24 * 3600);
long hour = between % (24 * 3600) / 3600;
long minute = between % 3600 / 60;
long second = between % 60;
System.out.println(between % 60);
str = day + "天" + hour + "小时" + minute + "分" + second + "秒";
} catch (ParseException e) {
e.printStackTrace();
}
return str;
}
/**
* 获取两个时间差值 几天
* @param startTime
* @param endTime
* @return
*/
public static long dateLagByDay(String startTime, String endTime) {
String str = "";
try {
Date start = df2.parse(startTime);
Date end = df2.parse(endTime);
//除以1000是为了转换成秒
long between = (end.getTime() - start.getTime()) / 1000;
long day = between / (24 * 3600);
return day;
} catch (ParseException e) {
e.printStackTrace();
}
return 0;
}
/**
* 只獲取年月當前時間
* @return
*/
public static String getNY() {
Date date = new Date();
String format = df4.format(date);
return format;
}
/**
* 比较时分 比较两个值得大小
* @param nowdate 时间
* @param comparedate 比较时间 例如7:30
* @return
*/
public static boolean hourMinuteCompare(String nowdate, String comparedate) {
//确保校验格式
String[] a = nowdate.split(":");
String[] b = comparedate.split(":");
//当前时间时分
int nowdateHour = Integer.parseInt(a[0]);
int nowdateMinute = Integer.parseInt(a[1]);
//比较时间时分
int comparedateHour = Integer.parseInt(b[0]);
int comparedateMinute = Integer.parseInt(b[1]);
if(nowdateHour<comparedateHour){
return true;
}else if(nowdateHour==comparedateHour){
return nowdateMinute<=comparedateMinute;
}
return false;
}
/**
* 日期转换为年月日
* @param startTime
* @return
*/
public static String formatDf(Date startTime) {
String str = "";
try {
str = df3.format(startTime);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
/**
* 查询当天是否为工作日
* @param startTime
* @return
*/
public static int ifDateWeekend(String startTime) {
try {
Calendar calendar =Calendar.getInstance();
calendar.setTime(df2.parse(startTime));
// 0周末 6 周六
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
return dayOfWeek;
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
/** 参考文章:https://blog.csdn.net/weixin_43831204/article/details/108241420
* 查询给定时间范围内的每一天的日期(yyyy-MM-dd HH:mm:ss")
* @param startDateStr 开始时间 (yyyy-MM-dd HH:mm:ss")
* @param endDateStr 结束时间 (yyyy-MM-dd HH:mm:ss")
* @return List<String>
*/
public static List<String> handleRangeDate(String startDateStr, String endDateStr) {
List<String> listDate = new ArrayList<>();
DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter df2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
LocalDateTime startDate = LocalDateTime.parse(startDateStr, df1);
LocalDateTime endDate = LocalDateTime.parse(endDateStr, df1);
LocalDateTime tempDate = null;
while (!(LocalDateTime.of(startDate.plusDays(-1).toLocalDate(), LocalTime.MIN)
.equals(LocalDateTime.of(endDate.toLocalDate(), LocalTime.MIN)))) {
tempDate = startDate;
String format = tempDate.format(df2);
listDate.add(format);
startDate = startDate.plusDays(1);
}
System.out.println(listDate.toString());
return listDate;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 字符串转日期
* @param date
* @return
*/
public static Date parseDate(String date) {
try {
Date parse = df5.parse(date);
return parse;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
/**
* 返回当前时间之前N周 本周 之后N周 的周一周日准确时间
* @param date 当前时间
* @param week 获取上几周就传负数几 下几周就正数+1 举例上周 传 -1 本周传 0 下周传 1
* @return
*/
public static Map<String, String> reMonSun(String date, int week) {
Map<String, String> map = new HashMap();
try {
calendar.setTime(df2.parse(date));
//设置一周第一天是星期一 国外的一周第一天是星期天 默认是按照国外算得
calendar.setFirstDayOfWeek(Calendar.MONDAY);
calendar.add(Calendar.WEEK_OF_MONTH, week);
//查询当前星期几 在本周中 从周日开始算 星期天就是 1 星期一就是2 以此类推
int nowTime = calendar.get(Calendar.DAY_OF_WEEK);
//是1的时候就是星期天 给他赋值8 可以在下边得出负数 用于消减时间 其他状况不做处理
if (nowTime == 1) {
nowTime = 8;
}
calendar.add(Calendar.DATE, calendar.getFirstDayOfWeek() - nowTime);
Date monday = calendar.getTime();
String weekBegin = df.format(monday);
// 此时日期已经是星期一 给当前日期加上6天必然是周末
calendar.add(Calendar.DATE, 6);
Date sundayDate = calendar.getTime();
String weekEnd = df.format(sundayDate);
weekEnd = weekEnd.replace("00:00:00", "23:59:59");
map.put("mondayDate", weekBegin);
map.put("sundayDate", weekEnd);
return map;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 返回当前时间之前N月 本月 之后N月第一天和最后一天
* @param date 当前时间
* @param month 获取上几月就传负数几 下几月就正数+1 举例上月 传 -1 本月传 0 下月传 1
* @return
*/
public static Map<String, String> reOneLast(String date, int month) {
Map<String, String> map = new HashMap();
try {
calendar.setTime(df2.parse(date));
//当前月的上个月
calendar.add(Calendar.MONTH, month);
//设置当前月的最大天数
calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
Date lastDateOfMonth = calendar.getTime();
String lastDay = df2.format(lastDateOfMonth);
//设置一 即为每月第一天
calendar.set(Calendar.DATE, 1);
Date oneDayofMonth = calendar.getTime();
String oneDay = df2.format(oneDayofMonth);
map.put("oneDay", oneDay);
map.put("lastDay", lastDay);
} catch (Exception e) {
throw new RuntimeException(e);
}
return map;
}
/**
* 返回当月最大天数
* @param date 当前时间
* @return
*/
public static int reMonthMaxDay(String date) {
try {
calendar.setTime(df2.parse(date));
} catch (ParseException e) {
e.printStackTrace();
}
int actualMaximum = calendar.getActualMaximum(Calendar.DATE);
return actualMaximum;
}
public static void main(String[] args) {
String date = "2020-11-05 12:11:04";
try {
calendar.setTime(df2.parse(date));
} catch (ParseException e) {
e.printStackTrace();
}
// System.out.println( dateDifference(date,"2020-10-06 10:25:54"));
// System.out.println(reMonSun(date, 0));
// System.out.println(hourMinuteCompare("10:25","7:30"));
// System.out.println(getNY());
// System.out.println(ifDateWeekend("2021-05-14 17:39:09"));
List<String> strings = handleRangeDate("2021-05-09 17:39:09", "2021-05-17 17:39:09");
System.out.println(strings);
}
}