This code
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
Logger.log(events);
var sp = PropertiesService.getScriptProperties();
sp.setProperty("events", JSON.stringify(events));
events = JSON.parse(sp.getProperty("events"));
Logger.log(events);
returns:
Info [CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent]
Info [{}, {}, {}, {}, {}]
Why is that? What is wrong?
Why is that?
CalendarEvent
is a Google Apps Script class which events are instances of.
Checking property ownership and enumerability yields the following:
function stringified() {
const event = CalendarApp.createAllDayEvent('Party', new Date());
const eventToString = JSON.stringify(event);
Logger.log(eventToString); // -> {}
Logger.log(Object.keys(event)); // -> []
Logger.log(Object.getOwnPropertyNames(event)); // -> [toString,...]
Logger.log(Object.getPrototypeOf(event)); // -> {}
Logger.log(event.toString()); // -> CalendarEvent
}
What does this tell us?
- there are no enumerable props we can access (see
Object.keys()
).
- there are own props (see
getOwnPropertyNames()
).
CalendarEvent
inherits from Object
1 (see toString()
).
Now, look at what JSON.stringify()
does for objects (this is a description from MDN, but if you dig into the ECMAScript spec, you will see that SerializeJSONObject
operation depends on abstract EnumerableOwnPropertyName
):
All the other Object instances (including Map, Set, WeakMap, and WeakSet) will have only their enumerable properties serialized
Which leads us to your second question:
What is wrong?
Since there are no enumerable own properties, the serialization results in "{}"
.
What to do?
It does not make much sense to store events with PropertiesService
- you will quickly get into quota issues on larger event collections even if you figure a way to store. What does, is to store a reference, so how about using getId()
method to store and getEventById()
to retrieve?
Sample
//...get event somehow
const store = PropertiesService.getUserProperties();
store.deleteProperty('events'); // demo only
const eventIds = store.getProperty('events') || '[]';
const id = event.getId();
const idList = JSON.parse(eventIds);
idList.push(id);
store.setProperty('events',JSON.stringify(idList));
Logger.log(store.getProperty('events'));
What else to do?
Use the Calendar API (don't forget to enablle it for your GCP project first by going to Resources
-> Cloud Platform project
-> APIs and Services
-> Library
). This API is a REST API that you can query with good old HTTP requests like that:
function listEvents() {
const calendar = CalendarApp.getCalendarById('yourEmailHere');
const endpoint = `https://www.googleapis.com/calendar/v3/calendars/${calendar.getId()}/events`;
const query = {};
const preparedQuery = Object
.entries(query)
.map(param =>`${param[0]}=${param[1]}`)
.join('&');
const resp = UrlFetchApp.fetch(`${endpoint}?${preparedQuery}`,{
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
}
});
if(resp.getResponseCode() === 200) {
//process the response
}
}
Note that one would have to set the OAuth scope to be passed with the JWT token (obtained by getOAuthToken()
). If there is an explicit scope list in application manifest (oauthScopes
field of appscript.json
), add "https://www.googleapis.com/auth/calendar.events.readonly"
or a more appropriate one.
Notes
- By this I mean that an instance of
CalendarEvent
has an object as its prototype due to prototypal inheritance.
- Usage of
getUserProperties()
is preferrable to getScriptProperties()
unless a script-wide setup is needed (see official guide in references). Script properties are shared across users and count toward quotas of the script owner.
- To use the second sample, V8 runtime has to be enabled (from the question sample it is unclear if it is used).
Reference
- Enumerability explanation on MDN
JSON.stringify()
docs on MDN
- Calendar events
getId()
docs
getEventById()
docs
- Calendar API reference
- OAuth scopes for Google APIs
PropertiesService
guide