Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Pull events from a public Google Calendar using the Google Calendar API. Based off of: https://stackoverflow.com/a/56496854/908059
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Google Calendar API</title>
</head>
<body>
<h1>Events:</h1>
<div id="js-gcal-event">
<!-- SVG loader By Sam Herbert (@sherb). http://goo.gl/7AJzbL -->
<svg aria-hidden="true" width="35" height="35" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#2c2a29"><g fill="none" fill-rule="evenodd" stroke-width="2"><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/><animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/></circle><circle cx="22" cy="22" r="1"><animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/><animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/></circle></g></svg>
<p>Loading...</p>
</div>
<p>Solution from László L. L. on <a href="https://stackoverflow.com/a/56496854/908059">Stack Overflow</a>, modified to use lighter dependencies (MomentJS > DayJS, jQuery > vanilla javascript).</p>
<script src="https://cdn.polyfill.io/v3/polyfill.min.js?version=3.52.1&features=Array.prototype.forEach,console,Date.prototype.toISOString,document,Intl,Map,Promise,Set"></script>
<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script>
<script src="https://unpkg.com/dayjs@1.8.23/plugin/localizedFormat.js"></script>
<script>dayjs.extend(window.dayjs_plugin_localizedFormat)</script>
<script src="https://apis.google.com/js/api.js"></script>
<script src="google-calendar.js"></script>
</body>
</html>
/* This solution makes use of "simple access" to google, providing only an API Key.
* This way we can only get access to public calendars. To access a private calendar,
* we would need to use OAuth 2.0 access.
*
* Solution from László L. L. on Stack Overflow:
* https://stackoverflow.com/a/56496854/908059
*
* Dependencies: day.js & the localizedFormat plugin for day.js:
* https://day.js.org/en/
*
* "Simple" vs. "Authorized" access: https://developers.google.com/api-client-library/javascript/features/authentication
* Examples of "simple" vs OAuth 2.0 access: https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
*
* We will make use of "Option 1: Load the API discovery document, then assemble the request."
* as described in https://developers.google.com/api-client-library/javascript/start/start-js
*/
function printCalendar () {
// The "Calendar ID" from your calendar settings page, "Calendar Integration" secion:
var calendarId = 'YOUR_CALENDAR_ID@group.calendar.google.com';
// 1. Create a project using google's wizzard: https://console.developers.google.com/start/api?id=calendar
// 2. Create credentials:
// a) Go to https://console.cloud.google.com/apis/credentials
// b) Create Credentials / API key
// c) Since your key will be called from any of your users' browsers, set "Application restrictions" to "None",
// leave "Website restrictions" blank; you may optionally set "API restrictions" to "Google Calendar API"
var apiKey = 'YOUR_API_KEY';
// You can get a list of time zones from here: http://www.timezoneconverter.com/cgi-bin/zonehelp
var userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (!userTimeZone) {
userTimeZone = 'America/New_York';
}
// Initializes the client with the API key and the Translate API.
gapi.client.init({
'apiKey': apiKey,
// Discovery docs docs: https://developers.google.com/api-client-library/javascript/features/discovery
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest']
}).then(function () {
// Use Google's "apis-explorer" for research: https://developers.google.com/apis-explorer/#s/calendar/v3/
// Events: list API docs: https://developers.google.com/calendar/v3/reference/events/list
return gapi.client.calendar.events.list({
'calendarId': calendarId,
'timeZone': userTimeZone,
'singleEvents': true,
'timeMin': (new Date()).toISOString(), // gathers only events not happened yet
'maxResults': 20,
'orderBy': 'startTime'
});
}).then(function (response) {
console.log(response); // TODO: Remove!
if (response.result.items) {
var getNowPlayingDiv = document.getElementById('js-gcal-event'); // Make sure your HTML has This ID!
// Create a table with events:
var calendarRows = ['<table class="gcal-event"><tbody>'];
response.result.items.forEach(function (entry) {
var eventDate = dayjs(entry.start.dateTime).format('LLL'); // eg: March 26, 2020 6:00 PM
var eventEndsAt = dayjs(entry.end.dateTime).format('LT'); // eg: 7:00 PM
calendarRows.push('' +
'<tr class="gcal-event__tr">' +
'<td class="gcal-event__td-time">' +
'<time datetime="' + entry.start.dateTime + '" class="gcal-event__time-start">' + eventDate + '</time> - ' +
'<time datetime="' + entry.end.dateTime + '" class="gcal-event__time-end">' + eventEndsAt + '</time>' +
'</td>' +
'<td class="gcal-event__td-event-name">' + entry.summary + '</td>' +
'</tr>');
});
calendarRows.push('</tbody></table>');
getNowPlayingDiv.innerHTML = calendarRows.join('');
}
}, function (reason) {
console.log('Error: ' + reason.result.error.message);
});
}
// Loads the JavaScript client library and invokes `start` afterwards.
gapi.load('client', printCalendar);
@bronze

This comment has been minimized.

Copy link

@bronze bronze commented Nov 2, 2020

hi there!
I was getting my current date/time instead of the event date. My html looked like this: <time datetime="undefined" class="gcal-event__time-start">
It seems their response has changed on entry.start.dateTime to entry.start.date

edit: it seems thats the response for all-day events, if you input a time, it responds with dateTime

@forumbaer

This comment has been minimized.

Copy link

@forumbaer forumbaer commented Mar 4, 2021

I included a short if else to avoid that issue for all-day events:
if (entry.start.date == undefined) {var eventDate = dayjs(entry.start.dateTime).format('DD.MM.YY H:mm');} // eg: March 26, 2020 6:00 PM
else {var eventDate = dayjs(entry.start.date).format('DD.MM.YY');}

@adamjohnson

This comment has been minimized.

Copy link
Owner Author

@adamjohnson adamjohnson commented Mar 4, 2021

👍 Good catch guys. Thanks.

@justoverclockl

This comment has been minimized.

Copy link

@justoverclockl justoverclockl commented Aug 13, 2021

i get a console error:

TypeError: e.fromNow is not a function
at o (humanTime.ts:32)
at s (humanTime.tsx:15)
at e.view (TerminalPost.js:26)
at Function.a (render.js:30)
at render.js:155
at render.js:160
at l (render.js:66)
at u (render.js:50)
at render.js:134
at l (render.js:63)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment