基于Java代码实现判断春节、端午节、中秋节等法定节假日的方法

一、前言

最近工作上遇到一个问题,后端有一个定时任务,需要用JAVA每天判断法定节假日、周末放假,上班等情况,其实想单独通过逻辑什么的去判断中国法定节假日的放假情况,基本不可能,因为国家每一年的假期可能不一样,是人为设定的;

所以只能依靠其它手段,能想到的比较靠谱的如下:

1.网络接口:有些数据服务商会提供,要么是收钱的,要么是次数限制,等等各种问题,效果不理想,可控性差,我也没试过,如:

https://www.juhe.cn/docs/api/id/177/aid/601

或者

http://apistore.baidu.com/apiworks/servicedetail/1116.html

2.在线解析网页信息,获取节假日情况:严重依赖被解析的网站网页,所以在选取网站的时候,要找稍微靠谱点的;

3.根据国家规定的法定节假日放假情况,每年录入系统,这种如果客户不怕麻烦的话。还是比较靠谱的;

本Demo将选择第二种来实现;

二、使用htmlunit在线解析网页信息,获取节假日情况

一开始是使用jsoup去解析网页的,效果不理想,如果网页是动态生成的时候,用jsoup遇到了各种问题,所以改成了htmlunit,总得来说htmlunit还是很强大的,能够模拟浏览器运行,被誉为java浏览器的开源实现;

首先去官网下载相关jar包,以及阅读相关文档:

http://htmlunit.sourceforge.net/

我这里解析的网页是360的万年历:

http://hao.360.cn/rili/

日历界面如下:

被解析的 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);
}
}

运行程序,结果正确:

(0)

相关推荐

  • 基于Java代码实现判断春节、端午节、中秋节等法定节假日的方法

    一.前言 最近工作上遇到一个问题,后端有一个定时任务,需要用JAVA每天判断法定节假日.周末放假,上班等情况,其实想单独通过逻辑什么的去判断中国法定节假日的放假情况,基本不可能,因为国家每一年的假期可能不一样,是人为设定的: 所以只能依靠其它手段,能想到的比较靠谱的如下: 1.网络接口:有些数据服务商会提供,要么是收钱的,要么是次数限制,等等各种问题,效果不理想,可控性差,我也没试过,如: https://www.juhe.cn/docs/api/id/177/aid/601 或者 http:/

  • 基于Java代码实现游戏服务器生成全局唯一ID的方法汇总

    在服务器系统开发时,为了适应数据大并发的请求,我们往往需要对数据进行异步存储,特别是在做分布式系统时,这个时候就不能等待插入数据库返回了取自动id了,而是需要在插入数据库之前生成一个全局的唯一id,使用全局的唯一id,在游戏服务器中,全局唯一的id可以用于将来合服方便,不会出现键冲突.也可以将来在业务增长的情况下,实现分库分表,比如某一个用户的物品要放在同一个分片内,而这个分片段可能是根据用户id的范围值来确定的,比如用户id大于1000小于100000的用户在一个分片内.目前常用的有以下几种:

  • 基于Java代码实现支付充值的通用流程

    废话不多说了,直接给大家贴java代码了. 具体代码如下所示: /*支付流程*/ /****Controller.java 代码如下:*/ @RequestMapping(value = "/paySubmit.htm", method = RequestMethod.POST) public ModelAndView paySubmit(HttpServletRequest request, HttpServletResponse response, @RequestParam Ma

  • 基于Java代码配置MyBatis Generator

    使用MyBatis Generator生成器时,有时候没办法使用xml形式的配置文件,比如将Maven项目设置成pom打包方式(<packaging>pom</packaging>)!由于Maven的工作机制对于打包方式为pom的项目是不会输出jar包或war包和resources内容,所以放在resources目录下或放在源码目录下的xml文件就没法读取了,就算你在pom.xml文件中明确有如下配置也没有用的: <build> <resources> &l

  • 基于java中byte数组与int类型的转换(两种方法)

    java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型.下面有两种方式. public static byte[] int2byte(int res) { byte[] targets = new byte[4]; targets[0] = (byte) (res & 0xf

  • 基于JAVA代码 获取手机基本信息(本机号码,SDK版本,系统版本,手机型号)

    老风格,废话不多说了,直接给大家贴java代码了. 代码如下: package com.zzw.getPhoneInfos; import android.app.Activity; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; public

  • 基于Java代码实现数字在数组中出现次数超过一半

    下文通过几种方法给大家介绍java数组数字出现次数,具体内容如下所示: 方法一: 数组排序,然后中间值肯定是要查找的值. 排序最小的时间复杂度(快速排序)O(NlogN),加上遍历. 方法二: 使用散列表的方式,也就是统计每个数组出现的次数,输出出现次数大于数组长度的数字. 方法三: 出现的次数超过数组长度的一半,表明这个数字出现的次数比其他数出现的次数的总和还多. 考虑每次删除两个不同的数,那么在剩下的数中,出现的次数仍然超过总数的一般,不断重复该过程,排除掉其他的数,最终找到那个出现次数超过

  • 基于Java代码操作Redis过程详解

    Jedis简介 实际开发中,我们需要用Redis的连接工具连接Redis然后操作Redis, 对于主流语言,Redis都提供了对应的客户端: 提供了很多客户端 官方推荐的是Jedis 托管地址:https://github.com/xetorthio/jedis 要使用redis首先得下载pom依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId&g

  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    之前因为项目组有自己的代码规范,为了约束平时的开发规范,于是基于2019.1.3版本开发了一个代码提示的插件.但是在把IDEA切换到2020.1版本的时候,却发现疯狂报错,但是网上关于IDEA插件开发的相关文章还是不够多,只能自己解决.于是根据官方的SDK文档,使用Gradle重新构建了一下项目,把代码拉了过来.下文会根据2020.1版本简单开发一个代码异常的提示插件,把容易踩坑的地方提示一下. 1.首先先根据IDEA插件开发官方文档,用Gradle新建一个project 选中file -> n

  • 浅谈一段java代码是如何执行的

    本文分享自华为云社区<一段java代码是如何执行的>,原文作者:技术火炬手 . 当你学会了java语言之后,你写了一些代码,然后你想要执行你的代码,来达成某些功能.那么,你都知道这段代码都是如何执行的吗? 1. 编译成class 众所周知,java代码是不能直接在jvm上执行的,执行的是class文件,将java代码编程class文件,需要编译 常用的编译方法是:javac xxx.java 但目前常见的java编辑工具,如eclipse和ideal都自带自动编译动能 2. jvm的构成 让我

随机推荐