Created
March 27, 2021 23:19
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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