Skip to content

Instantly share code, notes, and snippets.

@sdolenc
Last active June 23, 2023 14:25
Show Gist options
  • Save sdolenc/4a3dc2a8ef79cee1acdab625eb808c85 to your computer and use it in GitHub Desktop.
Save sdolenc/4a3dc2a8ef79cee1acdab625eb808c85 to your computer and use it in GitHub Desktop.
Import Recurring Events to Google Calendar

One method of quickly creating a lot of events in google calendar is to import a CSV file. However, there is no support for directly adding "recurring" events (birthdays, anniversaries, etc). Here's the workarond.

Summarized steps

  1. create csv file with events (no recurring)
  2. import csv into a new, temporary google calendar
  3. export temporary google calendar to an ics file
  4. edit ics file to change events into recurring
  5. import ics file into a new, permanent google calendar.
  6. delete temporary google calendar

Detailed steps

1. create csv file with events (no recurring)

The CSV format can be found at https://support.google.com/calendar/answer/37118?hl=en

example csv

2. import csv into a new, temporary google calendar

3. export temporary google calendar to an ics file

4. edit ics file to change events into recurring

4a. manually by adding RRULE:FREQ=YEARLY between each set of VEVENT begin/close statements. For example:

BEGIN:VEVENT
DTSTART;VALUE=DATE:20180520
DTEND;VALUE=DATE:20180521
RRULE:FREQ=YEARLY
...
END:VEVENT

or

4b. automatically by running this python

import icalendar
import os

def make_recurring():
    directory = os.path.dirname(__file__)
    with open(os.path.join(directory, 'noRecur.ics'), 'r') as fr:
        data = fr.read()

    cal = icalendar.Calendar.from_ical(data)
    for event in cal.subcomponents:
        if 'RRULE' not in event.keys():
            event.add('rrule', {'freq': ['YEARLY']})

    with open(os.path.join(directory, 'withRecur.ics'), 'wb') as fw:
        fw.write(cal.to_ical())

5. import ics file into a new, permanent google calendar.

6. delete temporary google calendar

Copy link

ghost commented Jul 21, 2021

Hello, sorry for dumb question but where is the output after running the python code?
I don't exactly know what I was supposed to do, I tried to put both .py and .ics file that I wanted to add RRULE YEARLY but after running the .py file nothing happens.

Was I supposed to specify wheres the input file located and the output file destination? It wasn't very clear in Step 4. I understand adding RRULE YEARLY manually but I need to edit 400 events :(

@sdolenc
Copy link
Author

sdolenc commented Jul 21, 2021

If I wrote this today then I would make the input/output file path user-provided parameters using typer

As it stands today: the input file is hardcoded as noRecur.ics and the output file is hardcoded as withRecur.ics. The python currently requires that noRecur.ics is in the same directory as the python file and it probably works best if withRecur.ics doesn't already exist (so delete or rename withRecur.ics if you run it multiple times)

Let me know how it goes. I'm happy to help further and make it work better.

@sdolenc
Copy link
Author

sdolenc commented Jul 21, 2021

another thing to consider: you need to pip install the icalendar python package if you haven't already done so

Copy link

ghost commented Jul 21, 2021

Hello, somehow I still can't get it to work :(

  1. I have done pip install icalendar
  2. Rename the calendar source to noRecur.ics
  3. Making sure theres no withRecur.ics file in the same folder
  4. Put both files in the same folder (.py and .ics), tried on its own folder and moved it to desktop but both still no output

I am executing the .py file with command prompt and this code "python test.py", it will give me warning if I didn't have icalendar installed. Tried with administrator command prompt but still no output.

The ICS file is exported from google calendar

@sdolenc
Copy link
Author

sdolenc commented Jul 21, 2021

Sorry to hear it isn't working yet. I need to add a bunch of recurring events to a calendar so I'll try this locally soon and get back to you around early August. For example: I might try out python-dateutil instead of icalendar, add typer for file name input, and I may temporarily deploy a small azure function that does this. Not sure yet

In the meantime: there are three other strategies you could try.

Let me know how it goes. Best of luck!

Copy link

ghost commented Jul 24, 2021

Sorry for late reply, I tried the notepad++ route and it works!
I'll try other options some other time since I needed to do this ASAP. But I just want to say thank you so much for sparing your time and helping me. I'll look forward to your new version :)

@Hsad1644
Copy link

Hsad1644 commented Aug 2, 2021

The code below is ready to use requiring you to add the path of the noRecur.ics file in __file__ (the one exported from the temp calendar)

Code

import icalendar
import os
__file__ = "" # paste full path of the noRecur.ics file here within the double quotes
# the directories can be separated using //
# EXAMPLE - C://Users//apa//OneDrive//Documents//[email protected]//noRecur.ics


def make_recurring():
    directory = os.path.dirname(__file__)
    with open(os.path.join(directory, 'noRecur.ics'), 'r') as fr:
        data = fr.read()

    cal = icalendar.Calendar.from_ical(data)
    for event in cal.subcomponents:
        if 'RRULE' not in event.keys():
            event.add('rrule', {'freq': ['WEEKLY']}) # /!\ Change frequency of recurrence as per requirement here in all caps
# WEEKLY, YEARLY and MONTHLY are valid not so sure about DAILY

    with open(os.path.join(directory, 'withRecur.ics'), 'wb') as fw:
        fw.write(cal.to_ical())


make_recurring()

Running the code

Once the code is saved on your system, say as test.py, open sh or cmd and type -

python test.py

@sdolenc
Copy link
Author

sdolenc commented Aug 2, 2021

Thanks @Hsad1644 !

I'll eventually try out your suggested version and update the gist accordingly 👍

@Hsad1644
Copy link

Hsad1644 commented Aug 3, 2021

Thanks @Hsad1644 !

I'll eventually try out your suggested version and update the gist accordingly 👍

Its pretty much the same thing
I just added some comments and that one line to call make_recurring() 😃

Aimed at python amateurs. That's all.

Much thanks for this. I'm trying to incorporate it into a web app which will be useful for preparing a timetable from an .xlsx file for students in my university.

@megalois
Copy link

Great work, thanks!

@dzigner
Copy link

dzigner commented Feb 3, 2022

@Hsad1644
Just ran the python code - thank you. it works.

@sdolenc
Copy link
Author

sdolenc commented Feb 3, 2022

@dzigner i think running
pip install icalendar
will fix this

https://pypi.org/project/icalendar/

@dzigner
Copy link

dzigner commented Feb 3, 2022

@sdolenc
I have updated my comment - thanks

@gprehder
Copy link

Thank you for the code, it help me a lot!! One question, I've tried different ways but I didn't get it to work with recurring UNTIL. I always get an error stating that I should use datetime, but it does not work.

Thank you

@abvgu
Copy link

abvgu commented Jan 9, 2023

Greetings! I needed to bulk upload a lot of annual events to the Google calendar. Your code worked great. Thanks a lot!

@okimselim
Copy link

Why waste time with python? Just open the .ics in a text editor and find/replace all

END:VEVENT

with

RRULE:FREQ=YEARLY
END:VEVENT

Done in 2 seconds.

@Hsad1644
Copy link

Hsad1644 commented Feb 13, 2023

Yeah I lost that script to my cache memory xP (so thanks for your comment since you led me back to it). This is what i do now. alt + D on vscode helps a bunch because I use this for making my semester's weekly schedule.

The script was more like a solution to add to an app that I have planned to make for our uni.

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