見出し画像

色々な国の祝日が見れるカレンダーアプリを作った

World Wide Holidays(WWH)という、色々な国の祝日が見れるカレンダーアプリを作ったので、その過程で得た知見を共有しようと思います。

ソースコード

使用した技術

フロントエンド
- Nuxt@2.11.0

国の情報取得元
REST COUNTRIES

祝日の情報取得元
- Google Calendar API

アプリホスティング先
- ZEIT Now

フロントエンドには普段、業務でも個人でも使い慣れているNuxtを使用しました。

様々な国の情報を得る必要があったため、調べたら REST COUNTRIES という国の情報をAPIで取得できるサービスがあったので こちらを利用しました。

各国の祝日の情報を取得できるAPIも色々調べたところ、有料だったり制限があるサービスだったりしました。
その中でも今回はGoogle Calendar API を利用することにしました。

理由は、Google Calendar API も制限があるのですが

The Google Calendar API has a courtesy limit of 1,000,000 queries per day.

と、1日に1,000,000リクエストが上限(それより上は有料)なので、さすがに1日でここまでのリクエストは来ないであろう & 上限を超えても1日後にはまた出来るだろう と考え Google Calendar API を利用することにしました。

アプリのホスティング先にはZEITのNowを利用しています。
今回、アプリのURLを

/:year/:month

といった感じで、動的にしたかったのでSPAにするか、SSRするかで迷いましたが、リダイレクトの処理を書く必要があるのが面倒に感じたのでSSRにしました。

Google Calendar API について

Google Calendar API には、「指定したカレンダーのイベントのリストを取得する」というAPIが存在します。
このAPIを利用して、各国の祝日を取得しました。

カレンダーの指定方法ですが、APIのパラメーターに calendarId というカレンダーを特定出来るIDを文字列として渡すことでカレンダーを特定できます。

この calendarId はかなり手探りなのですが 、例えば日本の祝日のカレンダーの calendarId は何になるかと言うと

ja.japanese#holiday@group.v.calendar.google.com

↑こんな感じになります。

Google Calendarに日本の祝日を追加して、その設定を開くと「カレンダーID」を確認することが出来ます。

画像1

このカレンダーIDは

{ISO 639-1の言語コード}.{国を特定できる文字列}#holiday@group.v.calendar.google.com

と言う感じです。

すべて確認できてませんが、「ISO 639-1の言語コード」は そのまま ISO 639-1 のものになると 思います…。ここをどの言語で取得したいかを指定すると、その言語でデータを取得することが出来ます。
そして、「国を特定できる文字列」が かなりやっかいで、ISO 3166-1 にある、alpha-2 か alpha-3 とかであれば良かったのですが、ISO 3166-1 のalpha-2 の場合もありますし、上記の日本のように(japanese)、そうではない場合もあります。

どういったときに ISO3166-1 の alpha-2 なのかそうではないのか、また、そうではなかった場合にどのような文字列になるのか、ルールのようなものが見つからなかったので、Google Calendarに各国の祝日のカレンダーを追加して、一つ一つ調べ alpha-2 とマッピング出来るデータを作りました…😭

このアプリを作るのに一番時間を使った部分だと思います。

もっとスマートな方法があれば良かったのですが、とりあえず、作りたかったので 力技で切り抜けました。

パフォーマンスについて

現在、祝日を取得できる国の数が220ほどあります。
祝日を取得すると1年分の祝日データを取得するようにしています。日本の2020年の祝日日数が16日なので、各国それくらいの祝日があると仮定すると、
220 × 16 = 3520 のデータ量になります。
また、カレンダーなので、一つの月で30日ほどあります。
その日が祝日かどうかを判定するには 30 × 3520 = 105600 回の処理が必要になってしまいます。

これをそのまま実行してしまうと さすがにブラウザの反応が悪くなってしまいました。

これを回避するため、以下の2つの方法を取りました。

Object.freeze でリアクティブなデータにしない
■ 処理するタイミングをずらして同時に処理させないようにした

Object.freeze でリアクティブなデータにしない

VueはVueインスタンスの data プロパティにオブジェクトを追加すると、変更を検知してくれるようになります。
これはものすごく便利なのですが、変更を検知する必要がないような場合もあります。
今回、取得した祝日のデータは 変更することが無く、単純にデータを参照するためだけに使用します。

そういった場合、オブジェクトを変更できないようにすると パフォーマンスが上がるようなので、早速やってみました。

これは以下の記事を参考にさせていただきました。

処理するタイミングをずらして同時に処理させないようにした

カレンダーの日数分 一気に祝日判定の処理を実行すると重いので、1日につき60msほど遅らせて処理をするようにしました。

これでだいぶブラウザの動作が軽くなりました。

まとめ

割と簡単に出来るかな、と考えてましたが、祝日を取得する部分やパフォーマンスなど考えなければならないことも多く、予想よりも時間がかかってしまいました。

また、パフォーマンスに関しては、カレンダーで表示してる月で祝日データをフィルタするなど、まだまだ改善の余地はあるので、時間見つけてやっていこうと思います。

実際に作ってみると、知らなかった・わからなかった部分が炙り出せるので、思いついたものは作ってみないとな、と改めて実感しました。

この記事が気に入ったらサポートをしてみませんか?