Sometimes I want to import a lot of events into my calendar – an example being a concert series – and the information is not in a format that allows easy import into my calendars.

I accomplish this with a simple two step process.

Side Note: This article was written in 2008 so some of the references may be out-of-date.

Create a CSV file

First I copy the information and paste it piece by piece into a spreadsheet.

This allows me to export it as a CSV or comma-separated-value format file

Convert to an iCalendar file.

Next I convert it into iCalendar format using a simple ruby utility.

Once in iCalendar format, I can import it into many calendar programs such as Lotus Notes at work and Google Calendar for my personal schedule.

The CSV File

A sample entry in the CSV file would be

2009-08-01, 20:00, 23:00,"This is the title","There are the details"

The order of the fields are event date as year-month-day, start and end times in 24 hour format, the title, and the description.

The Utility – csv2ical.rb –

This utility ports over the event date, start and end times, the title, and the description.

Usage is csv2ical.rb filename

The “.csv” extension on input filename is optional.

For example – csv2ical dancedates will convert dancedates.csv into dancedates.ics.

Files should be in the current working directory.

### 
### csv2ical.rb - A simple csv to iCal conversion utility written in Ruby
### 

### sample CSV
### 
### 2009-08-01, 20:00, 23:00,"summary 3 / description","location 3 is..."

require 'icalendar'
require 'csv'

    $argvFile = ""; $CSVFile = ""; $iCalFile = "";
  
    if ARGV[0] != nil then $argvFile = ARGV[0] end;
  
    if $argvFile.size < 1 then puts "Error: No CSV file specified.Usage is: csv2ical CSVFile.csv"; exit; end
    
    ## drop .csv extensions if entered
    ext = $argvFile.upcase[-4,4];
    if ext != nil then if ext == ".CSV" then $argvFile=$argvFile[0,$argvFile.size-4] end end
    
    # Build input file name
    $CSVFile=$argvFile + ".csv"
  
    # Build output file name
    $iCalFile = $argvFile + ".ics"

    puts "csv2ical - converting [#{$CSVFile}] to [#{$iCalFile}]"
    
    if !File.exist?($CSVFile) then puts "Error: CSV file specified does not exist."; exit; end
  
cal = Icalendar::Calendar.new

CSV.open("#{$CSVFile}", 'r') do |row|

    puts "processing #{row[0]} #{row[1]} #{row[2]} #{row[3]} #{row[4]} "

    event = cal.event
    event.timestamp = DateTime.now
    event.summary = row[3]
    event.description = row[3]  + "\n\n" + row[4]
    event.location = row[4] 
 
    start_date = Date.parse(row[0])
    start_time = row[1]
    event.start = DateTime.parse(start_date.to_s + " " + start_time)
 
    end_date = Date.parse(row[0])
    end_time = row[2]
    event.end = DateTime.parse(end_date.to_s + " " + end_time)

end

tcfile = File.new("#{$iCalFile}", "w+"); 
tcfile.puts cal.to_ical
tcfile.close;

puts "csv2ical - complete"

The iCalendar gem will create and populate UID (unique ID) values for each task being imported.

The iCalendar gem –

The iCalendar gem provides an easy way to read in your iCalendar file.

<b>Installing the icalendar gem</b>
<p>If you use RubyGems, run the following and select the newest version marked "ruby" --
<p>gem install icalendar

Code Snippets

1. Sample CSV File

2009-07-05,19:00,22:00,"Salsa Sundays ","The Forks"
2009-07-12,19:00,22:00,"Salsa Sundays ","The Forks"
2009-07-19,19:00,22:00,"Salsa Sundays ","The Forks"
2009-07-26,19:00,22:00,"Salsa Sundays ","The Forks"
2009-07-16,19:00,22:00,"Dancing under the Canopy Thursdays ","The Forks"
2009-07-23,19:00,22:00,"Dancing under the Canopy Thursdays ","The Forks"
2009-07-30,19:00,22:00,"Dancing under the Canopy Thursdays ","The Forks"
2009-08-06,19:00,22:00,"Dancing under the Canopy Thursdays ","The Forks"

2. csv2ical.rb

### 
### csv2ical.rb - A simple csv to iCal conversion utility written in Ruby
### 
    
### sample CSV
### 
### 2009-08-01, 20:00, 23:00,"summary 3 / description","location 3 is..."
    
require 'icalendar'
require 'csv'
    
    $argvFile = ""; $CSVFile = ""; $iCalFile = "";
  
    if ARGV[0] != nil then $argvFile = ARGV[0] end;
  
    if $argvFile.size < 1 then puts "Error: No CSV file specified.Usage is: csv2ical CSVFile.csv"; exit; end
    
    ## drop .csv extensions if entered
    ext = $argvFile.upcase[-4,4];
    if ext != nil then if ext == ".CSV" then $argvFile=$argvFile[0,$argvFile.size-4] end end
    
    # Build input file name
    $CSVFile=$argvFile + ".csv"
  
    # Build output file name
    $iCalFile = $argvFile + ".ics"
    
    puts "csv2ical - converting [#{$CSVFile}] to [#{$iCalFile}]"
    
    if !File.exist?($CSVFile) then puts "Error: CSV file specified does not exist."; exit; end
  
cal = Icalendar::Calendar.new
    
CSV.open("#{$CSVFile}", 'r') do |row|
    
    puts "processing #{row[0]} #{row[1]} #{row[2]} #{row[3]} #{row[4]} "
    
    event = cal.event
    event.timestamp = DateTime.now
    event.summary = row[3]
    event.description = row[3]  + "\n\n" + row[4]
    event.location = row[4] 
 
    start_date = Date.parse(row[0])
    start_time = row[1]
    event.start = DateTime.parse(start_date.to_s + " " + start_time)
 
    end_date = Date.parse(row[0])
    end_time = row[2]
    event.end = DateTime.parse(end_date.to_s + " " + end_time)
    
end
    
tcfile = File.new("#{$iCalFile}", "w+"); 
tcfile.puts cal.to_ical
tcfile.close;
    
puts "csv2ical - complete"