Skip to content

Instantly share code, notes, and snippets.

@kwcooper
Created March 27, 2021 23:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwcooper/5a028b54aff942b43602c196e9b5e9f7 to your computer and use it in GitHub Desktop.
Save kwcooper/5a028b54aff942b43602c196e9b5e9f7 to your computer and use it in GitHub Desktop.
Never miss a birthday! Create an ics calendar file from a spreadsheet of birthdays
# Computes an ICS file of birthdays from a spreadsheet
# spreadsheet in the format of
# Name - persons name
# Date - Birthdate in %m/%d/%Y format
# Description - some links or other info you want to add
# this is built ontop of ICSps
# https://icspy.readthedocs.io/en/stable/
# install with pip install ics
# Extentions to scrape your social media friends are reccomended
# to produce the data
# Tested and works successfully with google calendar
# KWC 210327
from ics import Calendar, Event, parse
import pandas as pd
from datetime import datetime, timedelta
def build_event(name, date, date_end, description=''):
"""
Builds a ics bday event based on the input data
inputs:
name - string of the persons name
date - string of the date to add ("%Y%m%d") format
date_end - string of the end date to add ("%Y%m%d") format
descripton = optional string
outputs:
birthday event object
"""
e = Event()
e.name = name
# e.begin = date # adds weird timestamp to the end...
# e.end = date_end
e.extra.append(parse.ContentLine(name="DTSTART;VALUE=DATE", value=date))
e.extra.append(parse.ContentLine(name="DTEND;VALUE=DATE", value=date_end))
e.extra.append(parse.ContentLine(name="RRULE", value="FREQ=YEARLY"))
e.extra.append(parse.ContentLine(name="DESCRIPTION", value=description))
return e
def edit_year(dte):
"""
Computes the year needed based on the current
date for the date object
inputs:
dte - a datetime object of the date to examine
outputs:
year - an integer of the proper year
"""
today = datetime.today()
# If the year has already passed, then we should set
# the first calendar event for the next year
if (today.month > dte.month):
if (today.day > dte.day):
yr2add = today.year + 1
else:
yr2add = today.year
else:
yr2add = today.year
return yr2add
## Load in the birthday data
fName = 'birthday-calendar_edit3.csv'
data = pd.read_csv(fName)
data = data.drop(columns=['Unnamed: 4']) # based on the data
## Compute events and read them to a file
nEvents = 0
# Write data events to the ICS or TXT file
c = Calendar()
for index, row in data.iterrows():
name = row['Subject'] + '\'s BDAY!'
# format the date; assumes "%d/%m/%Y" format
dte = datetime.strptime(row['Start Date'], "%m/%d/%Y")
# Compute the proper year and format the date
yrNew = edit_year(dte)
dte2add = datetime(yrNew, dte.month, dte.day)
date_start = dte2add.strftime("%Y%m%d")
dte2add2 = dte2add + timedelta(days=1)
date_end = dte2add2.strftime("%Y%m%d")
description = row['Description']
e = build_event(name, date_start, date_end, description)
c.events.add(e)
nEvents += 1
print(f'\nCreated {nEvents} events!')
## Write the calendar object to a txt file
with open('testWrite.txt', 'w') as my_file:
my_file.writelines(c)
## Write the calendar object to a ics file
with open('testWrite.ics', 'w') as my_file:
my_file.writelines(c)
## Optional birthday stats
# Look at the breakdown by month...
import numpy as np
import matplotlib.pyplot as plt
mnthCnt = np.zeros((1,12))
for index, row in data.iterrows():
# format the date; assumes "%d/%m/%Y" format
dte = datetime.strptime(row['Start Date'], "%m/%d/%Y")
mnthCnt[0,dte.month-1] += 1
bars = [c for c in mnthCnt[0]]
plt.bar(range(1,13), bars)
plt.xticks(range(1,13), range(1,13))
plt.title('Birthdays Per Month')
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment