I've finished the iCal CFC. The code has not been heavily tested, so use with care. Here is an example use of it:
<cffile action="read" file="#theFile#" variable="data">
<cfset ical = createObject("component","ical")>
<cfset results = ical.getEvents(data)>
<cfloop index="x" from="1" to="#arraylen(results)#">
<cfset eventData = results[x]>
<cfoutput>
<cfif not structKeyExists(eventData,"summary")>
<h2>Unnamed Event</h2>
<cfelse>
<h2>#eventData.summary.data#</h2>
</cfif>
<cfset startDate = ical.icalParseDateTime(eventData.dtstart.data)>
<cfif structKeyExists(eventData,"dtend")>
<cfset endDate = ical.icalParseDateTime(eventData.dtend.data)>
<cfelseif structKeyExists(eventData,"duration") and eventData.duration.data is not "P1D">
<cfset endDate = ical.icalParseDuration(eventData.duration.data,startdate)>
<cfelse>
<cfset enddate = startdate>
</cfif>
#dateFormat(startDate,"mm/dd/yy")#<cfif dateFormat(startDate,"mm/dd/yy") neq dateFormat(endDate,"mm/dd/yy")> - #dateFormat(endDate,"mm/dd/yy")#</cfif><br>
<cfif structKeyExists(eventData,"description")>#eventData.description.data#</cfif>
<p/>
<hr>
</cfoutput>
</cfloop>
As you can see - there is one main method, getEvents, that will parse the events from an iCal string. (iCal also supports "TODO"s I believe, and I'll look into adding support for that later.) I've also added a few supporting functions. iCalParseDateTime will parse the datetime strings in iCal files. iCalParseDuration will translate the duration value by adding it to a passed in date (such as the starting date).
You can download the code here.
Archived Comments
Why not use init() instead of getEvents() since you are initializing your iCal object with the data? Calling init() on objects is a good habit to get into and so is providing a standardized constructor-like API...
Because the CFC will eventually support getting toDos from the data as well. Or did you mean making the init take the data string and _keeping_ getEvents, but w/ no args? Ie (and not sure how well the code will look here)
ical = createObject("component",ical).init(data);
events = ical.getEvents();
Yes, sorry, I wasn't clear: I meant, to initialize the ical object with the data. Then call a variety of methods to get whatever data you want.
If you're only going to use it as a service to parse whatever data you pass then getEvents(data) and getToDos(data) would make sense (but you wouldn't really want to parse the data each time, right?).
Yeah - makes sense. Normally I'd say, "it's just a string funciton", but getEvents is very weighty. No need to reparse each time it is run. What's cool is that I could add support for date filters (getEvents in the future), and having the events already parsed would save a lot of time. I'll do an update later on today.