--- /dev/null
+#!/usr/bin/env python
+
+# Dan White <dan@whiteaudio.com>
+
+# public domain
+
+import datetime
+import sys
+import time
+
+import pytz
+import vobject
+
+#testing
+#sys.argv[1] = 'basic.ics'
+#sys.argv.append('-')
+
+centralTime = pytz.timezone('America/Chicago')
+
+datefmt = '%b %d %Y'
+timefmt = '%H:%M'
+remfmt_datetime = 'REM %s AT %s DURATION %s MSG %%"%s%%" [t()]%%'
+remfmt_date = 'REM %s *1 UNTIL %s MSG %%"%s%%" [t()]%%'
+
+# one year out
+fromDate = datetime.datetime(2010,1,1, tzinfo=centralTime)
+untilDate = fromDate + datetime.timedelta(days=365.25*4)
+
+if sys.argv[1] == '-':
+ infile = sys.stdin
+else:
+ infile = open(sys.argv[1])
+
+if sys.argv[2] == '-':
+ outfile = sys.stdout
+else:
+ outfile = open(sys.argv[2], 'wb')
+
+cal = vobject.readOne(infile)
+
+
+for event in cal.vevent_list:
+ text = event.summary.value
+
+ #print event
+
+ # TODO: handle all-day events of +1 day duration
+
+ #detect all-day events vs. times
+ if isinstance(event.dtstart.value, datetime.datetime):
+ dtstart = event.dtstart.value.astimezone(centralTime)
+ dtend = event.dtend.value.astimezone(centralTime)
+ elif isinstance(event.dtstart.value, datetime.date):
+ #cannot handle this yet
+ continue
+ #dtstart = event.dtstart.value
+ #dtend = event.dtend.value
+ else:
+ raise TypeError('unknown dtstart type: %s (%s)' %
+ (event.dtstart.value, type(event.dtstart.value)))
+
+ duration = str(dtend - dtstart)[:-3]
+
+
+ if event.rruleset:
+ for dtstart in event.rruleset.between(fromDate, untilDate, inc=True):
+ print >>outfile, remfmt_datetime % (
+ dtstart.strftime(datefmt),
+ dtstart.strftime(timefmt),
+ duration, text)
+ else:
+ print >>outfile, remfmt_datetime % (
+ dtstart.strftime(datefmt),
+ dtstart.strftime(timefmt),
+ duration, text)
+
+
+
+