失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 获取下一个工作日/休息日的方法 本地基础搭建 Springboot 法定节假日/休息日/调休

获取下一个工作日/休息日的方法 本地基础搭建 Springboot 法定节假日/休息日/调休

时间:2021-11-23 23:50:36

相关推荐

获取下一个工作日/休息日的方法 本地基础搭建 Springboot 法定节假日/休息日/调休

场景

我们在一些特殊的业务场景下,想要获取到下一个工作日,这里的工作日指正常的法定工作日(包含调休日),这个需求来源于银联的提现,银联只能在法定工作日才能体现,那么在业务代码里对提现日期必须就是工作日即可,在查询了相关的信息,目前没有稳定的API或者三方付费的稳定API,那么这个需求其实不难处理,自己也可以动手维护一套WorkingHolidayAPI的,那么我就以Springboot简答举例写出重要的环节。


文章目录

场景代码Springboot单元测试原理优化项 总结

代码

关键工具:

import cn.hutool.core.date.DateTime;import cn.hutool.core.date.DateUtil;import cn.hutool.core.date.Week;import java.util.*;import java.util.concurrent.ConcurrentHashMap;public class WorkingHolidayUtil {private static final int DEFAULT_YEAR_DAY = 365;private Map<Integer, WorkingHoliday> whMap;/*** 创建时间*/private Date createTime;/*** 起始日期*/private Date startDay;/****/private int offDay;/*** 权重比例**/private int[] WEIGHT_ARR = {10000, 100, 1};public WorkingHolidayUtil(List<WorkingHolidayEntity> data, Date startDay, int offDay) {if (data.isEmpty()) {throw new RuntimeException("构建参数源不能为空");}if (startDay == null) {throw new RuntimeException("构建参数源起始日期不能为空");}if (offDay <= 0) {throw new RuntimeException("构建参数偏移天数只能为正整数");}this.createTime = new Date();this.startDay = startDay;this.offDay = offDay > DEFAULT_YEAR_DAY * 10 ? DEFAULT_YEAR_DAY * 10 : offDay;this.whMap = new ConcurrentHashMap<>(offDay);buildBaseNode(data);}public WorkingHolidayUtil(List<WorkingHolidayEntity> data, Date startDay) {if (data.isEmpty()) {throw new RuntimeException("构建参数源不能为空");}if (startDay == null) {throw new RuntimeException("构建参数源起始日期不能为空");}this.createTime = new Date();this.startDay = startDay;this.offDay = DEFAULT_YEAR_DAY;this.whMap = new ConcurrentHashMap<>(offDay);buildBaseNode(data);}private boolean buildBaseNode(List<WorkingHolidayEntity> data) {Map<String, WorkingHolidayEntity> dataMap = new HashMap<>(1 << 10);if (!data.isEmpty()) {for (WorkingHolidayEntity whe : data) {dataMap.put(whe.getDayStr(), whe);}}return doBuildBaseNode(dataMap);}private boolean doBuildBaseNode(Map<String, WorkingHolidayEntity> dataMap) {Date curDate = DateUtil.date(startDay);String date = "unknow";int weight = -1;String source = "unknow";int holidayOrWorkingday = -1;WorkingHoliday lastWorkingDay = null;List<WorkingHoliday> lastWorkingDays = new ArrayList<>(DEFAULT_YEAR_DAY);WorkingHoliday lastHolidayDay = null;List<WorkingHoliday> lastHolidayDays = new ArrayList<>(DEFAULT_YEAR_DAY);String remark = "";for (int i = 0; i < offDay; i++) {date = DateUtil.format(curDate, "yyyy-MM-dd");weight = getWeight(curDate);if (!dataMap.isEmpty() && dataMap.containsKey(date)) {WorkingHolidayEntity dbItem = dataMap.get(date);source = "db";holidayOrWorkingday = dbItem.getHolidayOrWorkingday();remark = dbItem.getRemark();} else {Week week = DateUtil.dayOfWeekEnum(curDate);int dayOfWeek = week.getValue();source = "hutool";if (dayOfWeek == 1 || dayOfWeek == 7) {holidayOrWorkingday = 2;} else {holidayOrWorkingday = 3;}remark = week.toChinese();}WorkingHoliday wh = new WorkingHoliday(weight, date, holidayOrWorkingday, source, remark);// 偶休息 奇工作if (holidayOrWorkingday % 2 == 0) {clearArrs(0, lastWorkingDays, weight);if (lastHolidayDay != null) {lastHolidayDay.setNextHolidayDayWeight(weight);}lastHolidayDay = wh;lastHolidayDays.add(lastHolidayDay);} else {clearArrs(1, lastHolidayDays, weight);if (lastWorkingDay != null) {lastWorkingDay.setNextWorkingDayWeight(weight);}lastWorkingDay = wh;lastWorkingDays.add(lastWorkingDay);}whMap.put(weight, wh);curDate = DateUtil.offsetDay(curDate, 1);}return !whMap.isEmpty();}/*** @param holidayOrWorkingday* @param workingHolidays* @param weight*/private void clearArrs(int holidayOrWorkingday, List<WorkingHoliday> workingHolidays, int weight) {if (holidayOrWorkingday == 0) {for (WorkingHoliday e : workingHolidays) {e.setNextHolidayDayWeight(weight);}} else {for (WorkingHoliday e : workingHolidays) {e.setNextWorkingDayWeight(weight);}}workingHolidays.clear();}private int getWeight(Date curDate) {int year = DateUtil.year(curDate);int month = DateUtil.month(curDate) + 1;int day = DateUtil.dayOfMonth(curDate);return WEIGHT_ARR[0] * year + WEIGHT_ARR[1] * month + WEIGHT_ARR[2] * day;}private int getWeight(String curDate) {return getWeight(DateUtil.parse(curDate, "yyyy-MM-dd"));}public WorkingHoliday nextWorkingDay(String curDate) {int weight = getWeight(curDate);if (!whMap.containsKey(weight)) {throw new RuntimeException("数据源不存在当前日期");}WorkingHoliday workingHoliday = whMap.get(weight);while (true) {if (workingHoliday == null) {throw new RuntimeException("目前找不到下一个工作日");}Integer nextWorkingDayWeight = workingHoliday.getNextWorkingDayWeight();if (nextWorkingDayWeight != null) {return whMap.get(nextWorkingDayWeight);} else {String date = workingHoliday.getDate();DateTime dateTime = DateUtil.offsetDay(DateUtil.parse(date, "yyyy-MM-dd"), 1);int nextDayWeight = getWeight(dateTime);workingHoliday = whMap.containsKey(nextDayWeight) ? whMap.get(nextDayWeight) : null;}}}}

模型:

public class WorkingHoliday {/*** 权重*/private int weight;/*** 日期* yyyy-MM-dd*/private String date;/*** 法定工作日/休息日* 0法定休息日* 1法定工作日* 2正常休息日* 3正常工作日* <p>* 偶数休息 奇数工作*/private int holidayOrWorkingday;/*** 来源* db数据库 hutool糊涂*/private String source;/*** 下一个工作日权重*/private Integer nextWorkingDayWeight;/*** 下一个休息日权重*/private Integer nextHolidayDayWeight;private String remark;public WorkingHoliday() {}public WorkingHoliday(int weight, String date, int holidayOrWorkingday, String source, String remark) {this.weight = weight;this.date = date;this.holidayOrWorkingday = holidayOrWorkingday;this.source = source;this.remark = remark;}public Integer getNextWorkingDayWeight() {return nextWorkingDayWeight;}public void setNextWorkingDayWeight(Integer nextWorkingDayWeight) {this.nextWorkingDayWeight = nextWorkingDayWeight;}public Integer getNextHolidayDayWeight() {return nextHolidayDayWeight;}public void setNextHolidayDayWeight(Integer nextHolidayDayWeight) {this.nextHolidayDayWeight = nextHolidayDayWeight;}public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public int getHolidayOrWorkingday() {return holidayOrWorkingday;}public void setHolidayOrWorkingday(int holidayOrWorkingday) {this.holidayOrWorkingday = holidayOrWorkingday;}public String getSource() {return source;}public void setSource(String source) {this.source = source;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}@Overridepublic String toString() {return "WorkingHoliday{" +"weight=" + weight +", date='" + date + '\'' +", holidayOrWorkingday=" + holidayOrWorkingday +", source='" + source + '\'' +", nextWorkingDayWeight=" + nextWorkingDayWeight +", nextHolidayDayWeight=" + nextHolidayDayWeight +", remark='" + remark + '\'' +'}';}}

实体类

package com..mon.entity;import java.io.Serializable;import java.util.Date;public class WorkingHolidayEntity implements Serializable {/*** 日期*/private Date dayStr;/*** 法定工作日/休息日* 0法定休息日* 1法定工作日* 2正常休息日* 3正常工作日** 偶数休息 奇数工作*/private int holidayOrWorkingday;/*** 备注*/private String remark;public Date getDayStr() {return dayStr;}public void setDayStr(Date dayStr) {this.dayStr = dayStr;}public int getHolidayOrWorkingday() {return holidayOrWorkingday;}public void setHolidayOrWorkingday(int holidayOrWorkingday) {this.holidayOrWorkingday = holidayOrWorkingday;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}@Overridepublic String toString() {return "WorkingHolidayEntity{" +"dayStr='" + dayStr + '\'' +", holidayOrWorkingday=" + holidayOrWorkingday +", remark='" + remark + '\'' +'}';}}

业务实现类

@Servicepublic class WorkingHolidayServiceImpl implements IWorkingHolidayService {private WorkingHolidayUtil workingHolidayUtil;private String glCurDate;@Autowiredprivate WorkingHolidayDao workingHolidayDao;@Overridepublic WorkingHoliday nextWorkingDay(String curDate) {if (!curDate.equals(glCurDate) || workingHolidayUtil == null) {synchronized (this) {if (!curDate.equals(glCurDate) || workingHolidayUtil == null) {DateTime dateTime = DateUtil.parse(curDate, "yyyy-MM-dd");List<WorkingHolidayEntity> datas = workingHolidayDao.egYearWorkingHolidays(String.valueOf(dateTime.year()));workingHolidayUtil = new WorkingHolidayUtil(datas, dateTime);glCurDate = curDate;}}}return workingHolidayUtil.nextWorkingDay(curDate);}}

Dao关键SQL语句

<select id="egYearWorkingHolidays" parameterClass="java.lang.String"resultClass="com..mon.entity.WorkingHolidayEntity">SELECTDAY_STR dayStr,HOLIDAY_OR_WORKINGDAY holidayOrWorkingday,REMARK remarkFROM"WORKING_HOLIDAY"WHERESUBSTR( DAY_STR, 0, 4 ) <![CDATA[>= ]]> #year#ORDER BYDAY_STR ASC</select>

DDL表构建(oracle)

CREATE TABLE "WORKING_HOLIDAY" ("DAY_STR" VARCHAR2(10) NOT NULL ENABLE, "HOLIDAY_OR_WORKINGDAY" CHAR(1) NOT NULL ENABLE, "REMARK" VARCHAR2(500))

表数据填充

INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-01', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-02', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-03', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-29', '1', '春节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-30', '1', '春节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-31', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-01', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-02', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-03', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-04', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-05', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-06', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-02', '1', '清明节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-03', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-04', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-05', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-24', '1', '劳动节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-30', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-01', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-02', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-03', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-04', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-07', '1', '劳动节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-03', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-04', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-05', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-10', '0', '中秋节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-11', '0', '中秋节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-12', '0', '中秋节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-01', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-02', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-03', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-04', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-05', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-06', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-07', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-08', '1', '国庆节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-09', '1', '国庆节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-21', '0', '中秋节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-18', '1', '中秋节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-01', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-02', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-03', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-04', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-05', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-06', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-07', '0', '国庆节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-10-09', '1', '国庆节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-26', '1', '国庆节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-01', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-02', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-01-03', '0', '元旦');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-11', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-12', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-13', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-14', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-15', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-16', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-17', '0', '春节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-07', '1', '春节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-02-20', '1', '春节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-03', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-04', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-05', '0', '清明节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-01', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-02', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-03', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-04', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-05', '0', '劳动节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-04-25', '1', '劳动节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-05-08', '1', '劳动节调休');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-12', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-13', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-06-14', '0', '端午节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-19', '0', '中秋节');INSERT INTO "WORKING_HOLIDAY" VALUES ('-09-20', '0', '中秋节');

Springboot单元测试

调用IWorkingHolidayService.nextWorkingDay(curDate) 即可

原理

实现过程也很简单,因为法定节假日法定工作日长时间是稳定不变,在此基础上,我们先通过以数据表为基础,再以hutool为辅助,来完成近365天的所有法定日的标记,通过维护好的线程安全map我们很快就能获取到具体某一日的下一个工作日是哪一天。

优化项

可以将实时获取到数据库数据的操作改为每天一获取最新的根据大部分业务来说固定offDay的长度,并注入到容器中完善其方法,比如下一个休息日等需要的方法

总结

很简单的实现不是么,没有花里胡哨的操作,一起加油

获取下一个工作日/休息日的方法 本地基础搭建 Springboot 法定节假日/休息日/调休日 均可 不用调三方

如果觉得《获取下一个工作日/休息日的方法 本地基础搭建 Springboot 法定节假日/休息日/调休》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。