在有些场景需要判断指定的日期是否为工作日,例如,在做数据运维时,有些任务必须是每工作日运行的,这就需要检查当前日期是否为工作日了。判断是否为工作日,不能简单的判断是否是周一至周五或是不是周末,还需要依据国家的法定假日安排。
法定假日中,有一些是以公历日期安排的,例如:元旦、劳动节、国庆节;有些是按农历日期安排,这个就在公历上没有一个固定的日期了,例如:清明节、端午节、中秋节、除夕、春节。另外,法定假期还可能涉及平时工作日调整的情况。
如果是自己去收集这些信息,就太麻烦了。幸好我们只要在度娘上直接搜索“日历”就会返回当前月份的月历,如果有法定假期或工作日调整的,都会有标注:

通过跟踪发现,她这个是依据一个网页接口返回的数据展示出来的。例如查询2020年1月的接口地址是:
https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=2020%E5%B9%B41%E6%9C%88&co=&resource_id=6018&t=1578357406127&ie=utf8&oe=gbk&cb=op_aladdin_callback&format=json&tn=baidu&cb=jQuery11020002977011609388569_1578357382912&_=1578357382916
有了接口就开干:
import requests
import json
import calendar, os, pathlib, datetime
def getYearHolidays(year):
'''得到法定节假日安排'''
if(datetime.datetime.now().year < year): return {}
cachefile = os.path.join(os.getcwd(), 'caches', 'holidays'+ str(year) +'.json')
if not pathlib.Path(cachefile).exists():
pathlib.Path(os.path.dirname(cachefile)).parent.mkdir(parents=True, exist_ok=True)
url = r'https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query='+ str(year) + r'%E5%B9%B41%E6%9C%88&co=&resource_id=6018&t=1578357406127&ie=utf8&oe=gbk&format=json&tn=baidu&_=1578357382916'
response = requests.get(url)
res = json.loads(response.text)
with(open(cachefile, 'wt', encoding='UTF-8')) as f:
json.dump(res['data'][0]['holiday'], f, ensure_ascii=False)
holidays = res['data'][0]['holiday']
else:
with(open(cachefile, encoding='UTF-8')) as f:
holidays = json.load(f)
days = {}
for holiday in holidays:
for x in holiday['list']:
days[x['date']] = x['status'] #1为假日;2为工作日
return days
def isWorkingDay(year, month, day):
'''
判断日期是否为工作日
如果是由返回True,否则返回False
'''
#法定节检查
holidays = getYearHolidays(year)
dateStr = f"{year}-{month}-{day}"
if(dateStr in holidays):
return holidays[dateStr] != '1'
#检查是否为普通的工作日(周一至五)或周末(周六、日)
weekday = calendar.weekday(year, month, day)
return weekday in [0, 1, 2, 3, 4]#0是周一
测试结果:
print(isWorkingDay(2020, 1, 1)) #False
print(isWorkingDay(2020, 1, 2)) #True
但是使用这个也存在问题:
1、接口只返回近10年的节假日安排;
2、法定节假日安排要等国家节假日办颁布后才能查询,比如现在想查2021年的是没办法的