GASで祝日一覧(年月日と祝日名)データをJSON出力するAPIを作成
PHPのシステム案件で祝日を取得し、処理を行う箇所があった。GoogleカレンダーのAPIに接続してどうこうしようかと考えたが、カレンダーAPIを使ったことが無いのと、GoogleMapsAPIみたいにAPIキーが必須だった場合、クライアント様にキーを発行いただく必要がありその辺りが面倒だった。結局のところ他所様のAPIを使用して実装したが、よくよく考えればこういった時こそGoogle Apps Scriptの出番じゃないかと思った。以下に祝日APIの作成方法をメモ。
目次
やりたいこと
今年と来年の祝日一覧(年月日と祝日名)をJSON出力するAPIを作成したい。
APIリクエスト時にGoogleログイン認証は不要だが、GoogleMapsAPIのAPIキーのようにGETパラメータをつけることで認証させたい。もちろんキーが無い場合はデータを返さない。
法改正等による祝日の変更を考慮し、1日に1回Googleカレンダーから祝日データを引っ張ってきてスプレッドシートに保存・更新したい。
GAS側の作業
必要な作業はプログラムの作成、トリガーの設定、デプロイになる。
プログラムの作成
//スプレッドシートに祝日データを書き込む関数 function setHoliday(){ //開始年月日と終了年月日の指定 const now = new Date(); const start = now.getFullYear() + '-01-01'; const end = (now.getFullYear() + 1) + '-12-31'; //Googleカレンダーから祝日取得 const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com').getEvents(new Date(start), new Date(end)); //祝日データを整形して配列に格納 const result = []; for( var i = 0; i < calendar.length; i++ ){ result[i] = [ Utilities.formatDate(calendar[i].getStartTime(), 'JST', 'yyyy-MM-dd'), calendar[i].getTitle() ]; } //正常にデータが取得できた場合、スプレッドシートに書き込み if( result.length ){ //スプレッドシートの読み込み const sheet = SpreadsheetApp.getActiveSpreadsheet(); //シートを指定 const holidaySheet = sheet.getSheetByName('holiday'); //シートにまとめて書き込み holidaySheet.getRange(1, 1, result.length, result[0].length).setValues(result); } } //祝日データをJSON出力 function getHoliday(){ //スプレッドシートの読み込み const sheet = SpreadsheetApp.getActiveSpreadsheet(); //シートを指定 const holidaySheet = sheet.getSheetByName('holiday'); //シートのデータを取得 const holidaySheetVal = holidaySheet.getDataRange().getValues(); //年月日の整形 for( let i = 0; i < holidaySheetVal.length; i++ ){ holidaySheetVal[i][0] = Utilities.formatDate(holidaySheetVal[i][0], 'JST', 'yyyy-MM-dd'); } //データをJSON化 const payload = JSON.stringify(holidaySheetVal); //Textoutputオブジェクトを生成 const output = ContentService.createTextOutput(); //Mime TypeをJSONに設定 output.setMimeType(ContentService.MimeType.JSON); //データ出力 output.setContent(payload); return output; } //API呼び出し時に動作する関数 function doGet(e){ const key = e.parameter.key; const apiKey = 'xxxxxxxxxxxxxxxx'; if( key != apiKey ){ return ContentService.createTextOutput('アクセスできませんでした。'); } return getHoliday(); }
カレンダーデータ取得部分のエラー
「CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com')」の部分が動かず、以下のようなエラーメッセージが表示された。
TypeError: Cannot find function getEvents in object
GASで使うGoogleアカウントが最近取得したばかりでGoogleカレンダーを作成していなかった。Googleカレンダーを作成することで上記エラーが改善された。
他には以下のような場合もある模様。
https://teratail.com/questions/189134
http://syasuda.com/d/blog/2016/11/googleid.html
API呼び出し時
「const apiKey = 'xxxxxxxxxxxxxxxx';」の部分は適宜変更する。
年月日のフォーマット
「Utilities.formatDate(年月日データ, 'JST', 'yyyy-MM-dd')」でフォーマットする。フォーマット指定文字は以下の通り。
https://sites.google.com/site/gasgaidobukku/utilities/formatdate
APIリクエスト時のGETパラメータ取得
APIリクエスト時はdoGet関数が動作する。GETパラメータを取得したい場合は「e.parameter.パラメータのキー」で取得できる。リファレンスは以下の通り。
https://developers.google.com/apps-script/guides/web
トリガーの設定
setHoliday関数が1日1回動作するようトリガーを設定しておく。
デプロイ
「右上のデプロイボタン→新しいデプロイ」に進み「説明」は適当、「種類の選択」はウェブアプリ、「次のユーザーとしての実行」を自分、「アクセスできるユーザー」を全員で設定する。何故か初回デプロイ時は「アクセスできるユーザー」に全員の選択肢が無かった。「デプロイを管理→アーカイブ」で削除すると2回目以降からは全員を選択できた。
デプロイが完了するとURLが発行されるのでブラウザから開いてみると正常に動作した。尚、APIキーをGETパラメータとして付与するのを忘れないよう注意する。
API利用時の注意
GASの利用制限や上限にひっかからないよう、API利用時はデータを取得後にファイル化するのが良さそう。データとは別にファイルの有効期限を設定しておき、有効期限が切れていれば再度APIからデータを取得するような形が望ましいかと思われる。ざっくりとだけど以下のような形。
//祝日APIにリクエスト $api = file_get_contents('http://api.com/'); $holiday = json_decode($api, true); //JSONファイル用の制限時間 $holiday['limit'] = date('Y-m-d H:i:s', strtotime('+1 day')); //JSONファイル上書き保存 file_put_contents('./holiday.json', json_encode($holiday));
所感
GASはイマイチ業務での使いどころが思いつかないなぁ、とか考えながら勉強していたがやっと役に立ちそうなケースが出てきて嬉しい。
関連記事
-
GASでGoogleカレンダーと連携してイベントの取得・追加・削除
Google Apps Scriptの勉強としてGoogleカレンダーと連携させ ...
-
GASで「カクヨム」の更新状況をスクレイピングで取得する
Google Apps Scriptの勉強として「カクヨム」の指定した小説が更新 ...
-
GASを使ってみて感じたメリットとデメリット
Google Apps Scriptを色々勉強した中で感じたメリットとデメリット ...
-
GASとGoogleカレンダを連携し暦通りではない店休日を取得する方法
小売店等のサイトで営業日カレンダーみたいなものを表示させる際に今まではPHPで管 ...
-
GASを利用してGmailに届いたメール内容をGoogleスプレッドシートに記入する方法
WordPressのContact Form7から送信した内容をGmailで受け ...