java获取国家法定节假日, 由此可获取每月第一个工作日和最后一个工作日
(不依赖API,主要是因为API接口不可靠或计费,此工具依赖国务院发布的节假日基础信息进行解析)
本工具仅供参考学习。各类数据获取需遵守法律法规
package com.exrate; import cn.hutool.core.util.NumberUtil; import okhttp3.*; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.io.*; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.ConcurrentSkipListSet; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Q */ public class ChinaHolidaysUtils { /** * 国务院发布的节假日安排的通知 保存的文件路径 */ private static final String HOLIDAY_NOTICES_FILE_PATH = ChinaHolidaysUtils.class.getResource("/").getPath()+"国务院发布的节假日安排的通知/"; /** * 国务院文件搜索地址 */ private static final String GOV_URL = "http://sousuo.gov.cn/s.htm?t=paper&advance=false&n=10&timetype=timeqb&mintime=&maxtime=&sort=pubtime&q=%E8%8A%82%E5%81%87%E6%97%A5%E5%AE%89%E6%8E%92%E7%9A%84%E9%80%9A%E7%9F%A5"; private static SetpublicHolidays = new ConcurrentSkipListSet<>(); private static Set oxenHorseDays = new ConcurrentSkipListSet<>(); public static void main(String[] args) { try { System.out.println(isOxenHorseDays(LocalDate.now().toString())); } catch (IOException e) { e.printStackTrace(); } System.out.println("publicHolidays: " + publicHolidays); System.out.println("oxenHorseDays: " + oxenHorseDays); } /** * 是否为调休补班日 * @param localDate * @return * @throws IOException */ public static boolean isOxenHorseDays(String localDate) throws IOException { if(oxenHorseDays.isEmpty()){ getDays(localDate, publicHolidays, oxenHorseDays); } return oxenHorseDays.contains(localDate); } /** * 是否为法定节假日 * @param localDate * @return * @throws IOException */ public static boolean isPublicHolidays(String localDate) throws IOException { if(publicHolidays.isEmpty()){ getDays(localDate, publicHolidays, oxenHorseDays); } return publicHolidays.contains(localDate); } private static synchronized void getDays(String localDate, Set publicHolidays, Set oxenHorseDays) throws IOException { //获取xxx年的节假日数据 String year = null; if(StringUtils.isEmpty(localDate)){ year = String.valueOf(LocalDate.parse(localDate).getYear()); }else{ year = String.valueOf(LocalDate.now().getYear()); } //先通过缓存文件,否则使用http获取 String html = getHtmlByCacheFiles(year); if(html == null){ html = getHtmlByHttp(year); } Document doc = Jsoup.parse(html); Element content = doc.select("div.b12c.pages_content").first(); Elements paragraphs = content.select("p"); for (Element p : paragraphs) { String text = p.text(); if (text.contains("、") && text.contains(":") && text.contains("。") && text.contains("放假")) { text = text.substring(text.indexOf(":")+1); String[] sentences = text.split("。"); for (String sentence : sentences) { if (sentence.contains("放假")) { String t = sentence.split("放假")[0]; if (t.contains("至")) { String start = t.split("至")[0]; String startDay=null, startMonth=null, startYear=null; if(start.contains("日") || start.contains("月") || start.contains("年")){ startDay = getDigit(start, "日"); startMonth = getDigit(start, "月"); startYear = getDigit(start, "年"); } LocalDate startDate = parseDate(startYear==null?year:startYear, startMonth, startDay); String end = t.split("至")[1]; String endDay=null, endMonth=null, endYear=null; if(end.contains("日") || end.contains("月") || end.contains("年")){ endDay = getDigit(end, "日"); endMonth = getDigit(end, "月"); endYear = getDigit(end, "年"); } LocalDate endDate = parseDate(endYear==null?(startYear==null?year:startYear):endYear, endMonth==null?startMonth:endMonth, endDay); for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) { publicHolidays.add(date.toString()); } } else { String tDay=null, tMonth=null, tYear=null; if(t.contains("日") || t.contains("月") || t.contains("年")){ tDay = getDigit(t, "日"); tMonth = getDigit(t, "月"); tYear = getDigit(t, "年"); } LocalDate date = parseDate(tYear==null? year:tYear, tMonth, tDay); publicHolidays.add(date.toString()); } } if (sentence.contains("上班")) { String t = sentence.split("上班")[0]; if (sentence.contains("、")) { String[] dates = sentence.split("、"); for (String dateStr : dates) { String tDay=null, tMonth=null, tYear=null; if(dateStr.contains("日") || dateStr.contains("月") || dateStr.contains("年")){ tDay = getDigit(dateStr, "日"); tMonth = getDigit(dateStr, "月"); tYear = getDigit(dateStr, "年"); } LocalDate date = parseDate(tYear==null? year:tYear, tMonth, tDay); oxenHorseDays.add(date.toString()); } }else{ String tDay=null, tMonth=null, tYear=null; if(t.contains("日") || t.contains("月") || t.contains("年")){ tDay = getDigit(t, "日"); tMonth = getDigit(t, "月"); tYear = getDigit(t, "年"); } LocalDate date = parseDate(tYear==null? year:tYear, tMonth, tDay); oxenHorseDays.add(date.toString()); } } } } } } /** * 模拟人为操作的参数 * @param url */ private static Request getRequestSetUnifiedHead(String url){ Request.Builder builder = new Request.Builder(); builder.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7") .header("Host", "www.gov.cn") .header("Referer", "http://sousuo.gov.cn/") // .header("Accept-Encoding", "gzip, deflate, br") 造成乱码问题 .header("Accept-Language", "zh-CN,zh;q=0.9") .header("Cache-Control", "max-age=0") .header("Connection", "keep-alive") .header("Sec-Fetch-Dest", "document") .header("Sec-Fetch-Mode", "navigate") .header("Sec-Fetch-Site", "cross-site") .header("Sec-Fetch-User", "?1") .header("Upgrade-Insecure-Requests", "1") .header("sec-ch-ua", "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"") .header("sec-ch-ua-mobile", "?0") .header("sec-ch-ua-platform", "Windows"); return builder.url(url).build(); } /** * http get请求 * @param client * @param url * @return * @throws IOException */ private static String httpGet(OkHttpClient client, String url) throws IOException { Request request = getRequestSetUnifiedHead(url); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) { throw new IOException("获取数据失败:" + url); } String html = response.body().string(); System.out.println("进行了一次http get请求:" + url); return html; } /** * 通过http获取国务院发布xxxx年的节假日安排的通知 * @return * @throws IOException */ private static String getHtmlByHttp(String year) throws IOException { OkHttpClient client = new OkHttpClient(); String html = httpGet(client, GOV_URL); Document doc = Jsoup.parse(html); Elements resList = doc.select("li.res-list"); if (!resList.isEmpty()) { Optional optional = resList.stream().filter(res -> res.text().contains("国务院办公厅关于"+year+"年")).findFirst(); if (!optional.isPresent()) { throw new IOException("未获取到"+ year +"年节假日安排的通知:" + GOV_URL); } Element element = optional.get(); String linkUrl = element.select("a[href]").attr("abs:href"); html = httpGet(client, linkUrl); str2File(html, HOLIDAY_NOTICES_FILE_PATH, year+"节假日安排的通知-源数据", ".html"); Document resDoc = Jsoup.parse(html); str2File(html, HOLIDAY_NOTICES_FILE_PATH, resDoc.title(), ".html"); return html; } return null; } /** * 先通过缓存节假日通知的指定目录中获取 当年的 节假日通知文件 * @param year * @return */ private static String getHtmlByCacheFiles(String year) { String[] paths = new File(HOLIDAY_NOTICES_FILE_PATH).list(); if(paths != null && paths.length > 0){ Optional yearPath = Arrays.stream(paths).filter(p -> p.contains(year)).findFirst(); if (yearPath.isPresent()){ return file2Str(HOLIDAY_NOTICES_FILE_PATH + yearPath.get()); } } return null; } /** * 根据年月日字符转为 yyyy-M-d 格式的LocalDate * @param year * @param month * @param day * @return */ private static LocalDate parseDate(String year, String month, String day) { String dateStr = year + "-" + month + "-" + day; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d"); return LocalDate.parse(dateStr, formatter); } /** * 将字符串内容转为文件存到指定路径下 * @param str * @param filePath */ public static void str2File(String str, String filePath, String fileName, String fileSuffix) throws IOException { File file = new File(filePath + fileName + fileSuffix); if (!file.getParentFile().exists()) { boolean created = file.getParentFile().mkdirs(); if (!created) { throw new IOException("文件路径创建失败"); } } try (FileWriter writer = new FileWriter(file)) { writer.write(str); } catch (IOException e) { e.printStackTrace(); } } /** * 将指定路径的文件转为字符串 * @param filePath * @return */ private static String file2Str(String filePath) { File file = new File(filePath); try (FileReader reader = new FileReader(file)) { char[] buffer = new char[(int) file.length()]; reader.read(buffer); return new String(buffer); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 获取指定字符串前的数字 */ private static final Pattern PATTERN = Pattern.compile("[^\\d]"); private static String getDigit(String content, String targetStr) { if(!content.contains(targetStr)){ return null; } content = content.substring(0, content.indexOf(targetStr)); StringBuffer sb = new StringBuffer(content); content = sb.reverse().toString(); //使用正则表达式匹配第一个非数字 Matcher matcher = PATTERN.matcher(content); if (matcher.find()) { content = content.substring(0, matcher.start()); sb = new StringBuffer(content); return sb.reverse().toString(); } //是否为数字 if(NumberUtil.isNumber(content)){ return new StringBuffer(content).reverse().toString(); } return null; } }
到此这篇关于java获取国家法定节假日的文章就介绍到这了,更多相关内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文地址:https://blog.csdn.net/wshzfansjk/article/details/131513787