Skip to content

Plain text

Mike Angstadt edited this page Aug 23, 2018 · 6 revisions

iCalendar data is most commonly encoded in a special plain-text format. The specifications for the latest version of the plain-text data format is defined in RFC 5545. A deprecated version of this specification is defined in RFC 2445. There is hardly any difference between the two.

An older version of the iCalendar data format (called "vCalendar") is defined in this specification and is supported by biweekly. See vCalendar for more information.

1 Reading plain-text iCalendar data

The ICalReader class handles the parsing of plain-text iCalendar data. The data is read in a streaming fashion, meaning it parses the data as it is read off the wire. This results in a smaller memory footprint than other approaches.

ICalReader automatically detects the version of the iCalendar data that's being read, and adjusts its parsing algorithm accordingly. It also automatically takes timezone data into account by parsing date/time values according to their assigned VTIMEZONE definition. See the Timezones page for more information on working with timezones.

1.1 Important methods

readNext()
Parses and returns the next ICalendar object in the data stream. The method returns null when the end of stream has been reached.

getWarnings()
ICalReader does its best to skip over invalid or unparseable data and log it as a warning (as opposed to throwing an exception and aborting the entire parsing process). The getWarnings() method returns any problems the parser encountered while parsing the ICalendar object that was last returned by readNext(). Examples of things that could cause warnings are: invalid syntax or unparseable property values (such as malformed date values).

close()
As with all I/O operations, it's important to call the close() method when you are done with the ICalReader object in order to properly close the input stream.

Please see the Javadocs for a complete listing of all the methods.

1.2 Example

The example below outputs the start times and summaries of each event in an iCalendar data stream.

Note that, when outputting the start dates, the DateFormat object is not configured with a timezone. Therefore, the dates will be displayed in the user's local timezone. For example, if a date/time value has a time of 13:00 UTC, and the user's local timezone is 5 hours behind UTC, the time will be displayed as "08:00".

File file = new File("events.ics");
ICalReader reader = new ICalReader(file);
try {
  ICalendar ical;
  DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm");
  while ((ical = reader.readNext()) != null) {
    for (VEvent event : ical.getEvents()) {
      DateStart dateStart = event.getDateStart();
      String dateStartStr = (dateStart == null) ? null : df.format(dateStart.getValue());

      Summary summary = event.getSummary();
      String summaryStr = (summary == null) ? null : summary.getValue();

      if (summaryStr != null && dateStartStr != null) {
        System.out.println(dateStartStr + ": " + summaryStr);
        continue;
      }

      if (summaryStr != null){
        System.out.println(summaryStr);
        continue;
      }

      if (dateStartStr != null){
        System.out.println(dateStartStr);
        continue;
      }
    }
  }
} finally {
  reader.close();
}

1.3 A note about unparseable property values

If a property's value cannot be parsed (for example, due to a malformed date value), the property is treated as an experimental property and a warning is logged. The code below demonstrates this:

String str =
"BEGIN:VCALENDAR\r\n" +
"VERSION:2.0\r\n" +
"BEGIN:VEVENT\r\n" +
  "SUMMARY:Party at my place.\r\n" +
  "DTSTART:Come over whenever, dude.\r\n" +
"END:VEVENT\r\n" +
"END:VCALENDAR\r\n";

ICalReader reader = new ICalReader(str);
ICalendar ical = reader.readNext();

List<String> warnings = reader.getWarnings();
System.out.println("Warnings: " + warnings);

VEvent event = ical.getEvents().get(0);
System.out.println("DTSTART property: " + event.getDateStart());

RawProperty prop = event.getExperimentalProperty("DTSTART");
System.out.println("Experimental property: " + prop.getValue());

reader.close();

The above code produces the following output:

Warnings: [Line 5 (DTSTART property): (1) Property value could not be unmarshalled.  Value: "Come over whenever, dude."  Reason: (17) Could not parse date-time value.]
DTSTART property: null
Experimental property: Come over whenever, dude.

2 Writing plain-text iCalendar data

The ICalWriter class handles the serialization of plain-text iCalendar data. Its constructor takes an ICalVersion object, which specifies the iCalendar version that the data will be written in.

By default, ICalWriter automatically formats all date/time values in UTC time, but this can be changed. See the Timezones page for more information on working with timezones.

2.1 Important methods

write()
Writes the contents of an ICalendar object to the data stream.

close()
As with all I/O operations, it's important to call the close() method when you are done with the ICalWriter object in order to properly close the output stream.

Please see the Javadocs for a complete listing of all the methods.

2.2 Example

The example below writes a list of ICalendar objects to a file using the latest iCalendar version.

List<ICalendar> icals = ...
File file = new File("events.ics");
ICalWriter writer = new ICalWriter(file, ICalVersion.V2_0);
try {
  for (ICalendar ical : icals) {
    writer.write(ical);
  }
} finally {
  writer.close();
}