by: Shu-wai Chow
If you maintain a web calendar, the vCalendar/iCalendar specifications can help you share calendar events with users through your site. By clicking on a simple link to a text file, your events can be added to your users' Outlook, Palm Desktop, or scheduling program of their choice. Such an application can be easy, simple, and automated if the event data is stored in a database, and the text file is formatted to the vCalendar/iCalendar specification with any scripting language.
The vCalendar and iCalendar specifications are designed for platform and device neutral sharing of calendar and to-do items. Since its inception, the vCalendar specification has quietly gained ubiquitous support in software applications and spawned its successor, the iCalendar format. Most of the popular calendaring programs such as Outlook, Palm Desktop, and LotusNotes support one or both formats. Recently, iCalendar gained a big endorsement by being used to power Apple's iCal program.
In this article, I will run through the basic script setups needed, give a basic introduction to key vCalendar elements, and use PHP to format an example event. By the end, you should be able to share your calendars online.

Should I Use vCalendar or iCalendar?

As with most things in life, it depends. vCalendar has been around longer and enjoys wider adoption. Most software calendaring programs (iCal, Outlook 2000+ for Windows) support both vCalendar and iCalendar, some (Palm Desktop, Outlook 97) support only vCalendar, and a handful (Outlook and Entourage for Macintosh) support only iCalendar. Most of your WAP calendaring applications also support vCalendar.
On the other hand, iCalendar is the format of the future. The Outlook products have picked up iCalendar support and so will the next version of LotusNotes. Apache has default support for iCalendar enabled, but not vCalendar. If you're developing for vCalendar now, be aware of iCalendar.
Since this is an introductory article, I will be using the vCalendar specification in all of my examples with iCalendar exceptions noted. vCalendar is simpler than iCalendar and the official specifications are much more layman-friendly to read. iCalendar is based on vCalendar sort of like Java is based on C. Therefore, if you want to migrate to iCalendar later, it will be a flatter learner curve.

MIME Type Setups

A standard vCalendar file has an extension of .vcs and MIME type of text/x-vCalendar. If you use iCalendar, the MIME type is "text/Calendar" and the extension is .ics.
You'll need to tell Apache to send the linked-to file to PHP for parsing, and then tell PHP to send it with the vCalendar MIME type. The easiest way to do this is to have a .php file that sends a stream of data as a vCalendar file to the browser. This is accomplished by calling the header function at the very top of your script. For vCalendars:

<?php
    header
("Content-Type: text/x-vCalendar");
    
header("Content-Disposition: inline; filename=MyvCalFile.vcs");
?>
An alternative is to have a .vcs or .ics file with PHP code, but you'll need to make the appropriate changes to your server's httpd.conf and mime.types files. Add .vcs (or .ics) to httpd.conf's AddType application/x-httpd-php line and add the appropriate MIME type to your mime.types file.
On the client side, the browser must have the text/x-vCalendar MIME type registered, and, ideally, it should be told to directly open up the vCalendar file with the calendaring application. Most browsers should have this pre-configured. The rest will probably prompt the user for the application to open the file with. You may want to include help text on what this .vcs file does, and, if necessary, how to configure MIME type settings.

vCalendar Crash Course

Here is a simple vCalendar file with one event:

BEGIN:VCALENDAR
VERSION:1.0
BEGIN:VEVENT
SUMMARY:New Volunteer Orientation
DESCRIPTION;ENCODING=QUOTED-PRINTABLE:Interested in becoming a volunteer for the Sacramento SPCA? We'd love to have you join our team! Please download a volunteer application from this website, and when you mail it in, indicate that you'd like to attend this orientation.=0D=0A=
=0D=0A=
Contact Dee Dee Drake for more information.
DTSTART:20020925T010000Z
DTEND:20020925T020000Z
END:VEVENT
END:VCALENDAR
Each vCalendar object begins with a BEGIN:VCALENDAR statement and ends with a END:VCALENDAR statement. In-between are multiple events delimited by BEGIN:VEVENT and END:VEVENT. This is the general model for an element:

ELEMENTNAME;PARAMETER1=PARAMETER1VALUE:Element value.
Walking through our example, we set general calendar elements. They go before the first calendar event. There are several of these elements, but I won't go into detail about them because only one, VERSION, is required. VERSION:1.0 indicates vCalendar and VERSION:2.0 indicates an iCalendar file. Check the official specifications on using and formatting the other general calendar elements. After the general elements, we see the first event delimited with the BEGIN:VEVENT statement.
Again, I won't elaborate on every element available for an event. Instead, I will mention only the mandatory ones.
SUMMARY is a short description used widely in things like month/week/day calendar views.
DESCRIPTION is a detailed description of the event. Most software applications display the DESCRIPTION in a notes area or reveal it after the user clicks on the summary.
In our example, we see a use of an element parameter called ENCODING with a value of QUOTED-PRINTABLE. If your description uses line breaks, you'll need this parameter and value. Software applications probably can't see HTML in its scheduling functions, so <br> means nothing. The vCalendar specification uses line breaks as element delimiters, so manual line breaks will not show up. To show line breaks in your description, you'll have to encode the description with a value of QUOTED-PRINTABLE and use. =0D=0A= for line breaks, which is the hex value of a carriage return and new line.
DTSTART is the day and time the event starts. DTEND is the day and time the event ends. They both follow this format: YYYYMMDDTHHMMSSZ, where YYYY is the four digit year, MM is the two digit month, DD is the two digit day, T separates the date from the time, HH is the two digit hour, MM is the two digit minutes, and SS is the two digit seconds. The Z at the end is optional. If you have the Z, the time listed is in UTC, or Zulu time. The software application should automatically translate it to the user's local time. Without the Z, the date and time is always local to the user. This is an important consideration if the users are in different time zones.
These elements are basically all you need to schedule an event. The official specification has many more elements that can be added. You can tickle a visual or audio alarm, set location properties for an event, or set up recurring events. However, like most industry specifications that depend on vendor support, there is little consistency in their support. Developer, beware.

Enter PHP

Now that we know how to format a vCalendar file, we can use PHP to format the data and prepare the file. As an example, suppose we store events in a database table with the following fields:
EventID, Summary, Detail, EventStart, EventEnd
In the link to the vcs generation script, pass a url variable that holds the event ID. Use this variable to specify the exact event in my SQL statement. It's also a good idea to use this ID to generate a unique filename for the vcs file. This is necessary because if a user clicks on more than one event and downloads more than one vcs file, the operating system may append a number after the ..vcs extension. This number disrupts the browser's handling of the vcs file. So, the first few lines in our script are:

<?php
    $Filename 
"SSPCAEvent" $_GET['ID'] . ".vcs"
    
header("Content-Type: text/x-vCalendar");
    
header("Content-Disposition: inline; filename=$Filename");
?>
After this, hit the database to get the stored event data. I'll use a mysql/mysql_fetch_array example. Use the results to populate a correct vCalendar file. We'll use the Summary result in the SUMMARY element of the vCalendar file and the Detail result in the DESCRIPTION element. Feel free to add any other stored details in the DESCRIPTION element. For example, in a community calendar I support, I append a contact's name and phone number at the end of each description. Before you populate the DESCRIPTION element, remember to substitute line breaks for the appropriate CFLF hex values.

<?php
    $DescDump 
str_replace("\r""=0D=0A="$row['Detail']);
?>
Now, parse the start and end dates and times to the vCalendar format. Let's assume that the start and end information are stored as unix timestamp values. PHP's date function makes it easy to break out the date and time parts from unix timestamps, so we'll use it. If your information is not in unix timestamp values, you'll need to use another method to parse the date and time information to their year, month, day, hour, minute, and seconds. Don't forget to add leading zeros to any single digit units.
If multiple time zones are a concern, convert the start and end times to UTC before you parse the timestamp. For example, if the server is in the U.S. Pacific time zone, add 25,200 (number of seconds in seven hours, daylight savings time) to the unix timestamp. Remember, you'll also need to add the Z flag at the end of the string. For now, we'll keep things simple and ignore UTC.

<?php
$vCalStart 
date("Ymd\THi00"$row['EventStart']);
$vCalEnd date("Ymd\THi00"$row['EventEnd']);
?>
We've now grabbed and formatted the event's summary, description, start time, and end times. The final step is to take this data and make the vCalendar file:

<?php
    $Filename 
"SSPCAEvent" $_GET['ID'] . ".vcs"
    
header("Content-Type: text/x-vCalendar");
    
header("Content-Disposition: inline; filename=$Filename");

    
/** Put mysql connection and query statements here **/

$DescDump str_replace("\r""=0D=0A="$row['Detail']);

$vCalStart date("Ymd\THi00"$row['EventStart']);
$vCalEnd date("Ymd\THi00"$row['EventEnd']);
?>
BEGIN:VCALENDAR
VERSION:1.0
PRODID:SSPCA Web Calendar
TZ:-07
BEGIN:VEVENT
SUMMARY:<?php echo $row['Summary'] . "\n"?>
DESCRIPTION;ENCODING=QUOTED-PRINTABLE: <?php echo $DescDump "\n"?>
DTSTART:<?php echo $vCalStart "\n"?>
DTEND:<?php echo $vCalEnd "\n"?>
END:VEVENT
END:VCALENDAR
That's it! When the user clicks on the link to the vCalendar file, those 11 little lines are what they'll get. Hopefully you'll get a lot of mileage from vCalendar and iCalendar. Its widespread adoption makes it a way to strengthen your relationship with Internet visitors and extranet partners. Its flexibility can be used for creative applications. From being a missing link between corporate calendaring systems and intranet applications to communications with WAP users, PHP and vCalendar makes a powerful combination.

 

Resources

vCalendar:
iCalendar: