加班费计算(节假日、补班)

前言

给定开始时间 结束时间 以及指定时间 计算总加班费 节假日计算在内
一站式解决,复制粘贴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);


    }


}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值