Blow Up by Black Swan

2019年と2020年の祝祭日を反映したカレンダーを作るプログラム

[2019/12/8 追記]
ブログ内で「calender」と表記していますが、正式には「calendar」でした(^^; 変更して齟齬が出るのも嫌なので、記事内ではそのままにしています。

2019年は、天皇陛下の退位と皇太子様の即位、それに伴う元号の変更などカレンダーに影響を与えるイベントがたくさんあります。また来年は東京オリンピックが開催により、一部の祝日が移動されることが決まっています。祝日という観点からは非常にややこしいこの2年間ですが、今回はこの2年のイレギュラーな祝日にも対応するカレンダーを制作するプログラムを作ったので、それをまとめようと思います。

1. 環境設定

今回の実験環境は以下になります。

  • Python: 3.7
  • requests: 2.21.0

また使用するAPIは以下になります。

  1. カレンダーAPI
    • URL: http://calendar-service.net/api.php
    • 備考: データ形式や区間はサイトで設定できる
  2. 内閣府の祝祭日情報を提供するAPI
    • URL: https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv
    • 備考: 祝日の概要についてはこちらに記載

googleカレンダーのAPIを使っても良さそうでしたが、諸手続きが面倒くさそうだったので使うのをやめました。

2. コード

以下がカレンダーのコードになります。特に関数を作ったりせず、力技で処理しています。

#カレンダー情報の取得から整理 -> MySQlのcalenderに挿入
import requests
#カレンダーAPIから基本的なカレンダー情報の取得
api = "http://calendar-service.net/cal?start_year={year}&start_mon=1&end_year={year}&end_mon=12&year_style=normal&month_style=numeric&wday_style=ja&format=csv"
s = []
for i in [2019,2020]:  #ここでカレンダーにしたい年を設定
    res = requests.get(api.format(year=i))
    m = res.text.split('\n')
    s += m[1:-1]
calender = []
for i in s:
    m = i.split(',')
    date = '/'.join((m[0],m[1],m[2]))
    calender.append([date,m[5],m[7]])
#内閣府からの祝日情報の取得し、2019年度のデータだけを抽出
import requests
holidays_api = requests.get('https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv')
holidays_api.encoding = 'Shift_JIS'
f = holidays_api.text.split('\r\n')
holidays = []
s = []
for i in f:
    m = i.split(',')
    try:
        year = int(m[0].split('/')[0])
    except Exception:
        continue
    if year == 2018:
        continue
    holidays.append(m)
# calenderへの祝日APIの反映(主に即位の礼のため)
for holiday in holidays:
    for day in calender:
        if day[0] == holiday[0]:
            day[2] = holiday[1]
# スポーツの日への名称変更(2020年から)
for i in calender:
    if i[2] == '体育の日':
        if (i[0].split('/')[0]) != '2019':
            i[2] = 'スポーツの日'
# 天皇誕生日の変更
for i in calender:
    if i[0].split('/')[1] == '12' and i[0].split('/')[2] == '23':
        i[2] = ''
# 東京オリンピックによる祝日の改正への影響
for i in calender:
    if i[0] == '2019/12/23':
        i[2] = ''
    elif i[0] == '2020/7/20':
        i[2] = ''
    elif i[0] == '2020/7/23':
        i[2] = '海の日'
    elif i[0] == '2020/7/24':
        i[2] = 'スポーツの日'
    elif i[0] == '2020/8/10':
        i[2] = '山の日'
    elif i[0] == '2020/8/11':
        i[2] = ''
    elif i[0] == '2020/10/12':
        i[2] = ''
    continue
calender

戻り値

[['2019/1/1', '火', '元日'],
 ['2019/1/2', '水', ''],
 ['2019/1/3', '木', ''],
 
  (省略)
 ['2019/4/20', '土', ''],
 ['2019/4/21', '日', ''],
 ['2019/4/22', '月', ''],
 ['2019/4/23', '火', ''],
 ['2019/4/24', '水', ''],
 ['2019/4/25', '木', ''],
 ['2019/4/26', '金', ''],
 ['2019/4/27', '土', ''],
 ['2019/4/28', '日', ''],
 ['2019/4/29', '月', '昭和の日'],
 ['2019/4/30', '火', '休日'],
 ['2019/5/1', '水', '休日(祝日扱い)'],
 ['2019/5/2', '木', '休日'],
 ['2019/5/3', '金', '憲法記念日'],
 ['2019/5/4', '土', 'みどりの日'],
 ['2019/5/5', '日', 'こどもの日'],
 ['2019/5/6', '月', '休日'],
 ['2019/5/7', '火', ''],
 ['2019/5/8', '水', ''],
 ['2019/5/9', '木', ''],
 ['2019/5/10', '金', ''],
  (省略)
 ['2019/10/10', '木', ''],
 ['2019/10/11', '金', ''],
 ['2019/10/12', '土', ''],
 ['2019/10/13', '日', ''],
 ['2019/10/14', '月', '体育の日(スポーツの日)'],
 ['2019/10/15', '火', ''],
 ['2019/10/16', '水', ''],
 ['2019/10/17', '木', ''],
 ['2019/10/18', '金', ''],
 ['2019/10/19', '土', ''],
 ['2019/10/20', '日', ''],
 ['2019/10/21', '月', ''],
 ['2019/10/22', '火', '休日(祝日扱い)'],
 ['2019/10/23', '水', ''],
 ['2019/10/24', '木', ''],
  (省略)
 ['2019/12/19', '木', ''],
 ['2019/12/20', '金', ''],
 ['2019/12/21', '土', ''],
 ['2019/12/22', '日', ''],
 ['2019/12/23', '月', ''],
 ['2019/12/24', '火', ''],
 ['2019/12/25', '水', ''],
 ['2019/12/26', '木', ''],
  (省略)
 ['2020/7/19', '日', ''],
 ['2020/7/20', '月', ''],
 ['2020/7/21', '火', ''],
 ['2020/7/22', '水', ''],
 ['2020/7/23', '木', '海の日'],
 ['2020/7/24', '金', 'スポーツの日'],
 ['2020/7/25', '土', ''],
 ['2020/7/26', '日', ''],
 ['2020/7/27', '月', ''],
 ['2020/7/28', '火', ''],
 ['2020/7/29', '水', ''],
 ['2020/7/30', '木', ''],
 ['2020/7/31', '金', ''],
 ['2020/8/1', '土', ''],
 ['2020/8/2', '日', ''],
 ['2020/8/3', '月', ''],
 ['2020/8/4', '火', ''],
 ['2020/8/5', '水', ''],
 ['2020/8/6', '木', ''],
 ['2020/8/7', '金', ''],
 ['2020/8/8', '土', ''],
 ['2020/8/9', '日', ''],
 ['2020/8/10', '月', '山の日'],
 ['2020/8/11', '火', ''],
 ['2020/8/12', '水', ''],
 ['2020/8/13', '木', ''],
  (省略)

現時点で法令が変更された祝日が反映されたカレンダーが完成しました。

3. まとめ

以上が、直近2年間のややこしい祝祭日を反映させたカレンダーを作るプログラムです。カレンダーAPIから取得するデータの加工の仕方次第でより柔軟にカレンダーを作成することができます。もっと簡単にできそうな気がしたのですが、祝祭日の状況が変わりやすく、思った以上に手間取ったというのが本音です。日本では有給休暇の取得率の低さが問題になっていますが、個人的には祝日を半分程度に減らした上で、有給休暇の全日取得義務化、それができない場合は企業による1.5倍での未消化有給休暇日の買取義務化、のような施策を実施した方が良いと考えています(但し有休付与日でちょろまかす企業が出てくると思うので、そこも「雇用契約締結より1年を過ぎた職員には最低12日以上の有休付与義務を課す」といったルールを合わせて定める必要があるとは思います。)なお、上記のような考えを持ってはいますが、左派や労組よりというわけではなく、解雇規制の緩和、ホワイトカラーエグセプションや裁量労働制の拡大には賛成です。最後はかなり記事の主題からそれてしまいましたが、今回のカレンダーの作成プログラムがどなたかのお役に立てれば幸いです。