Subject: | Correctly handle VEVENTs with a start date but no end date or duration (patch enclosed) |
iCal::Parser assumes that every VEVENT has a DTEND or DURATION. According to RFC 2445,
however, neither one is required. Here are the relevant excerpts:
[RFC 2445, p. 53:] For cases where a "VEVENT" calendar component specifies a "DTSTART"
property with a DATE data type but no "DTEND" property, the events non-inclusive end is the
end of the calendar date specified by the "DTSTART" property. For cases where a "VEVENT"
calendar component specifies a "DTSTART" property with a DATE-TIME data type but no
"DTEND" property, the event ends on the same calendar date and time of day specified by the
"DTSTART" property.
[p.94:] In a "VEVENT" calendar component [the "DURATION" property] may be used to specify
a duration of the event, instead of an explicit end date/time.
I'm attaching a patch that implements the logic described in the RFC, and that adds a (trivial)
test calendar with an event containing a DTSTART property but no DURATION or DTEND. (I
wasn't sure how to create a dump file.)
Thanks very much!
Subject: | iCal-Parser-1.14.patch |
diff -NPur iCal-Parser-1.14.orig/lib/iCal/Parser.pm iCal-Parser-1.14/lib/iCal/Parser.pm
--- iCal-Parser-1.14.orig/lib/iCal/Parser.pm Thu Oct 19 18:21:55 2006
+++ iCal-Parser-1.14/lib/iCal/Parser.pm Wed Feb 28 16:50:55 2007
@@ -110,9 +110,30 @@
# stolen from Text::vFile::asData example
$e{allday}=1 if _param($event,'DTSTART','VALUE')||'' eq 'DATE';
- #is it a rule that an event must contain either a duration or end?
+ my $duration;
my $end=$e{DTEND};
- my $duration=delete $e{DURATION}||$end-$start;
+ if (exists $e{DURATION}) {
+ $duration=delete $e{DURATION};
+ } elsif (defined $end) {
+ $duration=$end-$start;
+ } elsif ($e{allday}) {
+ # RFC 2445 (page 53):
+ # For cases where a "VEVENT" calendar component specifies a
+ # "DTSTART" property with a DATE data type but no "DTEND"
+ # property, the events non-inclusive end is the end of the
+ # calendar date specified by the "DTSTART" property.
+ $duration=DateTime::Duration->new(days=>1);
+ $end=$e{DTEND}=$start+$duration;
+ }
+ else {
+ # RFC 2445 (page 53):
+ # For cases where a "VEVENT" calendar component specifies a
+ # "DTSTART" property with a DATE-TIME data type but no "DTEND"
+ # property, the event ends on the same calendar date and time
+ # of day specified by the "DTSTART" property
+ $end=$e{DTEND}=$start->clone;
+ $duration=$end-$start; #i.e., 0
+ }
$e{DTEND}||=$start+$duration;
$e{hours}=_hours($duration) unless $e{allday};
diff -NPur iCal-Parser-1.14.orig/t/calendars/11all-day-no-end.ics iCal-Parser-1.14/t/calendars/11all-day-no-end.ics
--- iCal-Parser-1.14.orig/t/calendars/11all-day-no-end.ics Wed Dec 31 19:00:00 1969
+++ iCal-Parser-1.14/t/calendars/11all-day-no-end.ics Thu Mar 1 07:32:40 2007
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Testing//Test//EN
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20041115
+SUMMARY:all day, no end specified
+UID:A4E57872-3516-11D9-8A43-000D93C45D90
+SEQUENCE:2
+DTSTAMP:20041113T015226Z
+END:VEVENT
+END:VCALENDAR