BREEZEの社内では1日の時間管理を行うときに、
12:00から13:00までの休憩時間や、
始業終業時間でアラーム鳴らしてたりしています。

リモートワークを進めざるを得ない昨今では、
遠隔で時間管理を行う必要が出てきました。

「SlackでBot流すか、、、」

となり、色々と試行錯誤した結果、
祝日判定する必要が生まれたので、
実装することに。

導入背景

APIの導入

Slackにはリマインダー機能ついています。
簡単な方法でいくかと思ったものの、
既にSlackをAPIを導入しているし、
メッセージ管理もしたいので、
Slack API Botを導入する方向で確定。

運用してみて

バッチサーバーに入れてcrontab にcurlコマンドでAPI叩けば
定時にPOSTできるプログラムの完成

0 10 * * 1-5  curl -XPOST -d "token=xxxxx" -d "text={通知内容}" -d "username={ユーザー名}" -d "channel={channelid}" "https://slack.com/chat.postMessage"
0 12 * * 1-5  curl -XPOST -d "token=xxxxx" -d "text={通知内容}" -d "username={ユーザー名}" -d "channel={channelid}" "https://slack.com/chat.postMessage"

crontabで平日の定時に通知させれば完成。

。。。とはいかず。
休日に通知はいかないものの、
祝日に通知はcrontabでは制御はできない、、、。

ので、
祝日だろうがお構いなしに通知するサーバには入れず、泣く泣く自分の端末(Mac)にバッチ入れることに。

まあ、休日祝日はPCいじらないかなーと思いきや。
長期休暇で緊急事態宣言発令中の昨今のゴールデンウィーク。
やることはないので、
勉強して時間過ごす可能性大。
となるとPCいじる可能性も大。

ということで、
祝日判定を実装することにしました。

祝日判定の方法

前置きが長くなりましたが、
ここからが本題です。
今回はshellscript (シェルスクリプト) で実装することにしました。
ソースコードはGitHubからご自由にお使いください。 https://github.com/bzgwhite/japanese_happy_holiday

現在はMac(BSD系)のみ対応です。

この記事では祝日のアルゴリズムを解説していきます。
ざっくりいうと祝日判定のアルゴリズムは5種類ありました。

  • 特定の日にちが祝日になる
  • 特定の曜日が祝日になる
  • 天文学的に祝日を決定する
  • 特例措置で祝日が決定する
  • 国民の休日

まずは祝日一覧です。

祝日一覧

元旦1月1日
成人の日1月第2月曜日
建国記念日2月11日
天皇誕生日2月23日
春分の日春分日
昭和の日4月29日
憲法記念日5月3日
みどりの日5月4日
こどもの日5月5日
海の日7月第3月曜日
山の日8月11日
敬老の日9月第3月曜日
秋分の日秋分日
スポーツの日10月第2月曜日
文化の日11月3日
勤労感謝の日11月23日

それぞれの祝日を割り振ると下記になります。

特定の日にちが祝日になる
元旦、建国記念日、昭和の日
昭和の日、みどりの日、こどもの日
山の日、文化の日、勤労感謝の日

特定の曜日が祝日になる
成人の日、海の日
敬老の日、スポーツの日

天文学的に祝日が決まる
春分の日、秋分の日

国民の休日
数年に一度発生
(現在の祝日制度なら敬老の日が月曜日で秋分の日が23日になる場合の9月22日)

特定の日にちが祝日になる

これが一番シンプルですね。
「指定した日付が特定の祝日に該当すれば祝日と判定」です。
ただし日曜日が該当すると振替休日を設ける必要があります。

この場合は、 「指定した日付の翌日が月曜日ならば振替休日」 です。

なので 「指定した日付が特定の祝日または指定した日付が特定の祝日の翌日かつ月曜日」 になります。

特定の曜日が祝日になる

大抵の場合は第n週の月曜日と指定されておりました。
例えば成人の日は1月の第2月曜日と定義されています。
1月の第2月曜日を出すには、 2回目の月曜日になる最短日と最長日を算出することです。
カレンダーを見ながら算出していきます。


最短日は第1週の1日が月曜日ならば、第2月曜日の最短日は8日です。
計算式は1+n*7。
最長日は第1週の1日が火曜日ならば、第2月曜日の最短日は14日です。
計算式は7+n*7

天文学的な数値で計算して算出する

これはかなり難しく参考サイトをご覧ください。
参考 秋分の日春分の日
http://koyomi.vis.ne.jp/reki_doc/doc_0330.htm

特例措置で祝日が決定する

イレギュラーで決定する場合です。 2020年は東京オリンピックの対応として下記となっておりました。

海の日7月23日
スポーツの日7月24日
山の日8月11日

これについては都度対応する必要があります。

国民の休日

ごく稀ですが、下記のような休日が適応される年も存在します。

当時の国民は飛び石連休の
解消や改善を望んでおり
それら世論に応える形で
1985年12月27日に
祝日法が改正されました。
それに伴って導入された
国民の休日は
祝日と祝日に挟まれた平日を
休日にするという制度です。



引用:国民の休日って知ってますか?
http://msch24.com/nationalholiday/

次回適応されるのは2026年だそうです。

終わりに

祝日判定は勤怠管理や営業日管理などで活かせます。
汎用性高い気がするものの、情報が多くない気がする。。。

需要あればLinux版も追加予定。

参考にしたサイト:
指定年の・日本の祝日日付一覧
http://koyomi.vis.ne.jp/sub/syukujitsu_table.htm
国民の祝日について – 内閣府
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
30日と31日ある月の覚え方!どうして2月は28日しかないの? – 気になる話題・おすすめ情報館
https://netwadai.com/blog/post-2852

作者情報
バックエンドエンジニア。Sier企画提案営業6年。独学1年を経て営業とエンジニアの職種並行期間1年。正式にエンジニアになり1年半経ちました。社内のIT教育推進担当としても邁進中。自身の開発環境のモダン化に挑戦中。ITに生きITに死す、我が人生。 公式Twitter