JAVA 根据传入的时间和增加的小时(n),跳过法定节假日和工作休息时间获取时间

目录

前言

一、导入每年的法定节假日(我这里入库)

二、创建工具类

1.创建map(用来存放法定节假日)

2.根据传入时间算出跳过法定节假日的时间

3.根据传入时间算出跳过法定节假日和工作日休息时间的时间

总结



前言

        最近写任务遇到个算时间的需求,在此记录一下。根据时间跳过法定节假日算出+1天的时间,根据时间即跳过法定节假日,又跳过工作日休息时间+n小时,算出时间。

一、导入每年的法定节假日(我这里入库)

@Slf4j
@Component
public class StatutoryHolidaysTask {
    @Resource
    private EventService eventService;

    @PostConstruct
    public void initializeHolidays() {
        initializeHolidays(null);
    }

    public void initializeHolidays(LocalDate beginTime) {
        List<StatutoryHolidays> list = statutoryHolidaysMapper.list(beginTime, null);
        if (list == null || list.isEmpty()) {
            syncHoliday();
        }
        DateUtil.clearHolidayList();
        Map<LocalDate, Integer> date = list.stream().collect(Collectors.toMap(StatutoryHolidays::getHolidaysDate, StatutoryHolidays::getHoliday));
        DateUtil.setHolidayList(date);
    }

    @Resource
    private StatutoryHolidaysMapper statutoryHolidaysMapper;

    private static String SYNC_ADDRESS = "https://timor.tech/api/holiday/year/";


     //# 法定节假日定时任务配置
    //syncHolidayDeadline: 0 5 1 28 12 *
    @Scheduled(cron = "${syncHolidayDeadline}")
    public void syncHoliday() {
        syncHoliday(null);
    }

    public void syncHoliday(LocalDate date) {

        log.error("StatutoryHolidaysTask.syncHoliday begin ==== {}", date);
        String url = SYNC_ADDRESS + (date == null ? LocalDate.now().getYear() : date.getYear());
        String result = null;
        try {
            result = HttpClientUtil.get(url, null);
        } catch (Exception e) {
            log.error("StatutoryHolidaysTask.syncHoliday param:{}  error:", url, e);
        }

        if (StringUtils.isBlank(result)) {
            log.error("StatutoryHolidaysTask.syncHoliday result 为空");
            return;
        }

        Map map = JSONObject.parseObject(result, Map.class);
        Integer code = (Integer) map.get("code");
        if (code == 0) {
            JSONObject holidayJson = (JSONObject) map.get("holiday");

            List<HolidayVo> rawInfoList = new ArrayList<>();
            holidayJson.forEach((k, v) -> {
                if (v == null) {
                    return;
                }
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(v);
                HolidayVo holidayRawInfo = JSONUtil.toBean(jsonObject, HolidayVo.class);
                rawInfoList.add(holidayRawInfo);
            });


            // 定义节假日集合
            if (rawInfoList == null || rawInfoList.isEmpty()) {
                log.error("StatutoryHolidaysTask.syncHoliday 节假日为空");
                return;
            }

            List<LocalDate> hasHolidays = new ArrayList<>();
            List<StatutoryHolidays> holidaysList = rawInfoList.stream().map(item -> {
                StatutoryHolidays temp = new StatutoryHolidays();
                temp.setHolidaysDate(LocalDate.parse(item.getDate()));
                temp.setHolidaysYear(temp.getHolidaysDate().getYear());
                temp.setHolidaysMonth(temp.getHolidaysDate().getMonthValue());
                temp.setHolidaysDay(temp.getHolidaysDate().getDayOfMonth());
                temp.setHolidaysName(item.getName());
                temp.setHoliday(Boolean.TRUE.equals(item.getHoliday()) ?
                        CommonConstant.CommonStatusEnum.YES.getCode() : CommonConstant.CommonStatusEnum.NO.getCode());
                hasHolidays.add(temp.getHolidaysDate());
                return temp;
            }).sorted(Comparator.comparing(StatutoryHolidays::getHolidaysDate)).collect(Collectors.toList());

            List<LocalDate> has = CollectionUtils.isEmpty(hasHolidays) ? new ArrayList<>() :
                    statutoryHolidaysMapper.selectHasHolidays(hasHolidays);

            if (!CollectionUtils.isEmpty(has)) {
                holidaysList = holidaysList.stream().filter(item -> !has.contains(item.getHolidaysDate())).collect(Collectors.toList());
            }

            if (!CollectionUtils.isEmpty(holidaysList)) {
                statutoryHolidaysMapper.insertBatch(holidaysList);
            }
        }

        log.error("StatutoryHolidaysTask.syncHoliday end ==== ");

    }
}

二、创建工具类

1.创建map(用来存放法定节假日)

代码如下(示例):

public class DateUtil {

    private static Map<LocalDate, Integer> HOLIDAY_LIST = new HashMap<>();

    public static void setHolidayList(Map<LocalDate, Integer> holidayList) {
        HOLIDAY_LIST = holidayList;
    }
}

2.根据传入时间算出跳过法定节假日的时间

代码如下(示例):

public class DateUtil {
    private static Map<LocalDate, Integer> HOLIDAY_LIST = new HashMap<>();

    public static void setHolidayList(Map<LocalDate, Integer> holidayList) {
        HOLIDAY_LIST = holidayList;
    }

 /**
     * 获取 传入参数 num个工作日后日期
     *
     * @param day 不能为空
     * @param offSetNum 正整数 为之后 负整数为之前
     * @return 获取 传入参数 num个工作日后日期 参数为空 返回当前时间
     */
    public static Date getDaysAfterOffSetTime(Date day, Integer offSetNum) {
        if (day == null || offSetNum == null) {
            return new Date();
        }
        Boolean positiveNumber = NumberUtils.INTEGER_ZERO > offSetNum;
        Date today = day;
        Date tomorrow = null;
        int delay = 1;
        if (positiveNumber) {
            offSetNum = Math.abs(offSetNum);
        }
        //根据需要设置,这个值就是业务需要的n个工作日
        int num = offSetNum;
        while (delay <= num) {
            if (positiveNumber) {
                tomorrow = getYesterday(today);
            } else {
                tomorrow = getTomorrow(today);
            }
            //当前日期+1 即tomorrow,判断是否是周末,都不是则将scheduleActiveDate日期+1,直到循环num次即可
            // 是假期直接跳过; 不是假期: 1.周末,跳过, 2.不是周末,不跳过
            if (!checkHoliday(tomorrow)) {
                delay++;
            }
            today = tomorrow;
        }
        return getEndOfDay(today);
    }

    /**
     * 入参为空 和 不是假期返回 false, 是假期返回 true
     * @param tomorrow
     * @return
     */
    private static boolean checkHoliday(Date tomorrow) {
        if (tomorrow == null) {
            return false;
        }
        LocalDate localDate = tomorrow.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Integer holiday = HOLIDAY_LIST.get(localDate);
        if (holiday == null) {
            // 没有匹配到(不是假期) -> 看周末
            return isWeekend(getFormatDate(tomorrow, DATE_FORMAT_YYYY_MM_DD));

        }
        return CommonConstant.CommonStatusEnum.YES.getCode().equals(holiday);
    }


    /**
     * 获取明天的日期
     *
     * @param date
     * @return
     */
    public static Date getTomorrow(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, +1);
        date = calendar.getTime();
        return date;
    }

    /**
     * 获取昨天的日期
     *
     * @param date
     * @return
     */
    public static Date getYesterday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        date = calendar.getTime();
        return date;
    }

    /**
     *  获取一天结束时间
     * @param date
     * @return
     */
    public static Date getEndOfDay(Date date) {
        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.setTime(date);
        return calendarEnd.getTime();
    }

}

3.根据传入时间算出跳过法定节假日和工作日休息时间的时间

代码如下(示例):

public class DateUtil {
    private static Map<LocalDate, Integer> HOLIDAY_LIST = new HashMap<>();

    public static void setHolidayList(Map<LocalDate, Integer> holidayList) {
        HOLIDAY_LIST = holidayList;
    }

    //这些变量需要设置值
    public static final String WORK_HOURS_START = " 09:00:00";//上班时间
    public static final String WORK_HOURS_END = " 17:00:00";//下班时间
    public static final String NOON_BREAK_START = " 11:30:00";//午休开始时间
    public static final String NOON_BREAK_END = " 14:00:00";//午休结束时间

    /**
     * 根据时间 + n小时 算出跳过法定节假日和作息时间
     * @param date 时间
     * @param hour 几小时
     * @return
     */
    @SneakyThrows
    public static Date getDaysAfterHourSetTime(Date date,Integer hour) {
        Date current = date;
        //指定时间  1小时  单位小时 ,自己根据需求修正
        int zdSec = hour * 60 * 60;
        SimpleDateFormat hm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat hm6 = new SimpleDateFormat("yyyy-MM-dd");


//            TimeDifference morningWorkTime = getDatePoor(hm.parse(startWork), hm.parse(lunchBreak));
//            TimeDifference afternoonWorkTime = getDatePoor(hm.parse(workGoOn), hm.parse(offDuty));

        while (true) {
            String startWork = hm6.format(current) + WORK_HOURS_START;
            String lunchBreak = hm6.format(current) + NOON_BREAK_START;
            String workGoOn = hm6.format(current) + NOON_BREAK_END;
            String offDuty = hm6.format(current) + WORK_HOURS_END;
            //今天是否为节假日
            if (checkHoliday(current)) {
                //是节假日
                String sw = hm6.format(current) + WORK_HOURS_START;
                current = getTomorrow(hm.parse(sw));
            } else {
                if (zdSec <= 0) {
                    break;
                }
                //如果当前时间小于 早上上班时间  把时间初始化到九点半
                if (current.getTime() < hm.parse(startWork).getTime()) {
                    current = hm.parse(startWork);
                    continue;
                }
                //如果时间在上午上班内 就用当前时间 到上午下班时间减掉 是否大于有效时间
                //如果不大于有效时间就直接九点半加上有效时间 如果大于有限时间 就减掉有效时间
                //设置当前时间为下午上班时间
                if (hm.parse(startWork).getTime() <= current.getTime() && current.getTime()
                        <= hm.parse(lunchBreak).getTime()) {
                    TimeDifference datePoor = getDatePoor(current, hm.parse(lunchBreak));
                    if (datePoor.getTotalSec() >= zdSec) {
                        current = addHour(zdSec, current, 2);
                        break;
                    } else {
                        zdSec = zdSec - datePoor.getTotalSec().intValue();
                        current = hm.parse(workGoOn);
                        continue;
                    }
                }


                if (hm.parse(lunchBreak).getTime() < current.getTime() && current.getTime()
                        < hm.parse(workGoOn).getTime()) {
                    //如果时间在午休时候  就让时间变成下午起始时间
                    current = hm.parse(workGoOn);
                }

                //如果时间在下午上班时间 就用当前时间 到下午下班时间减掉有效时间
                if (hm.parse(workGoOn).getTime() <= current.getTime() && current.getTime()
                        <= hm.parse(offDuty).getTime()) {
                    TimeDifference datePoor = getDatePoor(current, hm.parse(offDuty));
                    if (datePoor.getTotalSec() >= zdSec) {
                        current = addHour(zdSec, current, 2);
                        break;
                    } else {
                        zdSec = zdSec - datePoor.getTotalSec().intValue();
                        current = getTomorrow(hm.parse(startWork));
                        continue;
                    }
                }
                //如果时间在下午下班时候 就跳过再次进入循环
                if (current.getTime() > hm.parse(offDuty).getTime()) {
                    current = getTomorrow(hm.parse(startWork));
                    continue;
                }


            }

        }
        System.out.println("计算时间结果" + hm.format(current));
        return current;
    }


    /**
     * 计算两个时间相差天 时 分 秒 总秒数
     * @param endDate
     * @param nowDate
     * @return
     */
    public static TimeDifference getDatePoor(Date endDate, Date nowDate) {

        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = nowDate.getTime()-endDate.getTime() ;
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff % nd % nh % nm / ns;
        Long totalsec=hour*60*60+min*60+sec;
        return new TimeDifference(day, hour, min,sec,totalsec);
    }

    public static Date addHour(int time, Date creatTime, int type) {

        //设置生效时间为一小时后
        Calendar cal = Calendar.getInstance();
        cal.setTime(creatTime);
        switch (type) {
            case 1: {
                cal.add(Calendar.HOUR, time);// 24小时制
            }
            case 3: {
                cal.add(Calendar.MINUTE, time);// 24小时制
            }
            case 2:{
                cal.add(Calendar.SECOND, time);
            }
        }

        Date effectivetime = cal.getTime();
        return effectivetime;
    }

    /**
     * 入参为空 和 不是假期返回 false, 是假期返回 true
     * @param tomorrow
     * @return
     */
    private static boolean checkHoliday(Date tomorrow) {
        if (tomorrow == null) {
            return false;
        }
        LocalDate localDate = tomorrow.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Integer holiday = HOLIDAY_LIST.get(localDate);
        if (holiday == null) {
            // 没有匹配到(不是假期) -> 看周末
            return isWeekend(getFormatDate(tomorrow, DATE_FORMAT_YYYY_MM_DD));

        }
        return CommonConstant.CommonStatusEnum.YES.getCode().equals(holiday);
    }

    /**
     * 获取明天的日期
     *
     * @param date
     * @return
     */
    public static Date getTomorrow(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, +1);
        date = calendar.getTime();
        return date;
    }

public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd";

    /**
     * 判断是否是weekend
     *
     * @param sdate yyyy-MM-dd
     * @return
     */
    public static boolean isWeekend(String sdate) {
        Date date = getFormatDate(sdate, DATE_FORMAT_YYYY_MM_DD);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            return true;
        } else {
            return false;
        }
    }


    public static Date getFormatDate(String dateStr, String template) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            SimpleDateFormat destsmf = new SimpleDateFormat(template);
            return destsmf.parse(dateStr);
        } catch (Exception e) {
            logger.error("格式化日期出错", e);
        }

        return null;
    }


}

总结

以上就是我遇到的计算时间方式,在此记录一下。

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
要根据传入时间增加小时数(n),从工作日历中获取新的时间,你可以按照以下步骤进行操作: 1. 首先,创建一个工作日历,包含工作日和非工作日的定义。你可以使用一个预定义的工作日历,或者从数据库或API中获取相关数据来进行定义。 2. 接下来,使用一个循环来增加小时数(n)到给定的时间,同时在每次增加小时之前检查该时间是否是工作日。如果是非工作日,则跳过时间并继续增加下一个小时。 3. 最后,返回计算后的时间。 下面是一个简单的示例代码,用于说明这个过程: ```java import java.time.DayOfWeek; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; public class SkipNonWorkingDays { public static void main(String[] args) { LocalDateTime startTime = LocalDateTime.now(); // 传入时间 int hoursToAdd = 5; // 增加小时数 LocalDateTime newTime = skipNonWorkingDays(startTime, hoursToAdd); System.out.println("新时间: " + newTime); } public static LocalDateTime skipNonWorkingDays(LocalDateTime startTime, int hoursToAdd) { LocalDateTime newTime = startTime; int addedHours = 0; while (addedHours < hoursToAdd) { newTime = newTime.plusHours(1); // 检查新时间是否是工作日 if (isWorkingDay(newTime)) { addedHours++; } } return newTime; } public static boolean isWorkingDay(LocalDateTime dateTime) { DayOfWeek dayOfWeek = dateTime.getDayOfWeek(); // 根据星期几判断是否为工作日 return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; } } ``` 请注意,这只是一个简单的示例代码,你需要根据你的实际需求进行适当的修改和扩展。例如,你可以根据具体的工作日历定义来判断工作日,或者使用更复杂的算法来处理跳过时间

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值