Friday, 18 January 2013

How to Import Birthdays and Anniversaries into Google Calendar


This is a quick bash script I made that reads a file of events and creates an ical file suitable for importing into Google Calendar.

Date file supports these event formats:

day/month event description
day/month/year event description

Brief Instructions

1. Cut and paste program into a text file.

2. Save file as pc-ssv-to-ical.bash (or whatever you like)

3. In a terminal, chmod +x pc-ssv-to-ical.bash

4. Make an event file (eg. special dates) lile this:
1/1 New Year
26/1 Australia Day
4/4/1914 Someon'es Birthday
5/5/1915 Bill/Jill Wedding (1915)

5. Run ./pc-ssv-to-ical.bash special.dates > cal-import.ics 
6. Import cal-import.ics into a Google Calendar

Script

#!/bin/bash


#    This script takes events from a file and outputs in ical format 
#    suitable for importing into a Google Calendar.
#
#    Copyright (C) 2013  phil colbourn
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    A copy of the GNU General Public License can be obtained from
#    .

SSV=$1

shopt -s extglob

# load special dates as day/month[/year] event description
# eg. 1/5/2004 A Person of Interest
# eg. 24/5 Not Sure When Born


# use this to convert SSV to CVS
# cat special-dates.ssv | sed 's/ /,/' > special-dates.csv


printf "BEGIN:VCALENDAR\nVERSION:2.0\nCALSCALE:GREGORIAN\n"


IFS+=","


while read DATE EVENT; do
    [[ -z $DATE ]] && continue               # ignore null dates
    # D/M[/Y] format
    D="0${DATE%%/*}"                         # get day part
    D="${D: -2}"   
    M="${DATE#*/}"                           # get month part
    M="0${M%%/*}"
    M="${M: -2}"
    # M/D[/Y] format
    #M="0${DATE%%/*}"                         # get month part
    #M="${M: -2}"   
    #D="${DATE#*/}"                           # get day part
    #D="0${D%%/*}"
    #D="${D: -2}"
    Y="${DATE/[0-9]?([0-9])[\/][0-9]?([0-9])/}"  # get year part
    Y=${Y//[\/]/}                            # remove left over /
    [[ -z $Y ]] && Y=$( date +%Y )           # use this year if none given

cat <
BEGIN:VEVENT
DTSTART;TZID=Australia/Sydney:${Y}${M}${D}
DTEND;TZID=Australia/Sydney:${Y}${M}${D}
RRULE:FREQ=YEARLY
DESCRIPTION:${EVENT}${Y:+ ($Y)}
SUMMARY:${EVENT}${Y:+ ($Y)}
END:VEVENT
EOF

done < $SSV

printf "END:VCALENDAR\n"

unset IFS

Notes

1. Code could be simplified if a more strict date format was used. eg. DD/MM[/YYYY]
2. Code will need to be changed for M/D[/Y] dates.
3. Space separated (SSV) and CSV formats both work. Quoted and double-quoted events also seem to work.