# Export all calendars as zip file from Gcal to a folder (e.g. ~/Downloads). Run this file there. # Requires icalendar and isoweek. import csv from icalendar import Calendar, Event import datetime import glob import isoweek import subprocess import os import collections years = [2021, 2022, 2023] print("Taking you to https://calendar.google.com/calendar/u/0/r/settings/export to download your calendar. OK?") input() os.system('open https://calendar.google.com/calendar/u/0/r/settings/export') input('Press enter when you have downloaded the zip file.') # I presume you have downloaded the zip file to ~/Downloads downloads_folder = os.path.expanduser('~/Downloads') # Find the most recent zip file zip_file = max(glob.glob('%s/*.zip' % downloads_folder), key=os.path.getctime) # Unzip to ~/Downloads/tmpcalendar print('Unzipping %s...' % zip_file) subprocess.call(['unzip', zip_file, '-d', os.path.join(downloads_folder, 'tmpcalendar')]) calendar_folder = os.path.join(downloads_folder, 'tmpcalendar') # Set the input and output file paths ics_files = glob.glob('%s/*.ics' % calendar_folder) csv_file_path = os.path.join(calendar_folder, 'calendar.csv') # skip birthday calendars ics_files = [x for x in ics_files if 'Birthday' not in x] print("Found %s ics files" % len(ics_files)) print("Processing...") weeks_dict = collections.defaultdict(list) # add every week in the years to the weeks_dict for year in years: # iterate through all the weeks in the year for week in isoweek.Week.weeks_of_year(year): weeks_dict[week] = [] # Loop through all the ics files for ics_file in ics_files: # loop through all events calendar_name = ics_file.split('/')[-1].split('_')[0].replace('.ical', '') for event in Calendar.from_ical(open(ics_file, 'rb').read()).walk('vevent'): # Get the start date of the event event_start = event.get('dtstart').dt if event_start.year not in years: continue all_day = getattr(event_start, 'hour', None) is None # if not all day event, skip, unless it is an event that contains "Flight" if not all_day and 'Flight' not in event.get('summary'): continue # get the week number of the event week = event_start.isocalendar()[1] # get the year of the event year = event_start.isocalendar()[0] # append to the weeks_dict weeks_dict[isoweek.Week(year, week)].append([calendar_name, event]) weeks_dict = collections.OrderedDict(sorted(weeks_dict.items())) writer = csv.writer(open(csv_file_path, 'w')) writer.writerow(['Week', 'Year', 'Event1', 'Event2', 'Event3', 'Event4', 'Event5', 'Event6', 'Event7']) for week, events in weeks_dict.items(): # format week as something like Jan 1 - Jan 7 week_str = f'{week.monday().strftime("%b %d")} - {week.sunday().strftime("%b %d")}' # format year as something like 2020 year_str = f'{week.year}' row = [week_str, year_str] for event in events: # format event text as Summary (Calendar Name) event_text = '%s (%s)' % (event[1].get('summary'), event[0]) row.append(event_text) if len(row) == 8: break writer.writerow(row) print("Done! Output file is %s" % csv_file_path) print("Taking you to import it to Google Sheets...") os.system('open https://docs.google.com/spreadsheets/u/0/')