[Rt-commit] r3590 - in Data-ICal: . lib/Data lib/Data/ICal lib/Data/ICal/Entry lib/Data/ICal/Entry/Alarm lib/Data/ICal/Entry/TimeZone t t/ics

glasser at bestpractical.com glasser at bestpractical.com
Wed Aug 3 11:35:25 EDT 2005


Author: glasser
Date: Wed Aug  3 11:35:23 2005
New Revision: 3590

Added:
   Data-ICal/lib/Data/ICal/Entry/TimeZone/
   Data-ICal/lib/Data/ICal/Entry/TimeZone/Daylight.pm
   Data-ICal/lib/Data/ICal/Entry/TimeZone/Standard.pm
   Data-ICal/t/08.parse.t
   Data-ICal/t/ics/
   Data-ICal/t/ics/badlyformed.ics
   Data-ICal/t/ics/test.ics
Modified:
   Data-ICal/   (props changed)
   Data-ICal/Changes
   Data-ICal/MANIFEST
   Data-ICal/Makefile.PL
   Data-ICal/README
   Data-ICal/lib/Data/ICal.pm
   Data-ICal/lib/Data/ICal/Entry.pm
   Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm
   Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm
   Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm
   Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm
   Data-ICal/lib/Data/ICal/Entry/Event.pm
   Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm
   Data-ICal/lib/Data/ICal/Entry/Journal.pm
   Data-ICal/lib/Data/ICal/Entry/TimeZone.pm
   Data-ICal/lib/Data/ICal/Entry/Todo.pm
Log:
 r38399 at tin-foil:  glasser | 2005-08-03 11:13:23 -0400
 Changes from Simon Wistow:  parsing support, and full timezone support.
 r38400 at tin-foil:  glasser | 2005-08-03 11:20:31 -0400
 A bit of POD cleanup
 r38401 at tin-foil:  glasser | 2005-08-03 11:26:05 -0400
 Authorship, changelog, etc
 r38402 at tin-foil:  glasser | 2005-08-03 11:33:19 -0400
 Make the parsing/roundtrip tests just one file
 r38403 at tin-foil:  glasser | 2005-08-03 11:34:29 -0400
 MANIFEST fix


Modified: Data-ICal/Changes
==============================================================================
--- Data-ICal/Changes	(original)
+++ Data-ICal/Changes	Wed Aug  3 11:35:23 2005
@@ -1,5 +1,9 @@
 Revision history for Data-ICal
 
+0.02  Wed Aug 03 11:25:00 EDT 2005
+    * Parser support, thanks to Simon Wistow
+    * Full Time Zone support
+
 0.01  Wed Jul 27 11:52:12 EDT 2005
 
     * Initial release

Modified: Data-ICal/MANIFEST
==============================================================================
--- Data-ICal/MANIFEST	(original)
+++ Data-ICal/MANIFEST	Wed Aug  3 11:35:23 2005
@@ -1,4 +1,3 @@
-SIGNATURE
 Changes
 doc/rfc2445.txt
 inc/Module/Install.pm
@@ -19,12 +18,15 @@
 lib/Data/ICal/Entry/FreeBusy.pm
 lib/Data/ICal/Entry/Journal.pm
 lib/Data/ICal/Entry/TimeZone.pm
+lib/Data/ICal/Entry/TimeZone/Daylight.pm
+lib/Data/ICal/Entry/TimeZone/Standard.pm
 lib/Data/ICal/Entry/Todo.pm
 lib/Data/ICal/Property.pm
 Makefile.PL
 MANIFEST			This list of files
 META.yml
 README
+SIGNATURE
 t/00.load.t
 t/01.simplegen.t
 t/02.linewrap.t
@@ -32,5 +34,8 @@
 t/04.mandatory-props.t
 t/05.prop-params.t
 t/06.prop-bad-quote.t
+t/08.parse.t
+t/ics/badlyformed.ics
+t/ics/test.ics
 t/pod-coverage.t
 t/pod.t

Modified: Data-ICal/Makefile.PL
==============================================================================
--- Data-ICal/Makefile.PL	(original)
+++ Data-ICal/Makefile.PL	Wed Aug  3 11:35:23 2005
@@ -8,6 +8,8 @@
 build_requires('Test::More');
 build_requires('Test::Warn');
 build_requires('Test::NoWarnings');
+build_requires('Test::LongString');
 requires('Class::Accessor');
+requires('Text::vFile::asData');
 
 &WriteAll;

Modified: Data-ICal/README
==============================================================================
--- Data-ICal/README	(original)
+++ Data-ICal/README	Wed Aug  3 11:35:23 2005
@@ -1,4 +1,4 @@
-Data-ICal version 0.0.1
+Data-ICal
 
 Data::ICal is a straightforward generator for iCalendar (RFC 2445) files, such
 as those used in Apple's iCal.

Modified: Data-ICal/lib/Data/ICal.pm
==============================================================================
--- Data-ICal/lib/Data/ICal.pm	(original)
+++ Data-ICal/lib/Data/ICal.pm	Wed Aug  3 11:35:23 2005
@@ -3,7 +3,10 @@
 
 package Data::ICal;
 use base qw/Data::ICal::Entry/;
-our $VERSION = '0.01';
+
+use Text::vFile::asData;
+
+our $VERSION = '0.02';
 
 use Carp;
 
@@ -20,9 +23,14 @@
 
     my $vtodo = Data::ICal::Entry::Todo->new();
     $vtodo->add_properties(
-	# ... see Data::ICal::Entry::Todo documentation
+        # ... see Data::ICal::Entry::Todo documentation
     );
 
+    # ... or
+
+    $calendar = Data::ICal->new('foo.ics'); # parse existing file
+
+
     $calendar->add_entry($vtodo);
 
     print $calendar->as_string;
@@ -50,21 +58,55 @@
 
 =head2 new
 
-Creates a new L<Data::ICal> object; sets its C<VERSION> and C<PRODID> properties
-to "2.0" and the value of the C<product_id> method respectively.
+Creates a new L<Data::ICal> object. 
+
+If a file name is passed, this parses that file into the object; otherwise it
+just sets its C<VERSION> and C<PRODID> properties to "2.0" and the value of the
+C<product_id> method respectively.
+
+Returns undef upon failure to open file or parse .ics file.
 
 =cut
 
 sub new {
     my $class = shift;
     my $self  = $class->SUPER::new(@_);
-    $self->add_properties(
-        version => '2.0',
-        prodid  => $self->product_id,
-    );
+
+    if (@_) {
+       $self->parse_file(@_) || return undef;
+    } else {
+       $self->add_properties(
+            version => '2.0',
+            prodid  => $self->product_id,
+       );
+    }
     return $self;
 }
 
+=head2 parse_file
+
+Parse a .ics file and populate a L<Data::ICal> object.
+
+=cut
+
+sub parse_file {
+    my ($self, $file) = @_;
+
+ 
+    # open the file (checking as we go, like good little Perl mongers)
+    open my($fh), $file or return undef;
+    my $cal = Text::vFile::asData->new->parse($fh) || return undef;
+    close $fh;
+
+    return undef unless exists $cal->{objects};
+    # loop through all the vcards
+    foreach my $object (@{ $cal->{objects} }) {
+        $self->parse_object($object);
+    }
+	return 1;
+}
+
+
 =head2 ical_entry_type
 
 Returns C<VCALENDAR>, its iCalendar entry name.
@@ -159,7 +201,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT
@@ -194,5 +236,4 @@
 SUCH DAMAGES.
 
 =cut
-
 1;

Modified: Data-ICal/lib/Data/ICal/Entry.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry.pm	Wed Aug  3 11:35:23 2005
@@ -14,7 +14,7 @@
 
     my $vtodo = Data::ICal::Entry::Todo->new();
     $vtodo->add_properties(
-	# ... see Data::ICal::Entry::Todo documentation
+    # ... see Data::ICal::Entry::Todo documentation
     );
 
     $calendar->add_entry($vtodo);
@@ -139,6 +139,20 @@
     return $self->{'properties'};
 }
 
+
+=head2 property
+
+Given a property name returns a reference to the array of L<Data::ICal::Property> objects.
+
+=cut
+
+sub property {
+    my $self = shift;
+    my $prop = lc shift;
+	return $self->{'properties'}->{$prop};
+}
+
+
 =head2 add_property $propname => $propval
 
 Creates a new L<Data::ICal::Property> object with name C<$propname> and value
@@ -350,9 +364,136 @@
     return 'END:' . $self->ical_entry_type . "\n";
 }
 
+# mapping of event types to class (under the Data::Ical::Event namespace)
+my %_generic = (
+    vevent    => 'Event',
+    vtodo     => 'Todo',
+    vjournal  => 'Journal',
+    vfreebusy => 'FreeBusy',
+    vtimezone => 'TimeZone',
+    standard  => 'TimeZone::Standard',
+    daylight  => 'TimeZone::Daylight',
+);
+
+
+=head2 parse_object
+
+Translate a L<Text::vFile::asData> sub object into the appropriate 
+L<Data::iCal::Event> subtype.
+
+=cut 
+
+
+# TODO: this is currently recursive which could blow the stack -
+#       it might be worth refactoring to make it sequential
+sub parse_object {
+    my ($self,$object) = @_;
+
+
+    my $type = $object->{type};
+    
+    
+    my $new_self;
+    
+    # First check to see if it's generic long name just in case there 
+    # event turns out to be a VGENERIC entry type
+    if (my $class = $_generic{lc($type)}) {
+        $new_self = $self->_parse_data_ical_generic($class, $object);     
+    # then look for specific overrides
+    } elsif (my $sub = $self->can('_parse_'.lc($type))) {
+        $new_self = $self->$sub($object);
+    # bitch
+    } else {
+        warn "Can't parse type $type yet";
+        return;
+    }
+        
+    # recurse through sub-objects
+    foreach my $sub_object(@{ $object->{objects} }) {
+        $new_self->parse_object($sub_object);
+    }
+
+}
+
+
+
+# special because we want to use ourselves as the parent
+sub _parse_vcalendar {
+    my ($self, $object) = @_;
+    $self->_parse_generic_event($self, $object);
+    return $self;
+}
+
+# mapping of action types to class (under the Data::Ical::Event::Alarm namespace)
+my %_action_map = (
+    AUDIO      => 'Audio',
+    DISPLAY    => 'Display',
+    EMAIL      => 'Email',
+    PROCEDURE  => 'Procedure',
+);
+
+# alarms have actions
+sub _parse_valarm {
+    my ($parent, $object) = @_;
+
+    # ick
+    my $action = $object->{properties}->{ACTION}->[0]->{value};
+    die "Can't parse VALARM with action $action" unless exists $_action_map{$action};
+
+    
+    my $alarm_class = "Data::ICal::Entry::Alarm::".$_action_map{$action};
+    eval "require $alarm_class";
+    die "Failed to require $alarm_class : $@" if $@;
+
+    $alarm_class->import;
+    my $alarm = $alarm_class->new;
+    $parent->_parse_generic_event($alarm, $object);
+    $parent->add_entry($alarm);
+    return $alarm;
+
+    
+}    
+
+# generic event handler
+sub _parse_data_ical_generic {
+    my ($parent, $class, $object) = @_;
+    
+    my $entry_class = "Data::ICal::Entry::$class";
+    eval "require $entry_class";
+    die "Failed to require $entry_class : $@" if $@;
+    
+    $entry_class->import;
+    my $entry = $entry_class->new;
+    $parent->_parse_generic_event($entry, $object);
+    $parent->add_entry($entry);
+    return $entry;
+}
+
+# handle transferring of properties
+sub _parse_generic_event {
+    my ($parent, $entry, $object) = @_;
+
+    my $p = $object->{properties};
+    while (my($key,$val) = each(%$p)) {
+        foreach my $occurence (@$val) {
+            my $prop;
+            # handle optional params and 'normal' key/value pairs
+            # TODO: line wrapping?
+            if ($occurence->{param}) {
+                $prop = [ $occurence->{value}, $occurence->{param} ];
+            } else {
+                $prop = $occurence->{value};
+            }
+            $entry->add_property( lc($key) => $prop );            
+        }
+    }
+    return $entry;
+}
+
+
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Audio.pm	Wed Aug  3 11:35:23 2005
@@ -88,7 +88,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Display.pm	Wed Aug  3 11:35:23 2005
@@ -85,7 +85,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Email.pm	Wed Aug  3 11:35:23 2005
@@ -117,7 +117,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Alarm/Procedure.pm	Wed Aug  3 11:35:23 2005
@@ -90,7 +90,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Event.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Event.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Event.pm	Wed Aug  3 11:35:23 2005
@@ -89,7 +89,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/FreeBusy.pm	Wed Aug  3 11:35:23 2005
@@ -74,7 +74,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/Journal.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Journal.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Journal.pm	Wed Aug  3 11:35:23 2005
@@ -80,7 +80,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Modified: Data-ICal/lib/Data/ICal/Entry/TimeZone.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/TimeZone.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/TimeZone.pm	Wed Aug  3 11:35:23 2005
@@ -64,7 +64,7 @@
 =head2 mandatory_unique_properties
 
 According to the iCalendar standard, the C<tzid> property must be specified
-exact one time in a time zone declaration.
+exactly one time in a time zone declaration.
 
 =cut
 
@@ -76,7 +76,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Added: Data-ICal/lib/Data/ICal/Entry/TimeZone/Daylight.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/TimeZone/Daylight.pm	Wed Aug  3 11:35:23 2005
@@ -0,0 +1,145 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::TimeZone::Daylight;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::TimeZone::Daylight - Represents a Daylight Time base offset from UTC for parent TimeZone
+
+
+=head1 SYNOPSIS
+
+  
+=head1 DESCRIPTION
+
+A time zone is unambiguously defined by the set of time
+measurement rules determined by the governing body for a given
+geographic area. These rules describe at a minimum the base  offset
+from UTC for the time zone, often referred to as the Standard Time
+offset. Many locations adjust their Standard Time forward or backward
+by one hour, in order to accommodate seasonal changes in number of
+daylight hours, often referred to as Daylight  Saving Time. Some
+locations adjust their time by a fraction of an hour. Standard Time
+is also known as Winter Time. Daylight Saving Time is also known as
+Advanced Time, Summer Time, or Legal Time in certain countries. The
+following table shows the changes in time zone rules in effect for
+New York City starting from 1967. Each line represents a description
+or rule for a particular observance.
+
+     Effective Observance Rule
+
+     Date       (Date/Time)             Offset  Abbreviation
+
+     1967-*     last Sun in Oct, 02:00  -0500   EST
+
+     1967-1973  last Sun in Apr, 02:00  -0400   EDT
+
+     1974-1974  Jan 6,  02:00           -0400   EDT
+
+     1975-1975  Feb 23, 02:00           -0400   EDT
+
+     1976-1986  last Sun in Apr, 02:00  -0400   EDT
+
+     1987-*     first Sun in Apr, 02:00 -0400   EDT
+
+Note: The specification of a global time zone registry is not
+addressed by this document and is left for future study.
+However, implementers may find the Olson time zone database [TZ]
+a useful reference. It is an informal, public-domain collection
+of time zone information, which is currently being maintained by
+volunteer Internet participants, and is used in several
+operating systems. This database contains current and historical
+time zone information for a wide variety of locations around the
+globe; it provides a time zone identifier for every unique time
+zone rule set in actual use since 1970, with historical data
+going back to the introduction of standard time.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<DAYLIGHT>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'DAYLIGHT'}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the following properties must be specified
+exactly one time in a daylight declaration:
+
+	dtstart  tzoffsetto  tzoffsetfrom
+
+=cut
+
+sub mandatory_unique_properties {
+    qw(
+        dtstart
+		tzoffsetto 
+		tzoffsetfrom 
+    );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for a daylight declaration:
+
+	comment  rdate  rrule  tzname  
+
+=cut
+
+sub optional_repeatable_properties {
+    qw(
+        comment
+		rdate 
+		rrule 
+		tzname 
+    );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC.  All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;

Added: Data-ICal/lib/Data/ICal/Entry/TimeZone/Standard.pm
==============================================================================
--- (empty file)
+++ Data-ICal/lib/Data/ICal/Entry/TimeZone/Standard.pm	Wed Aug  3 11:35:23 2005
@@ -0,0 +1,145 @@
+use warnings;
+use strict;
+
+package Data::ICal::Entry::TimeZone::Standard;
+
+use base qw/Data::ICal::Entry/;
+
+=head1 NAME
+
+Data::ICal::Entry::TimeZone::Standard - Represents a Standard Time base offset from UTC for parent TimeZone
+
+
+=head1 SYNOPSIS
+
+  
+=head1 DESCRIPTION
+
+A time zone is unambiguously defined by the set of time
+measurement rules determined by the governing body for a given
+geographic area. These rules describe at a minimum the base  offset
+from UTC for the time zone, often referred to as the Standard Time
+offset. Many locations adjust their Standard Time forward or backward
+by one hour, in order to accommodate seasonal changes in number of
+daylight hours, often referred to as Daylight  Saving Time. Some
+locations adjust their time by a fraction of an hour. Standard Time
+is also known as Winter Time. Daylight Saving Time is also known as
+Advanced Time, Summer Time, or Legal Time in certain countries. The
+following table shows the changes in time zone rules in effect for
+New York City starting from 1967. Each line represents a description
+or rule for a particular observance.
+
+     Effective Observance Rule
+
+     Date       (Date/Time)             Offset  Abbreviation
+
+     1967-*     last Sun in Oct, 02:00  -0500   EST
+
+     1967-1973  last Sun in Apr, 02:00  -0400   EDT
+
+     1974-1974  Jan 6,  02:00           -0400   EDT
+
+     1975-1975  Feb 23, 02:00           -0400   EDT
+
+     1976-1986  last Sun in Apr, 02:00  -0400   EDT
+
+     1987-*     first Sun in Apr, 02:00 -0400   EDT
+
+Note: The specification of a global time zone registry is not
+addressed by this document and is left for future study.
+However, implementers may find the Olson time zone database [TZ]
+a useful reference. It is an informal, public-domain collection
+of time zone information, which is currently being maintained by
+volunteer Internet participants, and is used in several
+operating systems. This database contains current and historical
+time zone information for a wide variety of locations around the
+globe; it provides a time zone identifier for every unique time
+zone rule set in actual use since 1970, with historical data
+going back to the introduction of standard time.
+
+=head1 METHODS
+
+=cut
+
+=head2 ical_entry_type
+
+Returns C<STANDARD>, its iCalendar entry name.
+
+=cut
+
+sub ical_entry_type {'STANDARD'}
+
+=head2 mandatory_unique_properties
+
+According to the iCalendar standard, the following properties must be specified
+exactly one time in a standard time declaration:
+
+	dtstart  tzoffsetto  tzoffsetfrom
+
+=cut
+
+sub mandatory_unique_properties {
+    qw(
+        dtstart
+		tzoffsetto 
+		tzoffsetfrom 
+    );
+}
+
+=head2 optional_repeatable_properties
+
+According to the iCalendar standard, the following properties may be specified
+any number of times for a standard time declaration:
+
+	comment  rdate  rrule  tzname 
+
+=cut
+
+sub optional_repeatable_properties {
+    qw(
+        comment
+		rdate 
+		rrule 
+		tzname 
+    );
+}
+
+=head1 AUTHOR
+
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
+
+
+=head1 LICENCE AND COPYRIGHT
+
+Copyright (c) 2005, Best Practical Solutions, LLC.  All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself. See L<perlartistic>.
+
+
+=head1 DISCLAIMER OF WARRANTY
+
+BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
+YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR, OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
+LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+=cut
+
+1;

Modified: Data-ICal/lib/Data/ICal/Entry/Todo.pm
==============================================================================
--- Data-ICal/lib/Data/ICal/Entry/Todo.pm	(original)
+++ Data-ICal/lib/Data/ICal/Entry/Todo.pm	Wed Aug  3 11:35:23 2005
@@ -89,7 +89,7 @@
 
 =head1 AUTHOR
 
-Jesse Vincent  C<< <jesse at bestpractical.com> >>
+Jesse Vincent  C<< <jesse at bestpractical.com> >> with David Glasser and Simon Wistow
 
 
 =head1 LICENCE AND COPYRIGHT

Added: Data-ICal/t/08.parse.t
==============================================================================
--- (empty file)
+++ Data-ICal/t/08.parse.t	Wed Aug  3 11:35:23 2005
@@ -0,0 +1,85 @@
+#!/usr/bin/perl -w
+
+use warnings;
+use strict;
+
+use constant TESTS_IN_TEST_CALENDAR => 15;
+use Test::More tests => 6 + 2 * TESTS_IN_TEST_CALENDAR;
+use Test::LongString;
+use Test::NoWarnings; # this catches our warnings like setting unknown properties
+
+BEGIN { use_ok('Data::ICal') }
+
+
+
+our $s;
+$s = Data::ICal->new('t/ics/nonexistent.ics');
+
+is($s, undef, "Caught no file death");
+
+$s = Data::ICal->new('t/ics/badlyformed.ics'); 
+is($s, undef, "Caught badly formed ics file death"); 
+
+$s = Data::ICal->new('t/ics/test.ics');
+
+isa_ok($s, 'Data::ICal');
+
+test_calendar();
+
+SKIP: {
+    skip "Can't create t/ics/out.ics: $!", 1 + TESTS_IN_TEST_CALENDAR unless open(ICS,">t/ics/out.ics");
+    print ICS $s->as_string;
+    close ICS;
+
+    undef($s); 
+    $s = Data::ICal->new('t/ics/out.ics');
+    isa_ok($s, 'Data::ICal');
+
+    test_calendar();
+
+    unlink('t/ics/out.ics');
+}
+
+sub test_calendar {
+    is($s->ical_entry_type, 'VCALENDAR', "Is a VCALENDAR");
+    my $id = $s->property('prodid')->[0]->value;
+    my $name = $s->property('x-wr-calname')->[0]->value;
+    is($id,'Data::ICal test', 'Got id');
+    is($name,'Data::ICal test calendar', 'Got name');
+
+    my @entries = @{$s->entries};
+    is(@entries,2,"Correct number of entries");
+    
+    my ($event, $timezone);
+
+    for (@entries) {
+        if ( $_->ical_entry_type eq 'VEVENT' ) {
+            $event = $_;
+        } elsif ( $_->ical_entry_type eq 'VTIMEZONE' ) {
+            $timezone = $_;
+        }
+    }    
+    undef(@entries);
+
+    # Event 
+    isa_ok($event, 'Data::ICal::Entry::Event');
+    is($event->property('location')->[0]->value, 'The Restaurant at the End of the Universe', 'Correct location');
+    is($event->property('url')->[0]->value, 'http://www.bestpractical.com', 'Correct URL');
+    is($event->property('url')->[0]->parameters->{VALUE}, 'URI', 'Got parameter');
+
+    # check sub entries
+    @entries = @{$event->entries};
+    is(@entries, 1, "Got sub entries");
+    isa_ok($entries[0],'Data::ICal::Entry::Alarm::Audio');
+    undef(@entries);
+
+    # TimeZone
+    isa_ok($timezone, 'Data::ICal::Entry::TimeZone');
+    is($timezone->property('tzid')->[0]->value, 'Europe/London', 'Got TimeZone ID');
+    
+    # check daylight and standard settings
+    @entries = @{$timezone->entries};
+    is(@entries, 6, 'Got Daylight/Standard Entries');
+    is( grep( ($_->ical_entry_type eq 'DAYLIGHT'), @entries), 3, '3 DAYLIGHT');
+    is( grep( ($_->ical_entry_type eq 'STANDARD'), @entries), 3, '3 STANDARD');
+}

Added: Data-ICal/t/ics/badlyformed.ics
==============================================================================
--- (empty file)
+++ Data-ICal/t/ics/badlyformed.ics	Wed Aug  3 11:35:23 2005
@@ -0,0 +1 @@
+this is a (very) badly formed ics file

Added: Data-ICal/t/ics/test.ics
==============================================================================
--- (empty file)
+++ Data-ICal/t/ics/test.ics	Wed Aug  3 11:35:23 2005
@@ -0,0 +1,60 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+X-WR-CALNAME:Data::ICal test calendar
+PRODID:Data::ICal test
+BEGIN:VTIMEZONE
+TZID:Europe/London
+LAST-MODIFIED:20050716T111510Z
+BEGIN:DAYLIGHT
+DTSTART:20030330T020000
+TZOFFSETTO:+0100
+TZOFFSETFROM:+0000
+TZNAME:BST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20031026T020000
+TZOFFSETTO:+0000
+TZOFFSETFROM:+0100
+TZNAME:GMT
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20040328T020000
+TZOFFSETTO:+0100
+TZOFFSETFROM:+0000
+TZNAME:BST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20041031T020000
+TZOFFSETTO:+0000
+TZOFFSETFROM:+0100
+TZNAME:GMT
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20050327T020000
+TZOFFSETTO:+0100
+TZOFFSETFROM:+0000
+TZNAME:BST
+END:DAYLIGHT
+BEGIN:STANDARD
+DTSTART:20051030T020000
+TZOFFSETTO:+0000
+TZOFFSETFROM:+0100
+TZNAME:GMT
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTART;TZID=Europe/London:20050802T170000
+DURATION:PT6H
+LOCATION:The Restaurant at the End of the Universe
+SEQUENCE:42
+SUMMARY:Data::ICal release party
+URL;VALUE=URI:http://www.bestpractical.com
+BEGIN:VALARM
+TRIGGER;VALUE=DATE-TIME:19970317T133000Z
+REPEAT:4
+DURATION:PT15M
+ACTION:AUDIO
+ATTACH;FMTTYPE=audio/basic:ftp://host.com/pub/sounds/bell-01.aud
+END:VALARM
+END:VEVENT
+END:VCALENDAR


More information about the Rt-commit mailing list