Python:使用chinesecalendar获取中国节假日判断工作日和节假日

目录

    • 现有方案:chinesecalendar
    • 基于网络的方案
    • 使用china-calendar

      现有方案:chinesecalendar

      使用chinesecalendar库可以实现:判断一天是不是法定节假日/法定工作日(查看节假日安排)

      • https://pypi.org/project/chinesecalendar/
      • https://github.com/LKI/chinese-calendar/

        安装

        pip install chinesecalendar
        

        使用示例

        import datetime
        # 判断 2018年4月30号 是不是节假日
        from chinese_calendar import is_holiday, is_workday
        april_last = datetime.date(2018, 4, 30)
        assert is_workday(april_last) is False
        

        缺点:

        • 1、更新不及时,或需要手动更新才能判断,由于次年的节假日安排,取决于国务院发布的日程。 所以本项目一般会在国务院更新以后,发布新的版本。 按照以往的经验,一般是每年的 11月 前后发布新版本。
        • 2、支持的版本有点高,Python :: 3.8起步,不支持低版本

          基于网络的方案

          可以使用现有的维护的比较好的网站数据,比如:https://wannianrili.bmcx.com/,通过网页请求解析获取日历数据,这样就能获取到实时的数据,缺点也很明显,需要网络请求,如果考虑性能的场景下,可能不适用。

          依赖两个第三方库:

          pip install requests parsel
          

          代码文件,可以放到项目的utils工具包内

          # -*- coding: utf-8 -*-
          """
          @File    : calendar_util.py
          @Date    : 2024-04-03
          """
          import json
          import re
          import requests
          from parsel import Selector
          def get_calendar(year_and_month):
              """
              数据来源:https://wannianrili.bmcx.com/
              @return:
              {
                "2024-04-01": {
                  "class_name": "",
                  "comment": "愚人节"
                  }
              }
              """
              # https://wannianrili.bmcx.com/ajax/?q=2024-04&v=22121303
              url = 'https://wannianrili.bmcx.com/ajax/'
              params = { 'q': year_and_month,
                  'v': '22121303'
              }
              headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"
              }
              res = requests.get(url, params=params, headers=headers)
              
              sel = Selector(text=res.text)
              rows = sel.css('.wnrl_riqi')
              data = {}
              for row in rows:
                  class_name = row.css('a::attr(class)').extract_first('').strip()
                  day = row.css('a::attr(onclick)').extract_first('').strip()
                  comment = row.css('.wnrl_td_bzl::text').extract_first('').strip()
                  ret = re.search('\d{4}-\d{2}-\d{2}', day)
                  day = ret.group(0)
                  data[day] = { 'class_name': class_name,
                      'comment': comment
                  }
              return data
          def get_day_item(day):
              """
              @param day:
              @return:
              {
                  "class_name": "",
                  "comment": "愚人节"
              }
              """
              # 2024-05-04 => 2024-05
              calendar = get_calendar('-'.join(day.split('-')[:2]))
              # print(json.dumps(calendar, indent=2, ensure_ascii=False))
              return calendar.get(day)
          def is_workday(day):
              # 工作日
              workday_class_list = ['', 'wnrl_riqi_ban']
              day_item = get_day_item(day)
              if day_item:
                  if day_item.get('class_name') in workday_class_list:
                      return True
                  else:
                      return False
          def is_holiday(day):
              # 节假日
              holiday_class_list = ['wnrl_riqi_xiu', 'wnrl_riqi_mo']
              day_item = get_day_item(day)
              if day_item:
                  if day_item.get('class_name') in holiday_class_list:
                      return True
                  else:
                      return False
          if __name__ == '__main__':
              print(is_holiday('2024-05-04')) # True
          

          使用china-calendar

          基于以上代码,作者封装了一个库,可以直接使用

          文档:

          • https://github.com/mouday/china-calendar
          • https://pypi.org/project/china-calendar/

            安装

            pip install china-calendar
            

            使用示例:

            import china_calendar
            # 清明节
            assert china_calendar.is_holiday('2024-04-04') == True
            assert china_calendar.is_workday('2024-04-04') == False