Java 每年节假日获取

Java 每年节假日获取

参考链接

以下实现参考本篇文章

说明

自动获取每年节假日,因为国家每一年的假期可能不一样,是人为设定的;所以需要每年生成一次或者在项目中写定时任务实现。因为我这里的需求稍微简单一点,维护的时候执行一次就可以了。我是参照上面链接的文章再根据自己的需求稍有修改和完善。问题之处欢迎大家指出。不说废话直接来代码。

代码

环境依赖,这里说明一下,请注意依赖版本号,因为我在用最新依赖时发现里面大不一样,我没有找到完整的使用案例和API,所以这里用了一个老版本(也是使用人数最多的版本了)。

<dependency>
	<groupId>net.sourceforge.htmlunit</groupId>
	<artifactId>htmlunit</artifactId>
	<version>2.23</version>
</dependency>

实体类

package ***.**.utils.holidays;

import java.io.Serializable;
import java.util.Date;

/**
 * @ProjectName: ****
 * @Package: ***.**.utils.holidays
 * @ClassName: ChinaDate
 * @Author: 小王
 * @Date: 2022/1/18  13:55
 * @Description: 定义一个中国日期类
 */
public class ChinaDate implements Serializable {
   

    /**
     * 公历时间
     */
    private Date solarDate;
    /**
     * 农历日
     */
    private String lunar;
    /**
     * 公历日
     */
    private String solar;
    /**
     * 是否是 休
     */
    private boolean isVacation = false;
    /**
     * 如果是 休情况下的假期名字
     */
    private String vacationName = "工作日";

    private String vacationType="0";//类型

    private String practicalMonth;//实际月份

    private String formatDate;//yyyyMMdd格式日期
    /**
     * 是否是 班
     */
    private boolean isWorkFlag = false;
    private boolean isSaturday = false;
    private boolean isSunday = false;

    public ChinaDate() {
   
    }

    public ChinaDate(Date solarDate, String lunar, String solar, boolean isVacation, String vacationName, String vacationType, String practicalMonth, String formatDate, boolean isWorkFlag, boolean isSaturday, boolean isSunday) {
   
        this.solarDate = solarDate;
        this.lunar = lunar;
        this.solar = solar;
        this.isVacation = isVacation;
        this.vacationName = vacationName;
        this.vacationType = vacationType;
        this.practicalMonth = practicalMonth;
        this.formatDate = formatDate;
        this.isWorkFlag = isWorkFlag;
        this.isSaturday = isSaturday;
        this.isSunday = isSunday;
    }

    public String getVacationName() {
   
        return vacationName;
    }

    public void setVacationName(String vacationName) {
   
        this.vacationName = vacationName;
    }

    public String getVacationType() {
   
        return vacationType;
    }

    public void setVacationType(String vacationType) {
   
        this.vacationType = vacationType;
    }

    public String getPracticalMonth() {
   
        return practicalMonth;
    }

    public void setPracticalMonth(String practicalMonth) {
   
        this.practicalMonth = practicalMonth;
    }

    public String getFormatDate() {
   
        return formatDate;
    }

    public void setFormatDate(String formatDate) {
   
        this.formatDate = formatDate;
    }

    public Date getSolarDate() {
   
        return solarDate;
    }

    public void setSolarDate(Date solarDate) {
   
        this.solarDate = solarDate;
    }

    public String getLunar() {
   
        return lunar;
    }

    public void setLunar(String lunar) {
   
        this.lunar = lunar;
    }

    public String getSolar() {
   
        return solar;
    }

    public void setSolar(String solar) {
   
        this.solar = solar;
    }

    public boolean isVacation() {
   
        return isVacation;
    }

    public void setVacation(boolean vacation) {
   
        isVacation = vacation;
    }

    public boolean isWorkFlag() {
   
        return isWorkFlag;
    }

    public void setWorkFlag(boolean workFlag) {
   
        isWorkFlag = workFlag;
    }

    public boolean isSaturday() {
   
        return isSaturday;
    }

    public void setSaturday(boolean saturday) {
   
        isSaturday = saturday;
    }

    public boolean isSunday() {
   
        return isSunday;
    }

    public void setSunday(boolean sunday) {
   
        isSunday = sunday;
    }

      @Override
    public String toString() {
   
        return "ChinaDate{" +
                "solarDate=" + solarDate +
                ", lunar='" + lunar + '\'' +
                ", solar='" + solar + '\'' +
                ", isVacation=" + isVacation +
                ", vacationName='" + vacationName + '\'' +
                ", vacationType='" + vacationType + '\'' +
                ", practicalMonth='" + practicalMonth + '\'' +
                ", formatDate='" + formatDate + '\'' +
                ", isWorkFlag=" + isWorkFlag +
                ", isSaturday=" + isSaturday +
                ", isSunday=" + isSunday +
                '}';
    }
}

基础工具类

定义解析页面数据的工具类,主要用于基础数据提取,后面所有方法均在此类上使用

package ***.**.utils.holidays;

import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.yx.utils.common.DateUtils;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @ProjectName: ****
 * @Package: ***.**.utils.holidays
 * @ClassName: holidays
 * @Author: 小王
 * @Date: 2022/1/18  15:04
 * @Description: 解析网页,获取年详情:
 */
public class holidays {
   

    private static String url="http://hao.360.com/rili/";//要解析的网页链接

    private static WebClient webClient = new WebClient();//网页请求对象

    private static HtmlPage page=null;//页面内容对象

    private static String datesId="M-dates";//DOM对象 ,日期元素id

    private static String datesLi="li";//DOM对象 ,日期元素标签名称

    private static String toolId="M-controls";//DOM对象 ,日期工具头元素id

    private static String toolDiv="div";//DOM对象 ,日期工具头标签名称

    private static String toolClass="control-bar mouth-bar";//DOM对象 ,被点击元素的class名称

    private static String nextLabel="a";//DOM对象 ,下个月元素的标签名称

    private static String attributeName="class";//DOM对象 ,公用属性名称

    private static String nextAttributeValue="next";//DOM对象 ,下个月元素的属性值

    private static String lastLabel="a";//DOM对象 ,上个月元素的标签名称

    private static String lastAttributeValue="prev";//DOM对象 ,上个月元素的属性值

    //静态代码块初始化链接和对象
    static {
   
        try {
   
            //htmlunit 对css和javascript的支持不好,所以直接关闭
            //webClient.getOptions().setCssEnabled(false);
            //webClient.getOptions().setJavaScriptEnabled(false);
            //获取网页对象
            page = webClient.getPage(url);
            //最大等待30秒
            for(int k = 0; k < 30; k++){
   //由于网络原因可能会导致页面解析不全所以设置等待
                if(!page.getElementById(datesId).asText().equals("")) break;
                Thread.sleep(1000);
            }
            String titleText = page.getTitleText();
            System.err.println("get date from "+url+" success~,The page title is:"+titleText);
        } catch (Exception e) {
   
            System.err.println("get date from "+url+" error~");
            e.printStackTrace();
        }
    }

    /**
     * @author 小王
     * @Date 2022/1/19 10:30
     * @param null:
     * @return: null
     * @Description:  获取当前页日期元素集合
     */
    public static List<HtmlElement> getHtmlElements(){
   
        DomElement elementById = page.getElementById(datesId);
        DomNodeList<HtmlElement> htmlElements = page.getElementById(datesId).getElementsByTagName(datesLi);
        if(htmlElements.size()<=0){
   
            Iterator<HtmlElement> iterator = elementById.getHtmlElementDescendants().iterator();
            while (iterator.hasNext()){
   
                htmlElements.add(iterator.next());
                //  System.err.println("============iterator========"+iterator.next().asText());
            }
        }
        return htmlElements;
    }

    /**
    * @author 小王
    * @Date 2022/1/19 10:53
    * @param null:
    * @return: null
    * @Description:  获取下一页日期元素集合
    */
    public static List<HtmlElement> getNextPage(){
   
        try {
   
        DomElement elementHead = page.getElementById(toolId);
        List<HtmlElement> byXPath = elementHead.getElementsByTagName(toolDiv);
        if(byXPath.size()>0){
   
            for (HtmlElement element:byXPath){
   
                if(Objects.equals(toolClass,element.getAttribute(attributeName))){
   
                    List<HtmlElement> elementsByAttribute = element.getElementsByAttribute(nextLabel, attributeName, nextAttributeValue);
                    HtmlPage click = elementsByAttribute.get(0).click();
                    page = click.getPage();
                    return getHtmlElements();
                }
            }
        }
        } catch (IOException e) {
   
            System.err.println("get next page date from "+url+" error~");
            e.printStackTrace();
        }
        return null;
    }

    /**
    * @author 小王
    * @Date 2022/1/19 15:01
    * @param null:
    * @return: null
    * @Description:  获取上个月
    */
    public static List<HtmlElement> getLastPage(){
   
        try {
   
            DomElement elementHead = page.getElementById(toolId);
            List<HtmlElement> byXPath = elementHead.getElementsByTagName(toolDiv);
            if(byXPath.size()>0){
   
                for (HtmlElement element:byXPath){
   
                    if(Objects.equals(toolClass,element.getAttribute(attributeName))){
   
                        List<HtmlElement> elementsByAttribute = element.getElementsByAttribute(lastLabel, attributeName, lastAttributeValue);
                        HtmlPage click = elementsByAttribute.get(0).click();
                        page = click.getPage();
                        return getHtmlElements();
                    }
                }
            }
        } catch (IOException e) {
   
            System.err.println("get next page date from "+url+" error~");
            e.printStackTrace();
        }
        return null;
    }
}

封装工具类

这里因为目前项目需求用的不深,所以没有继续优化了。当跨年份太长了之后对网络要求较高,实际上有另一种高效率的实现但比较麻烦。目前我这里影响不是很大所以暂时没写,有需要的可以联系我。
执行效率低的代码:
在这里插入图片描述

package ***.**.utils.holidays;

import com.alibaba.fastjson.JSON;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.yx.utils.common.DateUtils;
import com.yx.utils.common.StringUtil;
import org.springframework.util.CollectionUtils;

import javax.swing.text.html.HTMLDocument;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Year;
import java.util.*;

/**
 * @ProjectName: ****
 * @Package: ***.**.utils.holidays
 * @ClassName: holidaysUtils
 * @Author: 小王
 * @Date: 2022/1/18  15:04
 * @Description: 全年节假日工具类,支持最大到本年:
 */
public class holidaysUtils {
   

    private static String lunarElementName="span";//DOM对象 ,农历日期标签名称

    private static String attributeName="class";//DOM对象 ,公用属性名称

    private static String lunarAttributeValue="lunar";//DOM对象 ,农历日期属性值

    private static String solarElementName="div";//DOM对象 ,农历日期标签名称

    private static String solarAttributeValue="solar";//DOM对象 ,公历日期属性值

    private static String solarDateAttributeValue="date";//DOM对象 ,公历日期结果属性名称

    private static String patternStr="yyyy/MM/dd";//日期解析字符串

    private static String patternMonthStr="MM";//日期解析月份字符串

    private static String staClass="weekend";//周六属性值

    private static String sunPrefixClass="last";//周日前缀属性值

    private static String sunClass="last weekend";//周日属性值

    private static String workClass="work";//工作日属性值

    private static String vacationClass="vacation";//节假日属性值

    private static String weekendName="周六日";//周六日名称

    private static String weekendType="1";//周六日类型值

    private static String workName="工作日";//周六日名称

    private static String workType="0";//周六日类型值

    private static String vacationName="";//节假日名称

    private static String vacationType="2";//节假日类型值

    private static int pioneerYear=1901;//最小可执行年份

    private static int latestYear=2100;//最大可执行年份


    /**
    * @author 小王
    * @Date 2022/1/19 11:18
    * @param null:
    * @return: null
    * @Description:  最近一次的可见的假期名
    */
    public static String getVocationName(List<HtmlElement> htmlElements, String date) {
   
        String rst = "";
        boolean pastTimeFlag = false;
        Date paramDate = DateUtils.parseDate(date, patternStr);
        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(attributeName).indexOf(vacationClass) != -1) {
   
                boolean hitFlag = false;
                String voationName = "";
                for (; i < htmlElements.size(); i++) {
   
                    HtmlElement elementTmp = htmlElements.get(i);
                    String liDate = elementTmp.getAttribute(solarDateAttributeValue);
                    List<HtmlElement> lunar = elementTmp.getElementsByAttribute(lunarElementName, attributeName, lunarAttributeValue);
                    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(attributeName).indexOf(vacationClass) == -1) {
   
                        break;
                    }
                }
                if (hitFlag == true && !voationName.equals("")) {
   
                    rst = voationName;
                    break;
                }
            } else {
   
                continue;
            }
        }
        if (rst.equals("")) {
   
            System.out.println("warning: fail to get vocation name from html page.");
            rst = holidaysUtils.vacationName;
        } else if (pastTimeFlag == true) {
   
            //更新《当前时间,且最近一次的可见的假期名
            holidaysUtils.vacationName = rst;
        }
        return rst;
    }

    /**
    * @author 小王
    * @Date 2022/1/19 11:12
    * @param null:
    * @return: null
    * @Description:  获取本月数据
    */
    public static List<ChinaDate> getCurrentDateInfo(List<HtmlElement> htmlElements){
   
        List<ChinaDate> dateList=new ArrayList<>();
        if(!CollectionUtils.isEmpty(htmlElements)){
   
            for(HtmlElement element : htmlElements){
   
                ChinaDate chinaDate = new ChinaDate();
                List<HtmlElement> lunar = element.getElementsByAttribute(lunarElementName, attributeName, lunarAttributeValue);
                List<HtmlElement> solar = element.getElementsByAttribute(solarElementName, attributeName, solarAttributeValue);
                chinaDate.setLunar(lunar.get(0).asText());
                chinaDate.setSolar(solar.get(0).asText());
                chinaDate.setSolarDate(DateUtils.parseDate(element.getAttribute(solarDateAttributeValue),patternStr));
                chinaDate.setFormatDate(DateUtils.format(chinaDate.getSolarDate(),DateUtils.DATEPATTERN));
                chinaDate.setPracticalMonth(DateUtils.format(chinaDate.getSolarDate(),patternMonthStr));
                if(element.getAttribute(attributeName).indexOf(staClass)!=-1 &&
                        element.getAttribute(attributeName).indexOf(sunPrefixClass)==-1
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
Java获取法定节假日可以通过使用第三方库来实现。一个常用的库是"Jollyday",它提供了一些方便的方法来获取法定节假日的信息。 首先,你需要在你的项目中引入Jollyday库。你可以在Maven或Gradle中添加以下依赖项: Maven: ```xml <dependency> <groupId>de.jollyday</groupId> <artifactId>jollyday</artifactId> <version>0.5.1</version> </dependency> ``` Gradle: ```groovy implementation 'de.jollyday:jollyday:0.5.1' ``` 接下来,你可以使用以下代码获取法定节假日的信息: ```java import de.jollyday.Holiday; import de.jollyday.HolidayManager; import de.jollyday.config.ConfigurationProviderManager; public class Main { public static void main(String[] args) { // 创建HolidayManager对象 HolidayManager holidayManager = HolidayManager.getInstance(ConfigurationProviderManager.createConfigurationProvider()); // 获取指定年份的所有法定节假日 int year = 2022; Set<Holiday> holidays = holidayManager.getHolidays(year, "CN"); // 遍历输出每个法定节假日的信息 for (Holiday holiday : holidays) { System.out.println(holiday.getDate() + " - " + holiday.getDescription()); } } } ``` 上述代码中,我们首先创建了一个HolidayManager对象,然后使用getHolidays方法获取指定年份和国家代码("CN"代表中国)的所有法定节假日。最后,我们遍历输出每个法定节假日的日期和描述信息。 请注意,Jollyday库提供了许多其他功能,例如获取特定日期是否为法定节假日获取指定日期范围内的法定节假日等。你可以根据自己的需求进行调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值