Add Multiple Timezones to a Google Calendar


The unoptimized values are hardcoded and not sensitive to the date changing. That is, local timezone changes like Daylight Savings Time will not be properly reflected in this data set. This should only be used for prototyping, not usage in production.

We recommend avoiding Daylight Savings Time in prompts if possible. If not, see for dynamically updating new values


❡Viewing events

After all this work, it will be a shame not to see the data we’ve imported. Therefore let’s bootstrap a little page that lists all of our events ordered by descending starting time (from most recent to oldest).

First, we need to create a query that accesses all of the events from a given user. Unfortunately we cannot use the hasManyThrough relationship since the Event model is three levels deep from the User model. That is, we could fetch the calendars (User → GoogleAccount → Calendar) but not one level deeper.

There is actually a package that defines a new Laravel relationship called hasManyDeep which would allow us to reach the Event model from the User model. However, for the purpose of this article, I’d rather not include yet another package. So here is my quick and simple implementation:

Okay next, let’s create an EventController with only one index action.

Finally let’s define a route for this.

If you’d like to see the front-end’s code, please check the changes on GitHub below.

Here is what my (made up) calendar events look like on the Google calendar app.

Here is what they look like on our application. 🍺

Here is what they look like on our application. 🍺

🐙 See changes on GitHub

🐙 See changes on GitHub



The user model stays the same but gets a hasMany relationship to the GoogleAccount model.


Every model that comes from the Google API, i.e. GoogleAccount, Calendar and Event have a column google_id which keeps track of the identifier of the resource that Google understands. This will be helpful at a later stage to know if we need to create a new resource or simply update an existing one.

For the GoogleAccount model, it will be helpful to ensure a user doesn’t enter twice the same account. This model also has a name (typically the email address of the account) and an authentication token which is stored as JSON.


Aside from its name and google_id, our simplified Calendar model also has a color and a timezone.


Finally our Event model has a name, a description and a starting and ending datetime with an allday flag letting us know if we should ignore the time of our datetime columns.

Instead of just casting our datetime columns, we provide custom accessors to incorporate the calendar’s timezone into the parsed Carbon instance. We also define an accessor to retrieve the event’s duration.

🐙 See changes on GitHub


currentTimezone a string like “America/Chicago”. Consult for a full list.
editable whether to allow dragging/resizing (default: false)
className CSS class to attach to each event
Any of the other Event Source options…


Next, you must have all the required js/css files. This includes the standard fullcalendar.js and fullcalendar.css, in addition to gcal.js:

<script type=‘text/javascript’ src=‘fullcalendar/gcal.js’></script>



To build the latest set of assets, run:

Human friendly timezones

We have set up human friendly timezones via google-calendar-tz.json, cleanup-google-calendar-tz.js, and tz-locales.json

To refresh the data for tz-locales.json (final result), perform the following steps:

  1. Go to Google Calendar ()
  2. Open “Create” page for a new event
  3. Open “Network” tab in developer tools
  4. Click “Timezone”
  5. Download “POST ” response body to google-calendar-tz.json
  6. Run npm run build-locales

Country codes

We have set up human friendly timezones via google-calendar-countries.json, cleanup-google-calendar-countries.js, and country-codes.json

To refresh the data for country-codes.json (final result), perform the following steps:

  1. Go to Google Calendar ()
  2. Open “Create” page for a new event
  3. Click “Timezone”
  4. Inspect the “Countries” element
  5. Download $0.outerHTML to google-calendar-countries.html
  6. Run npm run build-country-codes