🎌

指定した日が日本の祝日かどうかをチェックする

に公開

先日とある社内の開発チームで、社員と業務委託メンバー間で休暇や不在予定を共有する手段がなかったため、スプレッドシートで簡単なカレンダーを作成し、共有ができるようにしました。

その際、毎月新しくシートを作成し、その月のカレンダーを前の月のカレンダーからコピーする、という作業を手動でやるのは明らかにめんどくさいと思い、来月のカレンダーを作成する処理をGASで自動化しました。

そのカレンダーでは休日の列を分かりやすく色分けしようと思い、GASで休日判別処理を実装していましたが、土日は Date クラスを使って簡単に曜日判別ができますが、祝日をどうするべきかを悩みました。

最終的に、これがベストじゃないかという実装が思いつきましたので、紹介します。

ソースコード

工夫した点

祝日データの取得方法

簡単に祝日一覧の取得処理を実装したいなと思った場合、祝日一覧を取得するAPIを提供してくれるサービスを利用する方法があります。

  • Holidays JP API
    • キーが日付、値が祝日名となっているオブジェクトの配列を返す方式なので、シンプルで扱いやすい構造となっていますが、アプリ内で定義したclassやstructにマッピングして利用する場合は少々工夫が必要になるかもしれません。
  • 国民の祝日API
    • date name type の3つのキーが定義されたオブジェクトの配列をレスポンスとして返してくれるため、各アプリで作成したclassやstructにマッピングするような作りにしたい場合はこちらを利用します。

ただし、これらのサービスはサービス提供者側でメンテナンスができなくなるなどの理由で突然サービスが終了する可能性があります。そこで、より確実に、正確な祝日一覧が必要な場面では、政府が公式で提供しているデータを利用する方が良いでしょう。

https://data.e-gov.go.jp/data/dataset/cao_20190522_0002/resource/d9ad35a5-6c9c-4127-bdbe-aa138fdffe42

上記のサイトでcsvファイルのURLが提供されていますので、今回はこちらを利用しました。

csvファイルの文字コード問題

普段、アプリケーション内で文字列を扱う際、文字コードは基本 UTF-8 になっていることがほとんどではないかと思います。このGAS内で文字列データを扱う際も、基本的には UTF-8 となっています。

しかし、政府が提供しているcsvデータの文字コードは Shift_JIS (正確には Microsoftコードページ932 (MS932) ) となっているため、そのまま取得しGAS上で扱おうとすると文字化けが発生してしまいます。

そのため、csvデータ取得時に文字列を Shift_JIS として読み込み、 UTF-8 上で扱えるようにしました。

const response = UrlFetchApp.fetch(GOV_HOLIDAY_URL);
const holidaysCache = response.getBlob().getDataAsString("MS932");

祝日データのキャッシュ

毎回csvデータをWeb上から取得するのは効率が悪いのと、祝日一覧は滅多に更新されない(おそらく年に1〜3回ぐらい?)ため、取得したらある程度の期間キャッシュをしておき、そのキャッシュが生きている間はそのデータを利用するようにしました。

GASでは、キャッシュを扱うための CacheService というクラスがあり、それを通してキャッシュの設定・取得をすることができます。しかし、ドキュメントを見ると設定できる有効期限が最大でも6時間となっていました。

https://developers.google.com/apps-script/reference/cache/cache-service

https://developers.google.com/apps-script/reference/cache/cache

今回、キャッシュの有効期限として最低でも1日以上を指定したかったため、上記の CacheService は使わず、代わりに同様に値を保存できる PropertiesService を利用しました。

https://developers.google.com/apps-script/guides/properties

こちらに取得した祝日一覧と、最後に取得した日時を保存しています。

そして、祝日一覧判定処理の呼び出し時、キャッシュがあるかどうかのチェック後、最後に祝日一覧を取得した日時と現在日時を比較し、あらかじめ決めておいたしきい値を超えていたら、期限切れとしてWeb上から再取得するよう実装しました。(上記ソースコードでは、しきい値を1日としています)

それにしてもGASって便利ですよね〜〜〜

よく簡単に自動化を実現したいと思った時は、まずGASで実装することが多いです。

文法はほぼJavaScriptなので、そのプログラミング言語自体を知っている人も多く、誰でもメンテナンスができるし、何時間おき/1日おき/1週間おきのようなバッチ処理のバックエンドとしても使え、しかもそれらが基本無料で利用できるので、本当に便利に使わせてもらっています。

これからもどんどん活用していければなと思います。

Discussion