目录

前言

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

二、创建工具类

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

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

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

总结



前言

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

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

@Slf4j
@Component
public class StatutoryHolidaysTask {@Resourceprivate EventService eventService;@PostConstructpublic 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);}@Resourceprivate 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*/@SneakyThrowspublic 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;}}

总结

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

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

  1. java 跳过法定节假日和双休

    注意:五一假期的5天规则还需要算一下.直接拿过去即可使用 import java.text.ParseException; import java.text.SimpleDateFormat; imp ...

  2. 去除法定节假日以及周末,计算请假时间

    业务需要,不废话,直接说核心. 直接上最佳解决方案,那就是动态的获取国家法定节假日(每年都会更新,可维护性更强).并去除周六周末. 当然,有一种比较low的解决方案就是把当年的法定节假日储存到表中或者 ...

  3. 纽约比加州时间早3个小时

    New York is 3 hours ahead of California, 纽约时间比加州时间早三个小时, but it does not make California slow. 但加州时间 ...

  4. 纽约时间比加州时间早三个小时

    纽约时间比加州时间早三个小时 New York is 3 hours ahead of California, 但加州时间并没有变慢 but it does not make California s ...

  5. EXCEL时间计划顺延,并跳过周末以及法定节假日

    首先请原谅我在CSDN这么神圣的殿堂记录EXCEL: 任务与任务之间的关系是Finish-to-Start (FS) 关系,所以一个任务如果延期,会导致其余所有任务都延期.每次遇到这种情况都需要手动一 ...

  6. 一首火遍美国的小诗《纽约比加州时间早三个小时》

    New York is 3 hours ahead of California, 纽约时间比加州时间早三个小时, but it does not make California slow. 但加州时间 ...

  7. 《纽约比加州时间早3个小时》 | 一首火遍美国的小诗

    New York is 3 hours ahead of California, 纽约时间比加州时间早三个小时, but it does not make California slow. 但加州时间 ...

  8. 【转载】青椒如何“平衡”工作和家庭的时间?——科学网马臻

    已有 18023 次阅读 2014-5-27 23:15 |个人分类:出国回国|系统分类:生活其它 今天上午收到一个读者的评论.当时我正在努力工作中,没时间回复. [3]杜尔登  2014-5-27 ...

  9. centos7下系统日志的时间会比当前时间快8个小时的解决方案

    让我们来看一下,默认状态下日期时间 (1) 输入命令 date查看当前系统时间 linux系统下的默认时间比北京时间快了8小时,这对我们项目的log日志记录的时间非常不友好,当程序有查看特定时间日志需 ...

最新文章

  1. IT男人必学的20大泡妞妙招
  2. 工业4.0:数字化供应链的三个方向
  3. classpath路径(转)
  4. ESP32检测调制激光信号程序优化
  5. 集合嵌套存储和遍历元素的示例
  6. oracle 截取中英文混合_C语言截取中英文混合字符串
  7. 浙江理工大学电信宽带校园网访问添加路由表命令(Windows和Liunx)
  8. centos7 redis5.0以后版本 集群部署示例
  9. Linux学习笔记-消息队列的接收
  10. python开发蠕虫病毒_清除服务器蠕虫病毒
  11. redis中hash类型介绍
  12. Vuex 实战:如何在大规模 Vue 应用中组织 Vuex 代码 | 掘金技术征文
  13. html设置背景颜色以及透明度代码,HTML怎么设置背景颜色透明度?
  14. 2022焊工(初级)操作证考试题库及答案
  15. Override and Overload
  16. 企业间数据竞争规则研究
  17. mumu模拟器命令安装apk
  18. poi-tl导出word;自定义列表序号和表格宽度,表格合并,自定义标题,更新目录
  19. 医学影像工作站程序ProDicom的说明
  20. Google中国产品不断升级改进 继续招聘优秀人才

热门文章

  1. 微信 snsapi_userinfo 失败
  2. [电源系列]二、低成本MOS快速关断电路原理分析
  3. chapter16 性能调优与架构篇-基础理论和工具
  4. vert.x详细介绍,全异步框架
  5. VSTO 学习笔记(十二)自定义公式与Ribbon
  6. 一个非常简单那的蠕虫病毒(转)
  7. openGL编程学习(3):太阳、地球、月亮(含自转和公转)和航天飞机
  8. 武汉市计算机学校报名条件,武汉本地户口上小学报名需要什么证件
  9. 31岁才转行程序员,目前34了,我的经历和一些感受...
  10. NFS服务器的搭建(文件共享)