日本の祝日を取得するシェルスクリプト(バッチ処理プログラム)(「山の日」対応) – カレンダーファイル(ICSファイル)で祝日の取得 〜2015年の祝日一覧、2016年の祝日一覧、2017年の祝日一覧、2018年の祝日一覧、2019年の祝日一覧、2020年の祝日一覧〜

12月 9, 2016AWS,EC2,Lambda,Programming,Shell Script

運用系のプログラムを実装する際に時々必要になってくるのが祝日を取得するプログラムです。
ニーズとしては祝日の時のみ処理を停止したい、土日祝日の時に処理を停止したいというものです。

AWS関係ではAWS Lambdaをスケジューリング機能を使用してEC2インスタンスを土日祝日以外の日に指定時間にスタートさせたり、ストップさせたりするスクリプトに必要になってきます。

今回は、このようなシステムの運用面で必要になってくる祝日を取得するシェルスクリプトを備忘録として記載しておきたいと思います。
シェルスクリプトであれば、AWS LambdaでもPython等のスクリプトから呼び出して実行できますし、他のサーバ内でも実行することができますので、シェルスクリプトでの実装を選択しました。

祝日取得シェルスクリプト

祝日は正確に日付が決まっている日もあれば、月の何週目の何曜日のような指定、新しく定められた祝日など計算では割り出せないという特徴があります。
そのため、祝日の取得に関してはAppleやGoogleなどの有名ベンダーが公開しているカレンダーファイルから取得する方法をおすすめします。

下記では実際にApple、Google、Mozillaなど任意のICS形式のカレンダーファイルをダウンロードして祝日を取得するスクリプトを紹介します。
後述しますが、Googleから提供されているICSカレンダーファイルを使用することで2016年から新しく追加された祝日「山の日」に対応することができます。

祝日取得シェルスクリプトのソースコード

[magtranetwork@localhost ~]$ vim get_holidays.sh
#!/bin/bash

#カレンダーファイルを保存、編集する一時ディレクトリを指定する
tmp_dir=/tmp

#一時ディレクトリを作成する
mkdir -p ${tmp_dir}

#検索対象文字列にコマンド引数を代入する
target=${1}

#使用するICSカレンダーファイルURL
#Appleから提供されているICS
#ICS=https://ical.mac.com/ical/Japanese32Holidays.ics

#Googleから提供されているICS
ICS=https://www.google.com/calendar/ical/ja.japanese%23holiday%40group.v.calendar.google.com/public/basic.ics

#Mozillaから提供されているICS
#ICS=https://www.mozilla.org/projects/calendar/caldata/JapanHolidays.ics

#カレンダーファイルをJapanHolidays.icsの名称で一時ディレクトリへ保存する。
curl -s -S -L -o ${tmp_dir}/JapanHolidays.ics ${ICS}

#ダウンロードしたカレンダーファイルを編集し、[年月日文字列 祝日名称]の形式でJapanHolidays.txtという名称でファイル出力する
cat ${tmp_dir}/JapanHolidays.ics | grep -e "DTSTART;VALUE=DATE" -e SUMMARY -e "BEGIN:VEVENT" -e "END:VEVENT" | tr -d '\r\n' | sed 's/END:VEVENT/\n/g' | sed 's/BEGIN:VEVENT//g' | sed 's/:/ /g' | sed 's/SUMMARY/ /g' | awk '{print $2,$NF}' | awk '{if ( $1 ~/^[0-9]+$/){ print $1,$NF}else{ print $NF,$1}}' | sort -k 1 > ${tmp_dir}/JapanHolidays.txt

if [ "${target}" = "" ]; then
  #コマンド引数がない場合はJapanHolidays.txtの中身を全て表示する
  cat ${tmp_dir}/JapanHolidays.txt
else
  #コマンド引数がある場合はJapanHolidays.txtの中身を検索対象文字列で前方一致検索し、表示する
  cat ${tmp_dir}/JapanHolidays.txt | grep ^${target}
fi

#一時ディレクトリ内の一時ファイルを削除する
rm -f ${tmp_dir}/JapanHolidays.ics ${tmp_dir}/JapanHolidays.ics
rm -f ${tmp_dir}/JapanHolidays.ics ${tmp_dir}/JapanHolidays.txt

祝日取得シェルスクリプトの使用例

上記の祝日取得シェルスクリプトの実行は下記のようにYYYY, YYYYMM, YYYYMMDDの形式の日付を引数に指定することで各年月日に対応する祝日を取得できます。
引数を何も指定しなければ当日日付で検索します。

[magtranetwork@localhost ~]$ ./get_holidays.sh 201711
20171103 文化の日
20171123 勤労感謝の日
[magtranetwork@localhost ~]$ ./get_holidays.sh 20170811
20170811 山の日

2015年から2020年までの祝日一覧

下記はAppleから提供されているICSファイルを使用して、祝日取得シェルスクリプトを実行することで2015年から2020年までの祝日一覧を取得することができます。
ただし、Appleから提供されているICSは2016年11月時点で2016年から追加された祝日「山の日」が考慮されていません。

2015年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2015
20150101 元日
20150112 成人の日
20150211 建国記念の日
20150321 春分の日
20150429 昭和の日
20150503 憲法記念日
20150504 みどりの日
20150505 こどもの日
20150506 振替休日
20150720 海の日
20150921 敬老の日
20150923 秋分の日
20150922 国民の休日
20151012 体育の日
20151103 文化の日
20151123 勤労感謝の日
20151223 天皇誕生日

2016年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2016
20160101 元日
20160111 成人の日
20160211 建国記念の日
20160320 春分の日
20160321 振替休日
20160429 昭和の日
20160503 憲法記念日
20160504 みどりの日
20160505 こどもの日
20160718 海の日
20160919 敬老の日
20160922 秋分の日
20161010 体育の日
20161103 文化の日
20161123 勤労感謝の日
20161223 天皇誕生日

2017年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2017
20170101 元日
20170102 振替休日
20170109 成人の日
20170211 建国記念の日
20170320 春分の日
20170429 昭和の日
20170503 憲法記念日
20170504 みどりの日
20170505 こどもの日
20170717 海の日
20170918 敬老の日
20170923 秋分の日
20171009 体育の日
20171103 文化の日
20171123 勤労感謝の日
20171223 天皇誕生日

2018年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2018
20180101 元日
20180108 成人の日
20180211 建国記念の日
20180212 振替休日
20180321 春分の日
20180429 昭和の日
20180430 振替休日
20180503 憲法記念日
20180504 みどりの日
20180505 こどもの日
20180716 海の日
20180917 敬老の日
20180923 秋分の日
20180924 振替休日
20181008 体育の日
20181103 文化の日
20181123 勤労感謝の日
20181223 天皇誕生日
20181224 振替休日

2019年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2019
20190101 元日
20190114 成人の日
20190211 建国記念の日
20190321 春分の日
20190429 昭和の日
20190503 憲法記念日
20190504 みどりの日
20190505 こどもの日
20190506 振替休日
20190715 海の日
20190916 敬老の日
20190923 秋分の日
20191014 体育の日
20191103 文化の日
20191104 振替休日
20191123 勤労感謝の日
20191223 天皇誕生日

2020年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2020
20200101 元日
20200113 成人の日
20200211 建国記念の日
20200320 春分の日
20200429 昭和の日
20200503 憲法記念日
20200504 みどりの日
20200505 こどもの日
20200506 振替休日
20200720 海の日
20200921 敬老の日
20200922 秋分の日
20201012 体育の日
20201103 文化の日
20201123 勤労感謝の日
20201223 天皇誕生日

「山の日」を追加した2016年から2017年までの祝日一覧

上記でAppleから提供されているICSファイルから2015年から2020年までの祝日一覧を取得して見ましたが、2016年から追加された「山の日」は考慮されていませんでした。
一方でGoogleから提供されているICSファイルは2016年から追加された「山の日」が考慮された最新のデータが反映されています。
ただし、Googleから提供されているICSファイルは随時更新されているものの、取得できるデータは現在の年の前後1年だけのようです(例:現在2016年ならば2015年~2017年が取得可能)。
下記はGoogleから提供されているICSファイルを使用して、祝日取得シェルスクリプトを実行し、2015年から2017年までの祝日一覧を取得した結果です。

2015年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2015
20150101 元日
20150112 成人の日
20150211 建国記念の日
20150321 春分の日
20150429 昭和の日
20150503 憲法記念日
20150504 みどりの日
20150505 こどもの日
20150506 振替休日
20150720 海の日
20150921 敬老の日
20150922 国民の休日
20150923 秋分の日
20151012 体育の日
20151103 文化の日
20151123 勤労感謝の日
20151223 天皇誕生日

2016年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2016
20160101 元日
20160111 成人の日
20160211 建国記念の日
20160320 春分の日
20160321 振替休日
20160429 昭和の日
20160503 憲法記念日
20160504 みどりの日
20160505 こどもの日
20160718 海の日
20160811 山の日
20160919 敬老の日
20160922 秋分の日
20161010 体育の日
20161103 文化の日
20161123 勤労感謝の日
20161223 天皇誕生日

2017年の祝日一覧

[magtranetwork@localhost ~]$ ./get_holidays.sh 2017
20170101 元日
20170102 振替休日
20170109 成人の日
20170211 建国記念の日
20170320 春分の日
20170429 昭和の日
20170503 憲法記念日
20170504 みどりの日
20170505 こどもの日
20170717 海の日
20170811 山の日
20170918 敬老の日
20170923 秋分の日
20171009 体育の日
20171103 文化の日
20171123 勤労感謝の日
20171223 天皇誕生日
Reference: Tech Blog citing related sources