您现在的位置是:首页 > 技术教程 正文

Java 实现自动获取法定节假日

admin 阅读: 2024-03-25
后台-插件-广告管理-内容页头部广告(手机)

一、背景

在实现业务需求的过程中,遇到了需要计算 x 个工作日后的日期需求。由于工作日是每年国务院发布的,调休和休假都没有规律,所以无法使用算法进行计算。

一般的实现方案是自己维护一个工作日和调休的表,或者去爬取国务院发布的数据。但前者实现起来麻烦,每年都得搞一遍;后者可能涉及法律风险,爬虫的识别策略也不太可靠。

所以还是考虑使用由专人维护的接口,找到了天行数据的接口,个人用户有10个免费接口的额度,每个接口每天限制调用100次。

因为节假日一旦定下来就不会轻易改变,所以可以把获取到的数据存在本地,这样每天100次的接口额度完全够用,不需要进行付费。

二、技术实现方案

整体流程:
  1. 读取节假日配置:从本地文件中读取节假日,如果本地没有文件,则调用天行接口获取。
  2. 解析数据:从天行返回的数据里,获取该年份里需要调休的日期和补班的日期。
  3. 计算日期:循环获取日期,判断是否为工作日,计算x个工作日后的日期。
实现细节:
  1. 文件名:保存下来的文件,名字里要包含特定的年份。
  2. 计算逻辑:计算日期的时候,需要考虑到跨年的情况,跨年需要重新获取下一年的数据,再继续进行计算日期。
  3. 日期判断:工作日=不休假的周一至周五+补班的周六周末。

三、详细代码

Java 代码

主要有五个类,HolidayResponse 是封装天行API的返回结果;TianApiProperties 是获取天行API的key;TianApiHolidayService 是接口;TianApiHolidayServiceImpl 里是具体实现;HttpConnector 是接口请求,这个换成任何一个能发起http请求的库都行。

目前代码是基于SpringBoot写的,但纯粹只是为了方便,实际是可以转成纯Java工具代码,不依赖于SpringBoot。

HolidayResponse.java

  1. import com.fasterxml.jackson.annotation.JsonProperty;
  2. import lombok.Data;
  3. import java.util.List;
  4. /**
  5. * @author jing
  6. * @version 1.0
  7. * @desc 返回结果
  8. * @date 2023/12/19 11:40
  9. **/
  10. @Data
  11. public class HolidayResponse {
  12. @JsonProperty("code")
  13. private int code; // 公共参数 - 状态码
  14. @JsonProperty("msg")
  15. private String msg; // 公共参数 - 错误信息
  16. @JsonProperty("result")
  17. private Result result; // 公共参数 - 返回结果集
  18. // Getters and setters
  19. /**
  20. * Represents the result section of the response.
  21. */
  22. @Data
  23. public static class Result {
  24. @JsonProperty("update")
  25. private boolean update; // 公共参数 - 是否更新法定节假日
  26. @JsonProperty("list")
  27. private List list; // 应用参数 - 节假日列表
  28. // Getters and setters
  29. }
  30. /**
  31. * Represents an item in the list of holidays.
  32. */
  33. @Data
  34. public static class HolidayItem {
  35. @JsonProperty("holiday")
  36. private String holiday; // 应用参数 - 节日日期
  37. @JsonProperty("name")
  38. private String name; // 应用参数 - 节假日名称(中文)
  39. @JsonProperty("vacation")
  40. private String vacation; // 应用参数 - 节假日数组
  41. @JsonProperty("remark")
  42. private String remark; // 应用参数 - 调休日数组
  43. @JsonProperty("wage")
  44. private String wage; // 应用参数 - 薪资法定倍数/按年查询时为具体日期
  45. @JsonProperty("start")
  46. private int start; // 应用参数 - 假期起点计数
  47. @JsonProperty("now")
  48. private int now; // 应用参数 - 假期当前计数
  49. @JsonProperty("end")
  50. private int end; // 应用参数 - 假期终点计数
  51. @JsonProperty("tip")
  52. private String tip; // 应用参数 - 放假提示
  53. @JsonProperty("rest")
  54. private String rest; // 应用参数 - 拼假建议
  55. }
  56. }

TianApiProperties.java

  1. import lombok.Data;
  2. import org.springframework.boot.context.properties.ConfigurationProperties;
  3. import org.springframework.stereotype.Component;
  4. /**
  5. * @author jing
  6. * @version 1.0
  7. * @desc 配置
  8. * @date 2023/12/19 11:25
  9. **/
  10. @Component
  11. @Data
  12. @ConfigurationProperties(prefix = "tianapi")
  13. public class TianApiProperties {
  14. /**
  15. * 天行数据凭证key
  16. */
  17. private String key;
  18. }

TianApiHolidayService.java

  1. import org.springframework.stereotype.Service;
  2. import java.io.IOException;
  3. import java.time.LocalDateTime;
  4. /**
  5. * @author jing
  6. * @version 1.0
  7. * @desc 天行接口获取节假日,目前使用的是免费接口,每天只能调用100次,后续如果需要调用更多次数,可以考虑购买付费接口。只能获取到今年和明年的节假日,明年的节假日需要在今年11月份左右才能获取到
  8. * @date 2023/12/19 11:25
  9. **/
  10. @Service
  11. public interface TianApiHolidayService {
  12. /**
  13. * 计算x个工作日后的日期,跳过节假日
  14. *
  15. * @param startTime 开始日期
  16. * @param workdaysToAdd 需要跳过的工作日天数
  17. */
  18. LocalDateTime jumpWorkDay(LocalDateTime startTime, int workdaysToAdd) throws IOException;
  19. }

TianApiHolidayServiceImpl.java (核心逻辑)

  1. import cn.hutool.core.date.DateUtil;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.google.gson.Gson;
  4. import com.xxx.app.common.library.holiday.domain.HolidayResponse;
  5. import com.xxx.app.common.library.holiday.properties.TianApiProperties;
  6. import com.xxx.app.common.utils.http.HttpConnector;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.apache.commons.lang3.StringUtils;
  9. import org.springframework.stereotype.Service;
  10. import javax.annotation.Resource;
  11. import java.io.FileInputStream;
  12. import java.io.FileOutputStream;
  13. import java.io.IOException;
  14. import java.nio.file.FileSystems;
  15. import java.nio.file.Files;
  16. import java.nio.file.Path;
  17. import java.time.DayOfWeek;
  18. import java.time.LocalDate;
  19. import java.time.LocalDateTime;
  20. import java.time.LocalTime;
  21. import java.time.format.DateTimeFormatter;
  22. import java.util.ArrayList;
  23. import java.util.HashMap;
  24. import java.util.List;
  25. import java.util.Map;
  26. /**
  27. * @author jing
  28. * @version 1.0
  29. * @desc 天行接口获取节假日,目前使用的是免费接口,每天只能调用100次,后续如果需要调用更多次数,可以考虑购买付费接口。只能获取到今年和明年的节假日,明年的节假日需要在今年11月份左右才能获取到
  30. * @date 2023/12/19 11:25
  31. **/
  32. @Slf4j
  33. @Service
  34. public class TianApiHolidayServiceImpl implements TianApiHolidayService {
  35. @Resource
  36. private TianApiProperties tianApiProperties;
  37. @Resource
  38. private HttpConnector httpConnector;
  39. private final String FILE_FORMAT = "./.holiday/%s_holiday.json";
  40. /**
  41. * 计算x个工作日后的日期,跳过节假日
  42. *
  43. * @param startTime 开始日期
  44. * @param workdaysToAdd 需要跳过的工作日天数
  45. */
  46. public LocalDateTime jumpWorkDay(LocalDateTime startTime, int workdaysToAdd) throws IOException {
  47. // 从文件中读取节假日
  48. HolidayResponse response = getHolidayConfig(startTime);
  49. if (response == null) {
  50. return null;
  51. }
  52. // 节假日,只算周一到周五的
  53. List vacationList = new ArrayList<>();
  54. // 补班列表,表示周末补班的
  55. List workDayList = new ArrayList<>();
  56. extracted(response, vacationList, workDayList);
  57. return workDayAdd(startTime, workdaysToAdd, vacationList, workDayList);
  58. }
  59. /**
  60. * 提取返回数据里的节假日和调休列表
  61. *
  62. * @param response 返回数据
  63. * @param vacationList 节假日列表
  64. * @param workDayList 补班列表
  65. */
  66. private static void extracted(HolidayResponse response, List vacationList, List workDayList) {
  67. // 节假日列表
  68. response.getResult().getList().forEach(item -> {
  69. if (StringUtils.isNotEmpty(item.getWage())) {
  70. String[] vList = item.getVacation().split("\\|");
  71. for (String wage : vList) {
  72. // 不需要上班的工作日
  73. vacationList.add(LocalDate.parse(wage, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
  74. }
  75. }
  76. if (StringUtils.isNotEmpty(item.getRemark())) {
  77. String[] workList = item.getRemark().split("\\|");
  78. for (String work : workList) {
  79. // 需要上班的周末
  80. workDayList.add(LocalDate.parse(work, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
  81. }
  82. }
  83. });
  84. }
  85. /**
  86. * 添加工作日
  87. *
  88. * @param startTime 开始时间
  89. * @param workdaysToAdd 需要添加的工作日天数
  90. * @param vacationList 节假日列表
  91. * @param workDayList 补班列表
  92. * @return LocalDateTime 返回添加工作日后的时间
  93. * @throws IOException 异常
  94. */
  95. private LocalDateTime workDayAdd(LocalDateTime startTime, int workdaysToAdd, List vacationList, List workDayList) throws IOException {
  96. LocalDateTime result = startTime;
  97. // 今年最后一天
  98. LocalDateTime lastDayOfYear = LocalDateTime.of(LocalDate.of(startTime.getYear(), 12, 31), LocalTime.MAX);
  99. // 循环计算,直到工作日天数为0,或者到了今年最后一天
  100. while (workdaysToAdd > 0 && result.isBefore(lastDayOfYear)) {
  101. // 判断周一到周五,是否会放假,周六周日是否会补班
  102. result = result.plusDays(1);
  103. if (workDayNeedToWork(vacationList, result) && holidayNeedToWork(workDayList, result)) {
  104. workdaysToAdd--;
  105. }
  106. }
  107. // 如果还有剩余的工作日,就继续往后推
  108. if (workdaysToAdd > 0) {
  109. // 如果还有剩余的工作日,就继续往后推
  110. return jumpWorkDay(result, workdaysToAdd);
  111. }
  112. return result;
  113. }
  114. /**
  115. * 工作日需要去上班
  116. *
  117. * @param vacationList 节假日列表
  118. * @param date 日期
  119. * @return boolean 工作日是否需要上班
  120. */
  121. private boolean workDayNeedToWork(List vacationList, LocalDateTime date) {
  122. DayOfWeek dayOfWeek = date.getDayOfWeek();
  123. boolean isWork = dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
  124. if (isWork) {
  125. // 如果是工作日,还需要判断是否会放假
  126. LocalDate localDate = LocalDate.from(date);
  127. return !vacationList.contains(localDate);
  128. }
  129. return true;
  130. }
  131. /**
  132. * 周六末需要去补班
  133. *
  134. * @param workDayList 补班列表
  135. * @param date 日期
  136. * @return boolean 是否为休息日
  137. */
  138. private boolean holidayNeedToWork(List workDayList, LocalDateTime date) {
  139. DayOfWeek dayOfWeek = date.getDayOfWeek();
  140. boolean isHoliday = dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY;
  141. if (isHoliday) {
  142. // 如果是节假日,还需要判断是否是补班
  143. LocalDate localDate = LocalDate.from(date);
  144. return workDayList.contains(localDate);
  145. }
  146. return true;
  147. }
  148. /**
  149. * 获取某个日期所在年份的节假日配置数据,注:节假日指来自官方发布的有假节日,每年底政府公布后同步更新
  150. *
  151. * @param date 日期
  152. * @return boolean
  153. */
  154. public HolidayResponse getHolidayConfig(LocalDateTime date) throws IOException {
  155. // 节假日文件路径
  156. String savePath = String.format(FILE_FORMAT, DateUtil.format(date, "yyyy"));
  157. try {
  158. // 从文件中读取节假日
  159. HolidayResponse response = readJsonFromFile(savePath);
  160. if (response == null) {
  161. String url = "https://apis.tianapi.com/jiejiari/index";
  162. // 获取当年的节假日列表
  163. Map params = new HashMap<>();
  164. params.put("key", tianApiProperties.getKey());
  165. params.put("date", DateUtil.format(date, "yyyy-MM-dd"));
  166. params.put("type", "1");
  167. String formData = httpConnector.fromData(params);
  168. String rspBody = httpConnector.doFormPost(url, formData);
  169. // 将json转换为对象
  170. Gson gson = new Gson();
  171. response = gson.fromJson(rspBody, HolidayResponse.class);
  172. // 将对象写入文件
  173. writeJsonToFile(response, savePath);
  174. }
  175. return response;
  176. } catch (IOException e) {
  177. log.error("Error during holiday configuration retrieval : {} , {}", savePath, e.getMessage());
  178. }
  179. return null;
  180. }
  181. /**
  182. * 将json写入文件
  183. *
  184. * @param jsonObject jsonObject
  185. * @param filePath 文件路径
  186. */
  187. private void writeJsonToFile(HolidayResponse jsonObject, String filePath) {
  188. try {
  189. // Create directory if it doesn't exist
  190. Path parentDirectory = FileSystems.getDefault().getPath(filePath).getParent();
  191. if (parentDirectory != null && !Files.exists(parentDirectory)) {
  192. Files.createDirectories(parentDirectory);
  193. }
  194. try (FileOutputStream fos = new FileOutputStream(filePath)) {
  195. ObjectMapper objectMapper = new ObjectMapper();
  196. objectMapper.writeValue(fos, jsonObject);
  197. log.info("节假日文件写入成功 : {} , {}", filePath, jsonObject);
  198. } catch (Exception e) {
  199. log.error("节假日文件写入失败 : {} , {}", filePath, e.getMessage());
  200. }
  201. } catch (IOException e) {
  202. log.error("Error creating directory structure: {}", e.getMessage());
  203. }
  204. }
  205. /**
  206. * 从文件中读取节假日
  207. *
  208. * @param filePath 文件路径
  209. * @return 节假日
  210. */
  211. private HolidayResponse readJsonFromFile(String filePath) {
  212. try {
  213. // Create directory if it doesn't exist
  214. Path parentDirectory = FileSystems.getDefault().getPath(filePath).getParent();
  215. if (parentDirectory != null && !Files.exists(parentDirectory)) {
  216. Files.createDirectories(parentDirectory);
  217. }
  218. try (FileInputStream fis = new FileInputStream(filePath)) {
  219. ObjectMapper objectMapper = new ObjectMapper();
  220. return objectMapper.readValue(fis, HolidayResponse.class);
  221. } catch (Exception e) {
  222. log.error("节假日文件读取失败 : {} , {}", filePath, e.getMessage());
  223. }
  224. } catch (IOException e) {
  225. log.error("Error creating directory structure: {}", e.getMessage());
  226. }
  227. return null;
  228. }
  229. }

HttpConnector.java  (不重要,只是发起请求,可替换)

  1. package com.xxx.app.common.utils.http;
  2. import lombok.Setter;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.commons.collections.MapUtils;
  5. import org.apache.commons.lang3.StringUtils;
  6. import org.apache.http.*;
  7. import org.apache.http.client.HttpClient;
  8. import org.apache.http.client.methods.HttpGet;
  9. import org.apache.http.client.methods.HttpPost;
  10. import org.apache.http.client.methods.HttpRequestBase;
  11. import org.apache.http.entity.StringEntity;
  12. import org.apache.http.entity.mime.HttpMultipartMode;
  13. import org.apache.http.entity.mime.MultipartEntityBuilder;
  14. import org.apache.http.util.EntityUtils;
  15. import org.springframework.stereotype.Service;
  16. import javax.annotation.Resource;
  17. import java.io.File;
  18. import java.io.IOException;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import java.util.StringJoiner;
  22. /**
  23. * @author Jing
  24. * @desc http 连接工具类
  25. * https json post 请求用 doSSlPostRsp接口
  26. */
  27. @Setter
  28. @Slf4j
  29. @Service
  30. public class HttpConnector {
  31. @Resource
  32. private HttpClient httpClient;
  33. /**
  34. * 转拼接参数
  35. *
  36. * @param url 接口地址
  37. * @param params 参数
  38. * @return 拼接后的参数
  39. */
  40. public String addUrlParam(String url, Map params) {
  41. if (MapUtils.isNotEmpty(params)) {
  42. StringBuilder sb = new StringBuilder(url);
  43. sb.append("?");
  44. for (String key : params.keySet()) {
  45. sb.append(key).append("=").append(params.get(key)).append("&");
  46. }
  47. url = sb.substring(0, sb.length() - 1);
  48. }
  49. return url;
  50. }
  51. /**
  52. * 发送带参数post请求 表单请求头
  53. *
  54. * @param url 接口地址
  55. * @param postJson 传参
  56. * @return 响应数据
  57. */
  58. public String doFormPost(String url, String postJson) throws IOException {
  59. HttpPost httpPost = new HttpPost(url);
  60. if (postJson != null) {
  61. httpPost.setHeader("Accept", "application/json");
  62. httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
  63. httpPost.setEntity(new StringEntity(postJson, Consts.UTF_8));
  64. }
  65. Map headers = new HashMap<>();
  66. return doRequest(headers, httpPost);
  67. }
  68. /**
  69. * 发送带参数post请求 表单请求头
  70. *
  71. * @param url 接口地址
  72. * @param formData 传参
  73. * @return 响应数据
  74. */
  75. public String doFormPost(String url, Map headers, String formData) throws IOException {
  76. HttpPost httpPost = new HttpPost(url);
  77. if (formData != null) {
  78. httpPost.setHeader("Accept", "application/json");
  79. httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
  80. httpPost.setEntity(new StringEntity(formData, Consts.UTF_8));
  81. }
  82. return doRequest(headers, httpPost);
  83. }
  84. /**
  85. * 发送带文件和请求头的post请求
  86. *
  87. * @param url 接口地址
  88. * @param headers 请求头
  89. * @param file 文件
  90. * @param fileName 文件名
  91. * @return 响应数据
  92. */
  93. public String doPost(String url, Map headers, File file, String fileName) throws IOException {
  94. HttpPost httpPost = new HttpPost(url);
  95. if (file != null) {
  96. httpPost.setEntity(assemblyFileEntity(file, fileName));
  97. }
  98. return doRequest(headers, httpPost);
  99. }
  100. /**
  101. * 生成文件请求包
  102. *
  103. * @param file 文件
  104. * @return http 请求体
  105. */
  106. protected HttpEntity assemblyFileEntity(File file, String fileName) {
  107. MultipartEntityBuilder build = MultipartEntityBuilder.create();
  108. build.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
  109. build.addBinaryBody("file", file);
  110. build.addTextBody("filename", StringUtils.isBlank(fileName) ? file.getName() : fileName);
  111. HttpEntity entity = build.build();
  112. return entity;
  113. }
  114. /**
  115. * 发送请求
  116. *
  117. * @param headers 请求头
  118. * @param httpRequest request
  119. * @return 响应数据
  120. */
  121. private String doRequest(Map headers, HttpRequestBase httpRequest) throws IOException {
  122. HttpRspBO rspBO = doRequestRsp(headers, httpRequest);
  123. return rspBO.getBodyStr();
  124. }
  125. /**
  126. * 发送request 请求
  127. *
  128. * @param headers
  129. * @param httpRequest 注意这个方法需要自己关闭
  130. * finally {
  131. * httpRequest.releaseConnection();
  132. * }
  133. * @return 带请求头的响应数据封装
  134. */
  135. private HttpRspBO doRequestRsp(Map headers, HttpRequestBase httpRequest) throws IOException {
  136. if (headers != null) {
  137. for (String key : headers.keySet()) {
  138. httpRequest.addHeader(key, headers.get(key));
  139. }
  140. }
  141. try {
  142. HttpResponse response = httpClient.execute(httpRequest);
  143. int statusCode = response.getStatusLine().getStatusCode();
  144. if (statusCode == HttpStatus.SC_OK) {
  145. HttpRspBO bo = new HttpRspBO();
  146. bo.setBodyStr(getEntity(response));
  147. HashMap map = new HashMap<>();
  148. Header[] rspHeaders = response.getAllHeaders();
  149. int i = 0;
  150. while (i < rspHeaders.length) {
  151. map.put(rspHeaders[i].getName(), rspHeaders[i].getValue());
  152. i++;
  153. }
  154. bo.setHeaders(map);
  155. return bo;
  156. } else {
  157. String entity = getEntity(response);
  158. log.info("result msg " + entity);
  159. throw new FinMgwException("");
  160. }
  161. } finally {
  162. httpRequest.releaseConnection();
  163. }
  164. }
  165. /**
  166. * 解析返回请求体
  167. *
  168. * @param response 返回参数
  169. * @return 字符串类型的请求体
  170. */
  171. public String getEntity(HttpResponse response) throws IOException {
  172. HttpEntity entity = response.getEntity();
  173. if (entity == null) {
  174. throw new FinMgwException(ResultCodeEnum.HTTP_EXECUTE_EX.getCode(),
  175. ResultCodeEnum.HTTP_EXECUTE_EX.getDesc() + ", http response entity is null.");
  176. }
  177. String result;
  178. // 去掉首尾的 ""
  179. result = EntityUtils.toString(entity, Consts.UTF_8);
  180. String delStr = "\"";
  181. if (result.indexOf(delStr) == 0) {
  182. result = result.substring(1);
  183. }
  184. if (result.lastIndexOf(delStr) == result.length() - 1) {
  185. result = result.substring(0, result.length() - 1);
  186. }
  187. return result;
  188. }
  189. /**
  190. * 将参数转换为form data传参
  191. *
  192. * @param param map集合
  193. * @return form data
  194. */
  195. public String fromData(Map param) {
  196. StringJoiner joiner = new StringJoiner("&");
  197. for (Map.Entry map : param.entrySet()) {
  198. String data = String.format("%s=%s", map.getKey(), map.getValue());
  199. joiner.add(data);
  200. }
  201. return joiner.toString();
  202. }
  203. }
 使用示例:

application.yml 配置

  1. # 天行api
  2. tianapi:
  3. # API密钥
  4. key: xxxxxxxxxxxxxxxxxxxxxxxxxxx

demo 代码:

  1. @Slf4j
  2. @Service
  3. public class Demo {
  4. @Resource
  5. private TianApiHolidayService tianApiHolidayService;
  6. public void get(){
  7. LocalDateTime publishTime = LocalDateTime.now()
  8. // 计算五个工作日后的日期
  9. LocalDateTime deadlineTime = tianApiHolidayService.jumpWorkDay(publishTime, 5);
  10. }
  11. }

理论上可以扩展很多方法,比如判断当前是否工作日/节假日,减去x个工作日之类的。但不太想写了,暂时用不着。

四、相关依赖

天行API申请:

节假日API接口 - 天行数据TianAPI

代码依赖:

Java 版本 = 1.8 

Maven 版本 = 3.9.2 

涉及maven依赖版本:

  1. <dependency>
  2. <groupId>org.springframework.bootgroupId>
  3. <artifactId>spring-boot-starterartifactId>
  4. <version>2.3.4.RELEASEversion>
  5. <exclusions>
  6. <exclusion>
  7. <artifactId>log4j-apiartifactId>
  8. <groupId>org.apache.logging.log4jgroupId>
  9. exclusion>
  10. exclusions>
  11. dependency>
  12. <dependency>
  13. <groupId>org.springframework.bootgroupId>
  14. <artifactId>spring-boot-starter-webartifactId>
  15. <version>2.3.4.RELEASE<version>
  16. dependency>
  17. <dependency>
  18. <groupId>org.projectlombokgroupId>
  19. <artifactId>lombokartifactId>
  20. <optional>trueoptional>
  21. <version>1.18.16version>
  22. dependency>
  23. <dependency>
  24. <groupId>cn.hutoolgroupId>
  25. <artifactId>hutool-allartifactId>
  26. <version>5.7.10version>
  27. dependency>
  28. <dependency>
  29. <groupId>com.fasterxml.jackson.coregroupId>
  30. <artifactId>jackson-databindartifactId>
  31. <version>2.10.2version>
  32. dependency>
  33. <dependency>
  34. <groupId>com.google.code.gsongroupId>
  35. <artifactId>gsonartifactId>
  36. <version>2.8.9version>
  37. dependency>

五、补充

附带上2024年的节假日数据,如果只是要判断2024年的,那直接把文件放在项目目录/.holiday 目录下即可,不需要再申请天行的API接口权限。

或者拿这个去调试代码也可以,但需要保证日期范围在2024年内,否则会自动调用天行API接口获取其他年份的数据。

文件名:2024_holiday.json

  1. {
  2. "code": 200,
  3. "msg": "success",
  4. "result": {
  5. "update": true,
  6. "list": [
  7. {
  8. "holiday": "1月1号",
  9. "name": "元旦节",
  10. "vacation": "2023-12-30|2023-12-31|2024-01-01",
  11. "remark": "",
  12. "wage": "2024-01-01",
  13. "start": 0,
  14. "now": 0,
  15. "end": 2,
  16. "tip": "1月1日放假,与周末连休,共三天。",
  17. "rest": "2023年12月28日至12月29日请假2天,与周末连休可拼5天小长假。"
  18. },
  19. {
  20. "holiday": "2月10号",
  21. "name": "春节",
  22. "vacation": "2024-02-10|2024-02-11|2024-02-12|2024-02-13|2024-02-14|2024-02-15|2024-02-16|2024-02-17",
  23. "remark": "2024-02-04|2024-02-18",
  24. "wage": "2024-02-10|2024-02-11|2024-02-12",
  25. "start": 0,
  26. "now": 0,
  27. "end": 7,
  28. "tip": "2月10日至17日放假调休,共8天。2月4日(星期日)、2月18日(星期日)上班。鼓励各单位结合带薪年休假等制度落实,安排职工在除夕(2月9日)休息。",
  29. "rest": "2月8日至2月9日请假2天,与春节连休可拼10天长假。"
  30. },
  31. {
  32. "holiday": "4月4号",
  33. "name": "清明节",
  34. "vacation": "2024-04-04|2024-04-05|2024-04-06",
  35. "remark": "2024-04-07",
  36. "wage": "2024-04-04",
  37. "start": 0,
  38. "now": 0,
  39. "end": 2,
  40. "tip": "4月4日至6日放假调休,共3天。4月7日(星期日)上班。",
  41. "rest": "4月3日和4月7日请假2天,与清明节连休可拼5天小长假。"
  42. },
  43. {
  44. "holiday": "5月1号",
  45. "name": "劳动节",
  46. "vacation": "2024-05-01|2024-05-02|2024-05-03|2024-05-04|2024-05-05",
  47. "remark": "2024-04-28|2024-05-11",
  48. "wage": "2024-05-01",
  49. "start": 0,
  50. "now": 0,
  51. "end": 4,
  52. "tip": "5月1日至5日放假调休,共5天。4月28日(星期日)、5月11日(星期六)上班。",
  53. "rest": "4月28日至4月30日请假3天,周六与劳动节连休可拼9天长假。"
  54. },
  55. {
  56. "holiday": "6月10号",
  57. "name": "端午节",
  58. "vacation": "2024-06-08|2024-06-09|2024-06-10",
  59. "remark": "",
  60. "wage": "2024-06-10",
  61. "start": 0,
  62. "now": 0,
  63. "end": 2,
  64. "tip": "6月10日放假,与周末连休,共3天。",
  65. "rest": "6月6日至6月7日请假2天,与端午节连休可拼5天小长假。"
  66. },
  67. {
  68. "holiday": "9月15号",
  69. "name": "中秋节",
  70. "vacation": "2024-09-15|2024-09-16|2024-09-17",
  71. "remark": "2024-09-14",
  72. "wage": "2024-09-17",
  73. "start": 0,
  74. "now": 0,
  75. "end": 2,
  76. "tip": "9月15日至17日放假调休,共3天。9月14日(星期六)上班。",
  77. "rest": "9月13日至9月14日请假2天,与周日连休可拼5天小长假。"
  78. },
  79. {
  80. "holiday": "10月1号",
  81. "name": "国庆节",
  82. "vacation": "2024-10-01|2024-10-02|2024-10-03|2024-10-04|2024-10-05|2024-10-06|2024-10-07",
  83. "remark": "2024-09-29|2024-10-12",
  84. "wage": "2024-10-01|2024-10-02|2024-10-03",
  85. "start": 0,
  86. "now": 0,
  87. "end": 6,
  88. "tip": "10月1日至7日放假调休,共7天。9月29日(星期日)、10月12日(星期六)上班。",
  89. "rest": "9月29日至9月30号请假2天,周六与国庆节连休可拼10天长假。"
  90. }
  91. ]
  92. }
  93. }

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜