一个Golang判断节假日的方法(通过解析gov.cn)

本方法参考自:golang 获取每年法定节假日 - 简书 (jianshu.com)

依赖:

go 1.20

require (
	github.com/Azure/go-autorest v14.2.0+incompatible // indirect
	github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
)

WorkDayUtil.go:

package workdayutil

import (
	"errors"
	"fmt"
	"github.com/Azure/go-autorest/autorest/date"
	"io"
	"net/http"
	"regexp"
	"strings"
	"time"
)

var (
	holiday, workday, _ = GetDays()
)

// GetDays fjDays 法定节假日,全部列表
// GetDays sbDays 法定补休日,全部列表
func GetDays() (holiday, workday map[date.Date]interface{}, err error) {

	var pUrl = "http://sousuo.gov.cn/s.htm?t=paper&advance=false&q=%E9%83%A8%E5%88%86%E8%8A%82%E5%81%87%E6%97%A5%E5%AE%89%E6%8E%92%E7%9A%84%E9%80%9A%E7%9F%A5"
	bytes, err := HttpGet(pUrl, nil)
	if err != nil {
		return nil, nil, err
	}
	result, err := GetRegexpList(string(bytes), `<li class="res-list">(.*?)</li>`)
	if err != nil {
		return nil, nil, err
	}
	if len(result) == 0 {
		return nil, nil, errors.New("解析错误")
	}
	// 拿第一个即可
	var data = strings.TrimSpace(result[0][1])
	if len(data) <= 0 {
		return nil, nil, errors.New("data result")
	}
	linkUrl, err := GetRegexpItem(data, `a href="(.*?)"`)
	if err != nil {
		fmt.Println("linkUrl=err==", err)
		return nil, nil, err
	}
	bytes, err = HttpGet(linkUrl, nil)
	if err != nil {
		fmt.Println("bytes=err==", err)
		return nil, nil, err
	}
	year, err := GetRegexpItem(string(bytes), `国务院办公厅关于(.*?)年`)
	if err != nil {
		fmt.Println("year=err==", err)
		return nil, nil, err
	}
	content, err := GetRegexpItem(string(bytes), `<div class="b12c pages_content".*?>(.*?)</div>`)
	if err != nil {
		fmt.Println("content=err==", err)
		return nil, nil, err
	}
	ll, err := GetRegexpList(content, `</span>(.*?)</p>`)
	if err != nil {
		return nil, nil, err
	}
	holiday, workday = map[date.Date]interface{}{}, map[date.Date]interface{}{}
	for _, c := range ll {
		if len(c[1]) > 0 && !strings.Contains(c[1], "<") {
			if strings.Contains(c[1], "。") {
				var s = strings.Split(c[1], "。")
				for _, str := range s {
					if len(str) > 0 {
						if strings.Contains(str, "放假") {
							var t = strings.Split(str, "放假")[0]
							if strings.Contains(t, "至") {
								var st = strings.Split(t, "至")[0]
								var et = strings.Split(t, "至")[1]
								var y, m, d = GetDateTime(GetTimeFormat(year, "", st))
								var ey, em, ed = GetDateTime(GetTimeFormat(year, m, et))
								var times = GetDateRange(fmt.Sprintf("%s-%s-%s", y, m, d), fmt.Sprintf("%s-%s-%s", ey, em, ed))
								for _, t := range times {
									holiday[t] = nil
								}
							} else {
								var y, m, d = GetDateTime(GetTimeFormat(year, "", t))
								parseDate, _ := date.ParseDate(fmt.Sprintf("%s-%s-%s", y, m, d))
								holiday[parseDate] = nil
							}
						}
						if strings.Contains(str, "上班") {
							if strings.Contains(str, "、") {
								var ts = strings.Split(str, "、")
								for _, t := range ts {
									if strings.Contains(t, "日") {
										var ymd = strings.Split(t, "日")
										var y, m, d = GetDateTime(GetTimeFormat(year, "", ymd[0]+"日"))
										//workday = append(workday, fmt.Sprintf("%s-%s-%s", y, m, d))
										parseDate, _ := date.ParseDate(fmt.Sprintf("%s-%s-%s", y, m, d))
										workday[parseDate] = nil
									}
								}
							}
						}
					}
				}
			}
		}
	}
	return
}
func GetTimeFormat(year, month, t string) string {
	if strings.Contains(t, "月") {
		if !strings.Contains(t, "年") {
			t = fmt.Sprintf("%s年%s", year, t)
		}
	} else {
		t = fmt.Sprintf("%s月%s", month, t)
		if !strings.Contains(t, "年") {
			t = fmt.Sprintf("%s年%s", year, t)
		}
	}
	return t
}
func GetDateTime(t string) (year, month, day string) {
	var ymd = strings.Split(t, "年")
	var y = ymd[0]  //2022
	var md = ymd[1] //12月31日
	var m = strings.Split(md, "月")[0]
	var d = strings.Split(strings.Split(md, "月")[1], "日")[0]
	if len(m) == 1 {
		m = fmt.Sprintf("0%s", m)
	}
	if len(d) == 1 {
		d = fmt.Sprintf("0%s", d)
	}
	return y, m, d
}
func GetRegexpItem(content string, regexpStr string) (s string, err error) {
	if len(regexpStr) <= 0 {
		return "", nil
	}
	// 处理回车换行
	content = strings.Replace(content, "\r", "", len(content))
	content = strings.Replace(content, "\n", "", len(content))
	regexpStr = fmt.Sprintf("(?i)%s", regexpStr)
	reg := regexp.MustCompile(regexpStr)
	cs := reg.FindStringSubmatch(content)
	if len(cs) > 1 {
		// 去掉内容的前后空格
		return strings.TrimSpace(cs[1]), nil
	}
	return "", errors.New(fmt.Sprintf("%s匹配错误,请检查网页", regexpStr))
}

// GetRegexpList 匹配符合正则的多个结果
func GetRegexpList(content string, regexpStr string) (s [][]string, err error) {
	// 处理回车换行
	content = strings.Replace(content, "\r", "", len(content))
	content = strings.Replace(content, "\n", "", len(content))
	regexpStr = fmt.Sprintf("(?i)%s", regexpStr)
	reg := regexp.MustCompile(regexpStr)
	result := reg.FindAllStringSubmatch(content, -1)
	if len(result) <= 0 {
		return nil, errors.New(fmt.Sprintf("%s匹配错误,请检查网页", regexpStr))
	}
	return result, nil
}
func HttpGet(url string, headers map[string]string) (response []byte, err error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

// IsWorkday holiday 法定节假日日期列表["2023-04-29","2023-04-30","2023-05-01"...]
// IsWorkday workdays 法定补休日日期列表["2023-05-06"...]
func isWorkday(in date.Date, holidays map[date.Date]interface{}, workdays map[date.Date]interface{}) bool {
	_, ok := workdays[in]
	if ok {
		return true
	}
	_, ok = holidays[in]
	if ok {
		return false
	}
	// 如果不在指定日期表中,则判断是否是周末
	weekday := in.Weekday()
	if weekday != time.Saturday && weekday != time.Sunday {
		return true
	}
	return false
}
func IsWorkday(in date.Date) bool {
	return isWorkday(in, holiday, workday)
}
func GetDateRange(start, end string) []date.Date {
	startTime, _ := time.Parse("2006-01-02", start)
	endTime, _ := time.Parse("2006-01-02", end)
	var dates []date.Date
	for i := 0; i <= int(endTime.Sub(startTime).Hours()/24); i++ {
		currentTime := startTime.AddDate(0, 0, i)
		d := currentTime.Format("2006-01-02")
		dd, _ := date.ParseDate(d)
		dates = append(dates, dd)
	}
	return dates
}
func Init() {

}

pUrl可能有变化,截止撰写时应为中国政府网站内搜索 (www.gov.cn)

调用方式:

parseDate, _ := date.ParseDate(time.Unix(batchLog.BizDate/1000, 0).Format(time.DateOnly))
workdayutil.IsWorkday(parseDate)

 

posted @ 2024-05-21 22:38  Jackie_JK  阅读(102)  评论(0编辑  收藏  举报