色々な国の祝日が見れるカレンダーアプリを作った
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」を確認することが出来ます。
このカレンダー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ほど遅らせて処理をするようにしました。
これでだいぶブラウザの動作が軽くなりました。
まとめ
割と簡単に出来るかな、と考えてましたが、祝日を取得する部分やパフォーマンスなど考えなければならないことも多く、予想よりも時間がかかってしまいました。
また、パフォーマンスに関しては、カレンダーで表示してる月で祝日データをフィルタするなど、まだまだ改善の余地はあるので、時間見つけてやっていこうと思います。
実際に作ってみると、知らなかった・わからなかった部分が炙り出せるので、思いついたものは作ってみないとな、と改めて実感しました。
この記事が気に入ったらサポートをしてみませんか?