前言
工作日就是我们常说的星期一到星期五,休息日就是星期六星期天;而法定节假日的存在打破了这种规律,会出现星期六是法定加班日,而星期一成了节假日。国家每年年底会公布第二年的节假日,由于是描述性文字的方式公布的,所以这些数据还需要通过人工处理,才可以使用。如果想省去每年人工的处理,我们可以直接使用百度的日历API来获取节假日。
实现
从百度API获取下一个月的假期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
public void initMonthHoliday(LocalDate date) {
List<JsonObject> monthHoliday = getMonthHoliday(date);
if (CollectionUtils.isEmpty(monthHoliday)) {
return;
}
Map<Integer, Integer> holiday = new HashMap<>(monthHoliday.size());
for (JsonObject jsonObject : monthHoliday) {
String holidayDate = jsonObject.get("date").getAsString();
LocalDate parse = LocalDate.parse(holidayDate,DateTimeFormatter.ofPattern("yyyy-M-d"));
String dayOfMonth = parse.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//status 1 表示休息日,2 表示加班。
String status = jsonObject.get("status").getAsString();
holiday.put(Integer.valueOf(dayOfMonth), Integer.valueOf(status));
}
chineseHolidayMapper.insertIgnore(holiday);
}
public Map<Integer, Boolean> getHoliday() {
List<Map<String, Integer>> holiday = chineseHolidayMapper.getHoliday();
return holiday.stream().collect(Collectors.toMap(bean -> bean.get("dayOfMonth"), bean -> "1".equals(bean.get("status"))? false : true));
}
/**
*
* 根据百度api,解析假期。
* @date 2019年11月18日 11:17:02
* @author lralin
* @param date
* @return java.util.List<com.google.gson.JsonObject>
* @throws
*/
private List<JsonObject> getMonthHoliday(LocalDate date) {
String url = StringUtils.isBlank(holidayUrl) ? "https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=%s&resource_id=6018" : holidayUrl;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月");
int monthValue = date.getMonthValue();
log.info("日期:{}", date);
JsonParser parser = new JsonParser();
List<JsonObject> holidayList = new ArrayList<>();
try {
String run = OkhttpUtils.run(String.format(url, date.format(formatter)));
log.info(run);
JsonObject parse = parser.parse(run).getAsJsonObject();
JsonObject data = parse.getAsJsonArray("data").get(0).getAsJsonObject();
List<JsonObject> jsonObjectList = new ArrayList<>();
analysisHoliday(data, jsonObjectList);
for (JsonObject aJsonObjectList : jsonObjectList) {
JsonArray list = aJsonObjectList.getAsJsonArray("list");
for (int j = 0; j < list.size(); j++) {
JsonObject listObj = list.get(j).getAsJsonObject();
String s = listObj.get("date").getAsString();
int baiduMonth = Integer.parseInt(s.split("-")[1]);
if ((!holidayList.contains(listObj) && (baiduMonth == monthValue))) {
holidayList.add(listObj);
}
}
}
} catch (IOException e) {
log.error("节假日获取异常", e);
}
return holidayList;
}
/**
*
* 解析holiday字段
* @date 2019年11月19日 08:40:24
* @author lralin
* @param data, jsonObjectList
* @return void
* @throws
*/
private void analysisHoliday(JsonObject data, List<JsonObject> jsonObjectList) {
//百度返回的格式不一样。
getObject(data, jsonObjectList);
getArray(data, jsonObjectList);
}
/**
*
* 返回是对象时的解析
* @date 2019年11月19日 08:41:52
* @author lralin
* @param data, jsonObjectList
* @return void
* @throws
*/
private void getArray(JsonObject data, List<JsonObject> jsonObjectList) {
try {
JsonArray jsonArr;
if ((jsonArr = data.getAsJsonArray("holiday")) != null) {
Iterator<JsonElement> iterator = jsonArr.iterator();
while (iterator.hasNext()) {
jsonObjectList.add(iterator.next().getAsJsonObject());
}
}
} catch (ClassCastException ignored) {
}
}
/**
*
* 返回是数组时的解析
* @date 2019年11月19日 08:41:52
* @author lralin
* @param data, jsonObjectList
* @return void
* @throws
*/
private void getObject(JsonObject data, List<JsonObject> jsonObjectList) {
try {
JsonObject obj;
if ((obj = data.getAsJsonObject("holiday")) != null) {
jsonObjectList.add(obj);
}
} catch (ClassCastException ignored) {
}
}使用定时任务
0 15 23 L * ?
(每月最后一天的23点15分触发 ),在每个月月底执行initMonthHoliday
方法。把日期转换成int,插入到数据库。在知道某个月的所有节假日之后,我们就能进行工作日计算了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
/**
* 工作日加法计算
*
* @author lralin
* @create 2019年11月19日 08:41:52
**/
public class WorkDaysUtils {
private WorkDaysUtils() {
}
/**
* 法定节假日map,true为补休,false为放假
*/
private static final Map<Integer, Boolean> WORKDAY_MAP = new HashMap<>();
/**
* 初始化法定节假日map
* 日期格式为yyyyMMdd,true为补休,false为放假,如果本来就是周末的节假日则不需再设置
*/
public static void initWorkday(Map<Integer, Boolean> workdayMap) {
//存储在数据库中百度API返回的假期数据,来初始化。
WORKDAY_MAP.putAll(workdayMap);
// 2018年的节假日
// WORKDAY_MAP.put(20180101, false);
// WORKDAY_MAP.put(20180211, true);
// WORKDAY_MAP.put(20180215, false);
// WORKDAY_MAP.put(20180216, false);
// WORKDAY_MAP.put(20180219, false);
// WORKDAY_MAP.put(20180220, false);
// WORKDAY_MAP.put(20180221, false);
// WORKDAY_MAP.put(20180224, true);
// WORKDAY_MAP.put(20180405, false);
// WORKDAY_MAP.put(20180406, false);
// WORKDAY_MAP.put(20180408, true);
// WORKDAY_MAP.put(20180428, true);
// WORKDAY_MAP.put(20180430, false);
// WORKDAY_MAP.put(20180501, false);
// WORKDAY_MAP.put(20180618, false);
// WORKDAY_MAP.put(20180924, false);
// WORKDAY_MAP.put(20180929, true);
// WORKDAY_MAP.put(20180930, true);
// WORKDAY_MAP.put(20181001, false);
// WORKDAY_MAP.put(20181002, false);
// WORKDAY_MAP.put(20181003, false);
// WORKDAY_MAP.put(20181004, false);
// WORKDAY_MAP.put(20181005, false);
}
/**
* 获取某日几个工作日之后的日期
*
* @param date, daysNum
* @return java.time.LocalDate
* @throws
* @date 2019年11月18日 15:13:33
* @author lralin
*/
public static LocalDate getDate(LocalDate date, int daysNum) {
int num = 0;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
while (num <= daysNum) {
date = date.plusDays(1);
boolean workDay = isWorkDay(date, formatter.format(date));
if (workDay) {
num++;
}
}
return date;
}
private static boolean isWorkDay(LocalDate date, String dateStr) {
Boolean isWorkDay = WORKDAY_MAP.get(Integer.valueOf(dateStr));
if (isWorkDay != null) {
// 如果在法定节假日map里有记录,则按此判断工作日
return isWorkDay;
} else {
// 如果在法定节假日map里没记录,则按是否为周末判断工作日
DayOfWeek dayOfWeek = date.getDayOfWeek();
return (!DayOfWeek.SATURDAY.equals(dayOfWeek) && !DayOfWeek.SATURDAY.equals(dayOfWeek));
}
}
}