基于Java代码实现判断春节、端午节、中秋节等法定节假日的方法
一、前言
最近工作上遇到一个问题,后端有一个定时任务,需要用java每天判断法定节假日、周末放假,上班等情况,其实想单独通过逻辑什么的去判断中国法定节假日的放假情况,基本不可能,因为国家每一年的假期可能不一样,是人为设定的;
所以只能依靠其它手段,能想到的比较靠谱的如下:
1.网络接口:有些数据服务商会提供,要么是收钱的,要么是次数限制,等等各种问题,效果不理想,可控性差,我也没试过,如:
https://www.juhe.cn/docs/api/id/177/aid/601
或者
2.在线解析网页信息,获取节假日情况:严重依赖被解析的网站网页,所以在选取网站的时候,要找稍微靠谱点的;
3.根据国家规定的法定节假日放假情况,每年录入系统,这种如果客户不怕麻烦的话。还是比较靠谱的;
本demo将选择第二种来实现;
二、使用htmlunit在线解析网页信息,获取节假日情况
一开始是使用jsoup去解析网页的,效果不理想,如果网页是动态生成的时候,用jsoup遇到了各种问题,所以改成了htmlunit,总得来说htmlunit还是很强大的,能够模拟浏览器运行,被誉为java浏览器的开源实现;
首先去官网下载相关jar包,以及阅读相关文档:
我这里解析的网页是360的万年历:
日历界面如下:
被解析的 html格式如下:
实现步骤:
1、加载页面;
2、循环等待页面加载完成(可能会有一些动态页面,是用javascript生成);
3、根据网页格式解析html内容,并提取关键信息存入封装好的对象;
注意点:
1、难点在于判断是否休假及假期类型,由于原页面并没有标明每一天的假期类型,所以这里的逻辑要自己去实现,详情参考代码;
2、之所以有个静态latestvocationname变量,是防止出现以下情况(出现该情况的概率极低;ps:方法要每天调用一次,该变量才生效):
代码实现:
定义一个中国日期类:
package com.pichen.tools.getdate; import java.util.date; public class chinadate { /** * 公历时间 */ private date solardate; /** * 农历日 */ private string lunar; /** * 公历日 */ private string solar; /** * 是否是 休 */ private boolean isvacation = false; /** * 如果是 休情况下的假期名字 */ private string vacationname = "非假期"; /** * 是否是 班 */ 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; } }
解析网页,并调用demo,打印本月详情,和当天详情:
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 latestvocationname=""; 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 page for(int i = 0; i < htmlelements.size(); i++){ htmlelement element = htmlelements.get(i); if(element.getattribute("class").indexof("vacation")!=-1){ boolean hitflag = false; string voationname = ""; 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("元旦")){ voationname = "元旦"; }else if(lanartext.equals("除夕")||lanartext.equals("春节")){ voationname = "春节"; }else if(lanartext.equals("清明")){ voationname = "清明"; }else if(lanartext.equals("国际劳动节")){ voationname = "国际劳动节"; }else if(lanartext.equals("端午节")){ voationname = "端午节"; }else if(lanartext.equals("中秋节")){ voationname = "中秋节"; }else if(lanartext.equals("国庆节")){ voationname = "国庆节"; } 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 name if(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 name rst = main.latestvocationname; }else if(pasttimeflag == true){ //更新《当前时间,且最近一次的可见的假期名 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/"); //最大等待60秒 for(int k = 0; k < 60; k++){ if(!page.getelementbyid("m-dates").astext().equals("")) break; thread.sleep(1000); } //睡了8秒,等待页面加载完成...,有时候,页面可能获取不到,不稳定() //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("本月详情:"); for(chinadate date: datelist){ system.out.println(dateformat.format(date.getsolardate()) + " " + date.getvacationname()); } system.out.println("------------------------------------------------------------------------"); system.out.println("今日详情:"); system.out.println("日期:" + today.getsolardate()); system.out.println("农历:"+today.getlunar()); system.out.println("公历:"+today.getsolar()); system.out.println("假期名:"+today.getvacationname()); system.out.println("是否周六:"+today.issaturday()); system.out.println("是否周日:"+today.issunday()); system.out.println("是否休假:"+today.isvacation()); system.out.println("是否工作日:"+today.isworkflag()); system.out.println("已发生的最近一次假期:" + main.latestvocationname); } }
运行程序,结果正确: