1. Preface
I have encountered a problem at work recently. There is a timed task in the backend. I need to use JAVA to judge the statutory holidays, weekend holidays, work, etc. every day. In fact, it is basically impossible to judge the statutory holidays of China through logic alone, because the holidays in the country may be different every year and are set by artificially;
So you can only rely on other means, and the more reliable ones you can think of are as follows:
1. Network interface: Some data service providers will provide it, either for the charge, or for the limit of the number of times, etc. The effect is not ideal and the controllability is poor. I have never tried it, such as:
https://www.juhe.cn/docs/api/id/177/aid/601
or
http://apistore.baidu.com/apiworks/servicedetail/1116.html
2. Analyze web page information online and obtain holiday situations: rely heavily on the parsed website web pages, so when selecting a website, you should find a slightly more reliable one;
3. According to the national regulations on statutory holidays, enter the system every year, if customers are not afraid of trouble. Still relatively reliable;
This demo will choose the second one to implement;
2. Use htmlunit to analyze web page information online to obtain holiday situations
At the beginning, I used jsoup to parse web pages, but the effect was not ideal. If the web page was generated dynamically, I encountered various problems with jsoup, so I changed it to htmlunit. In general, htmlunit is still very powerful, can simulate the browser's operation, and is known as the open source implementation of java browsers;
First, go to the official website to download the relevant jar packages and read the relevant documents:
http://htmlunit.sourceforge.net/
The web page I am analyzing here is a 3.6 million perpetual calendar:
http://hao.360.cn/rili/
The calendar interface is as follows:
The parsed HTML format is as follows:
Implementation steps:
1. Load the page;
2. Loop to wait for the page to load (there may be some dynamic pages, generated using javascript);
3. Parses html content according to the web page format and extracts key information and stores it into the encapsulated object;
Note:
1. The difficulty lies in determining whether to take a vacation and the type of vacation. Since the original page does not indicate the type of vacation for each day, the logic here needs to be implemented by yourself. Please refer to the code for details;
2. The reason for a static latestVocationName variable is to prevent the following situations (the probability of this situation is extremely low; PS: The method must be called once a day before the variable takes effect):
Code implementation:
Define a Chinese date class:
package com.pichen.tools.getDate;import java.util.Date;public class ChinaDate {/*** Gregorian time*/private Date solarDate;/*** Lunar day*/private String lunar;/*** Gregorian day*/private String solar;/*** Whether it is a holiday*/private boolean isVacation = false;/*** If it is a holiday name*/private String VacationName = "non-vacation";/*** Whether it is a class*/private boolean isWorkFlag = false;private boolean isSaturday = false;private boolean isSunday = false;/*** @return the solarDate*/public Date getSolarDate() {return solarDate;}/*** @param solarDate the solarDate to set*/public void setSolarDate(Date solarDate) {this.solarDate = solarDate;}/*** @return the lunar*/public String getLunar() {return lunar;}/*** @param lunar the lunar to set*/public void setLunar(String lunar) {this.lunar = lunar;}/*** @return the solar*/public String getSolar() {return solar;}/*** @param solar the solar to set*/public void setSolar(String solar) {this.solar = solar;}/*** @return the isVacation*/public boolean isVacation() {return isVacation;}/*** @param isVacation the isVacation to set*/public void setVacation(boolean isVacation) {this.isVacation = isVacation;}/*** @return the vacationName*/public String getVacationName() {return VacationName;}/*** @param vacationName the vacationName to set*/public void setVacationName(String vacationName) {VacationName = vacationName;}/*** @return the isWorkFlag*/public boolean isWorkFlag() {return isWorkFlag;}/*** @param isWorkFlag the isWorkFlag to set*/public void setWorkFlag(boolean isWorkFlag) {this.isWorkFlag = isWorkFlag;}/*** @return the isSaturday*/public boolean isSaturday() {return isSaturday;}/*** @param isSaturday the isSaturday to set*/public void setSaturday(boolean isSaturday) {this.isSaturday = isSaturday;}/*** @return the isSunday*/public boolean isSunday() {return isSunday;}/*** @param isSunday the isSunday to set*/public void setSunday(boolean isSunday) {this.isSunday = isSunday;}} Parses the web page, and calls demo, prints the details of this month, and the details of the day:
package com.pichen.tools.getDate;import java.io.IOException;import java.net.MalformedURLException;import java.text.DateFormat;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;import com.gargoylesoftware.htmlunit.WebClient;import com.gargoylesoftware.htmlunit.html.DomNodeList;import com.gargoylesoftware.htmlunit.html.HtmlElement;import com.gargoylesoftware.htmlunit.html.HtmlPage;public class Main {private static String latest VocationName="";public String getVocationName(DomNodeList<HtmlElement> htmlElements, String date) throws ParseException{String rst = "";boolean pastTimeFlag = false;DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");Date paramDate = dateFormat.parse(date);if(new Date().getTime() >= paramDate.getTime()){pastTimeFlag = true;}//first step //jugde if can get vocation name from html pagefor(int i = 0; i < htmlElements.size(); i++){HtmlElement element = htmlElements.get(i);if(element.getAttribute("class").indexOf("vacation")!=-1){boolean hitFlag = false;String voteName = "";for(; i < htmlElements.size(); i++){HtmlElement elementTmp = htmlElements.get(i);String liDate = elementTmp.getAttribute("date");List<HtmlElement> lunar = elementTmp.getElementsByAttribute("span", "class", "lunar");String lanarText = lunar.get(0).asText();if(lanarText.equals("New Year's Day")){voationName = "New Year's Day";}else if(lanarText.equals("New Year's Eve")||lanarText.equals("Spring Festival")){voationName = "Spring Festival";}else if(lanarText.equals("Qingming")){voationName = "Spring Festival";}else if(lanarText.equals("International Labor Day")){voationName = "Spring Festival";}else if(lanarText.equals("Dragon Boat Festival")){voationName = "Dragon Boat Festival";}else if(lanarText.equals("Mid-Autumn Festival")){voationName = "Mid-Autumn Festival";}else if(lanarText.equals("National Day")){voationName = "National Day";}if(liDate.equals(date)){hitFlag = true;}if(elementTmp.getAttribute("class").indexOf("vacation")==-1){break;}}if(hitFlag == true && !voationName.equals("")){rst = voationName;break;}}else{continue;}}//if first step fail(rarely), get from the latest Vocation nameif(rst.equals("")){System.out.println("warning: fail to get vocation name from html page.");//you can judge by some simple rule //from the latest Vocation namersst = Main.latestVocationName;}else if(pastTimeFlag == true){//Update "Current time, and the most recent visible holiday name Main.latestVocationName = rst;}return rst;}public List<ChinaDate> getCurrentDateInfo(){WebClient webClient = null;List<ChinaDate> dateList = null;try{DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");dateList = new ArrayList<ChinaDate>();webClient = new WebClient();HtmlPage page = webClient.getPage("http://hao.360.cn/rili/");//Wait for(int k = 0; k < 60; k++){if(!page.getElementById("M-dates").asText().equals("")) break;Thread.sleep(1000);}//Sleep for 8 seconds, waiting for the page to load..., Sometimes, the page may not be retrieved, unstable() //Thread.sleep(8000); DomNodeList<HtmlElement> htmlElements = page.getElementById("M-dates").getElementsByTagName("li");//System.out.println(htmlElements.size()); for(HtmlElement element: htmlElements){ChinaDate ChinaDate = new ChinaDate();List<HtmlElement> lunar = element.getElementsByAttribute("span", "class", "lunar");List<HtmlElement> solar = element.getElementsByAttribute("div", "class", "solar");chinaDate.setLunar(lunar.get(0).asText());chinaDate.setSolar(solar.get(0).asText());chinaDate.setSolarDate(dateFormat.parse(element.getAttribute("date")));if(element.getAttribute("class").indexOf("vacation")!=-1){chinaDate.setVacation(true);chinaDate.setVacationName(this.getVocationName(htmlElements, element.getAttribute("date")));}if(element.getAttribute("class").indexOf("weekend")!=-1 && element.getAttribute("class").indexOf("last")==-1){chinaDate.setSaturday(true);}if(element.getAttribute("class").indexOf("last weekend")!=-1){chinaDate.setSunday(true);}if(element.getAttribute("class").indexOf("work")!=-1){chinaDate.setWorkFlag(true);}else if(chinaDate.isSaturday() == false &&chinaDate.isSunday() == false && chinaDate.isVacation() == false ){chinaDate.setWorkFlag(true);}else{chinaDate.setWorkFlag(false);}dateList.add(chinaDate);}}catch(Exception e){e.printStackTrace();System.out.println("get date from http://hao.360.cn/rili/ error~");} finally{webClient.close();}return dateList;}public ChinaDate getTodayInfo(){List<ChinaDate> dateList = this.getCurrentDateInfo();DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");for(ChinaDate date: dateList){if(dateFormat.format(date.getSolarDate()).equals(dateFormat.format(new Date()))){return date;}}return new ChinaDate();}public static void main(String[] args) throws FailingHttpStatusCodeException, MalformedURLException, IOException, InterruptedException {List<ChinaDate> dateList = new Main().getCurrentDateInfo();ChinaDate today = new Main().getTodayInfo();DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");System.out.println("Details of this month:");for(ChinaDate date: dateList){System.out.println(dateFormat.format(date.getSolarDate()) + " " + date.getVacationName());}System.out.println("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- today.getSolarDate());System.out.println("Lunar: "+today.getLunar());System.out.println("Gregorian calendar: "+today.getSolar());System.out.println("Holiday name: "+today.getVacationName());System.out.println("Saturday: "+tod ay.isSaturday());System.out.println("Is Sunday: "+today.isSunday());System.out.println("Is on vacation: "+today.isVacation());System.out.println("Is working day: "+today.isWorkFlag());System.out.println("Latest holiday that has occurred:" + Main.latestVocationName);}} Run the program and the result is correct: