原本我有一個 Idea 是做一個簡單 APP 會告訴你離你時間上跟距離上最近的天文活動,比方說流星雨、滿月、日月食等。但我找來找去,都沒有找到一個可以用的 API (我還以為 NASA 會有呢)。我唯一找到的,是 The New York Times 出的天文太空行事曆,讓大家可以加到自己的 iCalendar 或 Google Calendar 裡。
既然沒有現成的 API 可以用,不如把這個行事曆加到我的 Google Calendar,再使用 Google Calendar API 把裡面的資料抓出來。
先在 Google Developer Console 裡建立新 project 跟取得 API Key:
(話說我覺得雖然Google 畫面都很好,但體驗做的挺莫名其妙的,某些有點難找)
在取得 credentials
那邊選擇 API Key
,然後就會得到一個放著 key 的視窗。
此時再去 APIs Library 啟用 Google Calendar API。
現在來看看如果想要取得某個行事曆上面的事件,應該怎麼做。
在這邊使用 APIs Explorer 來找找我想要的功能。
在裡面找到了 calendar.events.list
這一條,會傳回特定行事曆上的事件。
裡面唯一必選的參數是 calendarid
,那現在來找出太空行事曆的 id 是什麼。
先開啟 Google Calendar,然後在左側的 Calendar List 上面找到想要使用的行事曆。滑鼠 hover 過去的時候,行事曆選項會出現一個三個點的按鈕,點進去可以看到 setting
:
在裡面可以找到 Calendar ID。
把找到的 Calendar ID 放回剛剛的 APIs Explorer 裡面,按 Authorize & Execute
在這邊授權給 APIs Explorer 讓你可以透過他修改你的行事曆。(不過我們沒有要使用到修改行事曆的功能就是了)
點完之後往下滑,就可以看到 Request URL 跟 Response 了。
所以我們現在的 API Request URL 如下:
'GET', "https://www.googleapis.com/calendar/v3/calendars/nytimes.com_89ai4ijpb733gt28rg21d2c2ek%40group.calendar.google.com/events?key={YOUR_API_KEY}"
雖然說,用 APIs Explorer 就得到了 Request URL,但還是要來看一下文件。
Google Calender API 裡有許多不同 Resource Type 讓你抓不同東西,在這邊要注意的是,主要的幾個 Resource 看起來很像,需要區分一下。
CalendarList 跟 Calendars 的區別乍看之下有些難懂,以「新增行事曆 (insert)」來看的話,使用 Calendars 的 endpoint 時 insert
是指創造一個新的行事曆,在 CalendarList 的 insert 則是將某個(已經存在的)行事曆,加入你的行事曆集合,正如我把太空行事曆加進我的行事曆 UI 上一樣。
要取得特定行事曆資料時,使用 Calendars 的 endpoint 得到的會是特定行事曆的 metadata,比方說預設時區或創建日期等,不會得到事件資料。要使用 events 的 endpoint 才能夠抓到個別事件的時間地點等細節。
現在建立一個簡單的 XHR Request。
var apiKey = "AIzaSyBDrmP70p70pao_3RvPXGXTfBJKLHvdm1I";
var url = "https://www.googleapis.com/calendar/v3/calendars/nytimes.com_89ai4ijpb733gt28rg21d2c2ek%40group.calendar.google.com/events?key="+ apiKey + '&timeMin=2018-01-01T00%3A00%3A00-05%3A00';
function makeRequest() {
xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(this.responseText);
console.log(response);
};
xhr.open(
"GET",
url,
true
);
xhr.send();
}
makeRequest();
由於我想做的 APP 只會回傳時間上最近的事件,所以必須在 request URL 上加一個 timeMin 的參數,設定只回傳參數時間之後的事件。這個參數的時間就會是使用者當下的時間。
Google Calendar API 吃的參數必須是RFC3339 timestamp 的格式,然後在URL 裡面的時候還要 URL encoded。我直接拿他的範例 2011-06-03T10:00:00Z
來修改。
把 2011-06-03
跟後面 T10:00:00Z
分開,前面日期改成變數,後面時間從 10 點改成 0 點。接著使用了 Moment.js 插入時間跟把時間格式改好,程式碼如下:
// 因為 timeMin 參數是用事件結束時間過濾,所以多加一天
var t = moment().add(1, 'd').format('YYYY-MM-DD');
var url = "https://www.googleapis.com/calendar/v3/calendars/nytimes.com_89ai4ijpb733gt28rg21d2c2ek%40group.calendar.google.com/events?key="+ apiKey + '&timeMin='+ t +'T00%3A00%3A00Z';
然後在 xhr.onload()
裡面把 HTML 寫進去。
<div class="container">
<h1 class="summary"></h1>
<div class="time"></div>
<div class="desc"></div>
</div>
var title = document.querySelector('.summary');
var eventTime = document.querySelector('.time');
var description = document.querySelector('.desc');
xhr.onload = function() {
var response = JSON.parse(this.responseText);
var time = response.items[0].start.date+"~"+response.items[0].end.date;
var desc = response.items[0].description;
var summary = response.items[0].summary;
title.innerHTML = summary;
eventTime.innerHTML = time;
description.innerHTML = desc;
};
成果:
完整 Code => Codepen 連結