diff options
author | Hans Petter <hansp@src.gnome.org> | 2003-09-12 06:04:44 +0800 |
---|---|---|
committer | Hans Petter <hansp@src.gnome.org> | 2003-09-12 06:04:44 +0800 |
commit | 697761cc337aa77a47140c8df50ed84bc25e23f6 (patch) | |
tree | b785830f72e9938cceaa016a419c7b6d9892bada /libical/src/Net-ICal-Libical/lib/Net/ICal/Libical | |
parent | 733d77e657516f9a59b5c1a7b62acb87b03ec86f (diff) | |
download | gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.gz gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.bz2 gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.lz gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.xz gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.tar.zst gsoc2013-evolution-697761cc337aa77a47140c8df50ed84bc25e23f6.zip |
Import new libical from mainline HEAD and make appropriate changes to
Evolution.
svn path=/trunk/; revision=22538
Diffstat (limited to 'libical/src/Net-ICal-Libical/lib/Net/ICal/Libical')
5 files changed, 1335 insertions, 0 deletions
diff --git a/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Component.pm b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Component.pm new file mode 100644 index 0000000000..c25297c111 --- /dev/null +++ b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Component.pm @@ -0,0 +1,175 @@ +#!/usr/bin/perl +# -*- Mode: perl -*- +#====================================================================== +# FILE: Component.pm +# CREATOR: eric 1 Mar 01 +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2000, Eric Busboom, eric@softwarestudio.org +# +# This package is free software and is provided "as is" without express +# or implied warranty. It may be used, redistributed and/or modified +# under the same terms as perl itself. ( Either the Artistic License or the +# GPL. ) +# +# +#====================================================================== + + + +package Net::ICal::Libical::Component; +use Net::ICal::Libical; + +use strict; + +sub new{ + my $class = shift; + my $ical_str = shift; # Ical data in string form + my $self = {}; + + $self->{'comp_p'} = Net::ICal::Libical::icalparser_parse_string($ical_str); + + die "Can't parse string into component" if !$self->{'comp_p'}; + + bless $self, $class; +} + +sub new_from_ref { + my $class = shift; + my $r = shift; + my $self = {}; + + $self->{'comp_p'} = $r; + + bless $self, $class; +} + +# Destroy must call icalcomponent_free() if icalcomponent_get_parent() +# returns NULL +sub DESTROY { + my $self = shift; + + my $c = $self->{'comp_p'}; + + if($c && !Net::ICal::Libical::icalcomponent_get_parent($c)){ + Net::ICal::Libical::icalcomponent_free($c); + } + +} + +# Return an array of all properties of the given type +sub properties{ + + my $self = shift; + my $prop_name = shift; + + my @props; + + if(!$prop_name){ + $prop_name = 'ANY'; + } + + # To loop over properties + # $comp_p = $self->{'comp_p'} + # $p = icallangbind_get_first_property($comp_p,$prop_name) + # $p = icallangbind_get_next_property($comp_p,$prop_name) + + my $c = $self->{'comp_p'}; + my $p; + + for($p = Net::ICal::Libical::icallangbind_get_first_property($c,$prop_name); + $p; + $p = Net::ICal::Libical::icallangbind_get_next_property($c,$prop_name)){ + + my $d_string = Net::ICal::Libical::icallangbind_property_eval_string($p,"=>"); + my %dict = %{eval($d_string)}; + + $dict{'ref'} = $p; + + # Now, look at $dict{'value_type'} or $dict{'name'} to construct a + # derived class of Property. I'll do this later. + + my $prop; + + if($dict{'value_type'} eq 'DATE' or $dict{'value_type'} eq 'DATE-TIME'){ + $prop = new Net::ICal::Libical::Time(\%dict); + } elsif($dict{'value_type'} eq 'DURATION' ) { + $prop = new Net::ICal::Libical::Duration(\%dict); + } else { + $prop = new Net::ICal::Libical::Property(\%dict); + } + + push(@props,$prop); + + } + + + return @props; + +} + + +sub add_property { + + # if there is a 'ref' key in the prop's dict, then it is owned by + # an icalcomponent, so dont add it again. But, you may check that + # it is owned by this component with: + # icalproperty_get_parent(p->{'ref'}') != $self->{'comp_p'} + + # If there is no 'ref' key, then create one with $p->{'ref'} = + # icalproperty_new_from_string($p->as_ical_string) + +} + +sub remove_property { + +# If $p->{'ref'} is set, then remove the property with +# icalcomponent_remove_property() } +} + +# Return an array of all components of the given type +sub components { + + my $self = shift; + my $comp_name = shift; + + my @comps; + + if(!$comp_name){ + $comp_name = 'ANY'; + } + + my $c = $self->{'comp_p'}; + my $p; + + for($p = Net::ICal::Libical::icallangbind_get_first_component($c,$comp_name); + $p; + $p = Net::ICal::Libical::icallangbind_get_next_component($c,$comp_name)){ + + push(@comps, Net::ICal::Libical::Component->new_from_ref($p)); + + } + + return @comps; + +} + + +sub add_component {} + +sub remove_component {} + +sub as_ical_string { + my $self = shift; + + return Net::ICal::Libical::icalcomponent_as_ical_string($self->{'comp_p'}) +} + + + +1; diff --git a/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Duration.pm b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Duration.pm new file mode 100644 index 0000000000..13ec9c437e --- /dev/null +++ b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Duration.pm @@ -0,0 +1,160 @@ +#============================================================================= +# +# This package is free software and is provided "as is" without express +# or implied warranty. It may be used, redistributed and/or modified +# under the same terms as perl itself. (Either the Artistic License or +# the GPL.) +# +#============================================================================= + +=head1 NAME + +Net::ICal::Duration -- represent a length of time + +=head1 SYNOPSIS + + use Net::ICal; + $d = Net::ICal::Duration->new("P3DT6H15M10S"); + $d = Net::ICal::Duration->new(3600); # 1 hour in seconds + +=head1 DESCRIPTION + +I<Duration> Represents a length of time, such a 3 days, 30 seconds or +7 weeks. You would use this for representing an abstract block of +time; "I want to have a 1-hour meeting sometime." If you want a +calendar- and timezone-specific block of time, see Net::ICal::Period. + +=cut + +#============================================================================= + +package Net::ICal::Libical::Duration; +use Net::ICal::Libical::Property; +use strict; +use Carp; +@Net::ICal::Libical::Duration::ISA = qw ( Net::ICal::Libical::Property ); + +=head1 METHODS + +=head2 new + +Create a new I<Duration> from: + +=over 4 + +=item * A string in RFC2445 duration format + +=item * An integer representing a number of seconds + +=cut + +sub new { + my $package = shift; + my $arg = shift; + my $self; + + if (ref($arg) == 'HASH'){ + # Construct from dictionary + $self = Net::ICal::Libical::Property::new($package,$arg); + my $val=Net::ICal::Libical::icalproperty_get_value_as_string($self->{'ref'}); + $self->{'dur'} = Net::ICal::Libical::icaldurationtype_from_string($val); + + return $self; + + } elsif ($arg =~ /^[-+]?\d+$/){ + # Seconds + $self = Net::ICal::Libical::Property::new($package,'DURATION'); + $self->{'dur'} = Net::ICal::Libical::icaldurationtype_new_from_int($arg); + } elsif ($arg) { + # iCalendar string + $self = Net::ICal::Libical::Property::new($package,'DURATION'); + $self->{'dur'} = Net::ICal::Libical::icaldurationtype_new_from_string($arg); + } else { + die; + } + + $self->_update_value(); + return $self; + +} + +sub _update_value { + my $self = shift; + + die "Can't find internal icalduration reference" if !$self->{'dur'}; + + $self->value(Net::ICal::Libical::icaldurationtype_as_ical_string($self->{'dur'})); + +} +=head2 clone() + +Return a new copy of the duration. + +=cut + +sub clone { + die "Not Implemented"; + +} + + +=head2 is_valid() + +Determine if this is a valid duration (given criteria TBD). + +=cut + +sub is_valid { + + die "Not Implemented;" + +} + +=head2 seconds() + +Set or Get the length of the duration as seconds. + +=cut + +sub seconds { + my $self = shift; + my $seconds = shift; + + if($seconds){ + $self->{'dur'} = + Net::ICal::Libical::icaldurationtype_from_int($seconds); + $self->_update_value(); + } + + return Net::ICal::Libical::icaldurationtype_as_int($self->{'dur'}); + +} + +=head2 add($duration) + +Return a new duration that is the sum of this and $duration. Does not +modify this object. + +=cut + +sub add { + my ($self, $duration) = @_; + + return new Duration($self->seconds() + $duration->seconds()); +} + + +=head2 subtract($duration) + +Return a new duration that is the difference between this and +$duration. Does not modify this object. + +=cut + +sub subtract { + my ($self, $duration) = @_; + + return new Duration($self->seconds() - $duration->seconds()); +} + +1; diff --git a/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Period.pm b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Period.pm new file mode 100644 index 0000000000..ecf29f3370 --- /dev/null +++ b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Period.pm @@ -0,0 +1,359 @@ +#!/usr/bin/perl -w +# -*- Mode: perl -*- +#====================================================================== +# +# This package is free software and is provided "as is" without express +# or implied warranty. It may be used, redistributed and/or modified +# under the same terms as perl itself. ( Either the Artistic License or the +# GPL. ) +# +# $Id$ +# +# (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org +# +# $Log +#====================================================================== + + +=pod +=head1 NAME + +Net::ICal::Period -- represent a period of time + +=head1 SYNOPSIS + + use Net::ICal; + $p = new Net::ICal::Period("19970101T120000","19970101T123000"); + $p = new Net::ICal::Period("19970101T120000","PT3W2D40S"); + $p = new Net::ICal::Period(time(),3600); + $p = new Net::ICal::Period( + new Net::ICal::Time("19970101T120000", + "America/Los_Angeles"), + new Net::ICal::Duration("2h")); + +=head1 DESCRIPTION + +Use this to make an object representing a block of time on a +real schedule. You can either say, "This event starts at 12 +and ends at 2" or "This event starts at 12 and lasts 2 hours." + +These two ways of specifying events can be treated differently +in schedules. If you say, "The meeting is from 12 to 2, but I +have to leave at 2," you are implying that the start date and +end date are fixed. If you say, "I have a 2-hour drive to +Chicago, and I need to leave at 4," you are saying that it will +take 2 hours no matter when you leave, and that moving the start +time will slide the end time correspondingly. + +=head1 BASIC METHODS + +=cut + + +#========================================================================= + +package Net::ICal::Period; +use strict; +use Net::ICal::Time; +use Net::ICal::Duration; + +use UNIVERSAL qw(isa); + +#------------------------------------------------------------------------- + +=pod +=head2 new($time, $time|$duration) + +Creates a new period object given to parameters: The first must be a +I<Time> object or valid argument to Net::ICal::Time::new. + +The second can be either: + +=pod + +=over 4 + +=item * a I<Time> object + +=item * a valid argument to Net::ICal::Time::new. + +=item * a I<Duration> object + +=item * a valid argument to Net::ICal::Duration::new. + +=back + +Either give a start time and an end time, or a start time and a duration. + +=cut + +sub new{ + my $package = shift; + my $arg1 = shift; + my $arg2 = shift; + my $self = {}; + + # Is the string in RFC2445 Format? + if(!$arg2 and $arg1 =~ /\//){ + my $tmp = $arg1; + ($arg1,$arg2) = split(/\//,$tmp); + } + + + if( ref($arg1) eq 'Net::ICal::Time'){ + $self->{START} = $arg1->clone(); + } else { + $self->{START} = new Net::ICal::Time($arg1); + } + + + if(isa($arg2,'Net::ICal::Time')){ + $self->{END} = $arg2->clone(); + } elsif (isa($arg2,'Net::ICal::Duration')) { + $self->{DURATION} = $arg2->clone(); + } elsif ($arg2 =~ /^P/) { + $self->{DURATION} = new Net::ICal::Duration($arg2); + } else { + # Hope that it is a time string + $self->{END} = new Net::ICal::Time($arg2); + } + + return bless($self,$package); +} + +#-------------------------------------------------------------------------- +=pod +=head2 clone() + +Create a copy of this component + +=cut +# XXX implement this +sub clone { + return "Not implemented"; +} + +#---------------------------------------------------------------------------- +=pod +=head2 is_valid() + +Return true if: + There is an end time and: + Both start and end times have no timezone ( Floating time) or + Both start and end time have (possibly different) timezones or + Both start and end times are in UTC and + The end time is after the start time. + + There is a duration and the duration is positive + +=cut + +# XXX implement this + +sub is_valid { + return "Not implemented"; +} + +#--------------------------------------------------------------------------- +=pod +=head2 start([$time]) + +Accessor for the start time of the event as a I<Time> object. +Can also take a valid time string or an integer (number of +seconds since the epoch) as a parameter. If a second parameter +is given, it'll set this Duration's start time. + +=cut + +sub start{ + my $self = shift; + my $t = shift; + + if($t){ + if(isa($t,'Net::ICal::Time')){ + $self->{START} = $t->clone(); + } else { + $self->{START} = new Net::ICal::Time($t); + } + } + + return $self->{START}; +} + +#----------------------------------------------------------------- +=pod +=head2 end([$time]) + +Accessor for the end time. Takes a I<Time> object, a valid time string, +or an integer and returns a time object. This routine is coupled to +the I<duration> accessor. See I<duration> below for more imformation. + +=cut + +sub end{ + + my $self = shift; + my $t = shift; + my $end; + + if($t){ + if(isa($t,'Net::ICal::Time')){ + $end = $t->clone(); + } else { + $end = new Net::ICal::Time($t); + } + + # If duration exists, use the time to compute a new duration + if ($self->{DURATION}){ + $self->{DURATION} = $end->subtract($self->{START}); + } else { + $self->{END} = $end; + } + } + + # Return end time, possibly computing it from DURATION + if($self->{DURATION}){ + return $self->{START}->add($self->{DURATION}); + } else { + return $self->{END}; + } + +} + +#---------------------------------------------------------------------- +=pod +=head2 duration([$duration]) + +Accessor for the duration of the event. Takes a I<duration> object and +returns a I<Duration> object. + +Since the end time and the duration both specify the end time, the +object will store one and access to the other will be computed. So, + +if you create: + + $p = new Net::ICal::Period("19970101T120000","19970101T123000") + +And then execute: + + $p->duration(45*60); + +The period object will adjust the end time to be 45 minutes after +the start time. It will not replace the end time with a +duration. This is required so that a CUA can take an incoming +component from a server, modify it, and send it back out in the same +basic form. + +=cut + +sub duration{ + my $self = shift; + my $d = shift; + my $dur; + + if($d){ + if(isa($d,'Net::ICal::Duration')){ + $dur = $d->clone(); + } else { + $dur = new Net::ICal::Duration($d); + } + + # If end exists, use the duration to compute a new end + # otherwise, set the duration. + if ($self->{END}){ + $self->{END} = $self->{START}->add($dur); + } else { + $self->{DURATION} = $dur; + } + } + + # Return duration, possibly computing it from END + if($self->{END}){ + return $self->{END}->subtract($self->{START}); + } else { + return $self->{DURATION}; + } + +} + +#------------------------------------------------------------------------ +=pod + +=head2 as_ical() + +Return a string that holds the RFC2445 text form of this duration + +=cut +sub as_ical { + my $self = shift; + my $out; + + $out = $self->{START}->as_ical() ."/"; + + if($self->{DURATION}){ + $out .= $self->{DURATION}->as_ical() + } else { + $out .= $self->{END}->as_ical() + } + + return $out; + +} + + +#------------------------------------------------------------------------ +=pod + +=head2 test() + +A set of developers' tests to make sure the module's working properly. + +=cut + +# Run this with a one-liner: +# perl -e "use lib('/home/srl/dev/rk/reefknot/base/'); use Net::ICal::Period; Net::ICal::Period::test();" +# adjusted for your environment. +sub test { + + print("--------- Test Net::ICal::Period --------------\n"); + + + my $p = new Net::ICal::Period("19970101T180000Z/19970102T070000Z"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/19970102T070000Z"; + + $p = new Net::ICal::Period("19970101T180000Z/PT5H30M"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/PT5H30M"; + + $p->duration("PT5H30M10S"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/PT5H30M10S" ; + + $p->duration(new Net::ICal::Duration("P10DT30M5S")); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/P10DT30M5S" ; + + $p->end("19970101T183000Z"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/PT30M" ; + + $p = new Net::ICal::Period("19970101T180000Z/19970102T070000Z"); + + $p->end("19970101T183000Z"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/19970101T183000Z" ; + + $p->duration("P1DT1H10M"); + print $p->as_ical()."\n"; + die if $p->as_ical() ne "19970101T180000Z/19970102T191000Z" ; + + + +} + +1; + + +__END__ + diff --git a/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Property.pm b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Property.pm new file mode 100644 index 0000000000..0aef347c43 --- /dev/null +++ b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Property.pm @@ -0,0 +1,173 @@ +#!/usr/bin/perl +# -*- Mode: perl -*- +#====================================================================== +# FILE: Property.pm +# CREATOR: eric 1 Mar 01 +# +# DESCRIPTION: +# +# +# $Id$ +# $Locker$ +# +# (C) COPYRIGHT 2000, Eric Busboom, eric@softwarestudio.org +# +# This package is free software and is provided "as is" without express +# or implied warranty. It may be used, redistributed and/or modified +# under the same terms as perl itself. ( Either the Artistic License or the +# GPL. ) +# +# +#====================================================================== + +use Net::ICal::Libical::Property; + + +package Net::ICal::Libical::Property; +use strict; + + +sub new { + + my $class = shift; + my $arg = shift; + my $self = {}; + my $kind; + + if(ref($arg) == 'HASH'){ + + $self->{'ref'} = $arg->{'ref'}; + + } else { + $kind = Net::ICal::Libical::icalproperty_string_to_kind($arg); + $self->{'ref'} = Net::ICal::Libical::icalproperty_new($kind); + } + + die "Did not get icalproperty ref in Net::ICal::Libical::Property::new " if !$self->{'ref'}; + + bless $self, $class; +} + + +sub DESTROY { + my $self = shift; + + my $r = $self->{'ref'}; + + if($r && !Net::ICal::Libical::icalproperty_get_parent($r)){ + Net::ICal::Libical::icalproperty_free($self->{'ref'}); + } +} + +sub name { + my $self = shift; + my $str; + + die if !$self->{'ref'}; + + $str = Net::ICal::Libical::icalproperty_as_ical_string($self->{'ref'}); + + $str =~ /^([A-Z\-]+)\n/; + + return $1; + +} + +#Get/Set the internal reference to the libical icalproperty """ +sub prop_ref { + my $self = shift; + my $p_r = shift; + + if($p_r){ + $self->{'ref'} = $p_r; + } + + return $self->{'ref'}; + +} + + +#Get/set the RFC2445 representation of the value. Dict value 'value' +sub value { + my $self = shift; + my $v = shift; + my $kind = shift; + + my $vt; + if($v){ + + if ($kind) { + $self->{'VALUE'} = $kind; + $vt = $kind; + } + elsif ($self->{'VALUE'}) { + $vt = $self->{'VALUE'}; + } + else { + $vt = 'NO'; # Use the kind of the existing value + } + + + Net::ICal::Libical::icalproperty_set_value_from_string($self->{'ref'},$v,$vt); + + } + + return Net::ICal::Libical::icalproperty_get_value_as_string($self->{'ref'}); + +} + + +# Get a named parameter +sub get_parameter{ + my $self = shift; + my $key = shift; + + die "get_parameter: missing parameter name" if !$key; + + $key = uc($key); + my $ref = $self->{'ref'}; + + my $str = Net::ICal::Libical::icalproperty_get_parameter_as_string($ref,$key); + + if($str eq 'NULL') { + return undef; + } + + return $str + +} + + +# Set the value of the named parameter +sub set_parameter{ + my $self = shift; + my $key = shift; + my $value = shift; + + die "set_parameter: missing parameter name" if !$key; + die "set_parameter: missing parameter value" if !$value; + + $key = uc($key); + my $ref = $self->{'ref'}; + + my $str = Net::ICal::Libical::icalproperty_set_parameter_from_string($ref,$key,$value); + + + return $self->get_parameter($self); + +} + + +sub as_ical_string { + my $self = shift; + my $str = Net::ICal::Libical::icalproperty_as_ical_string($self->{'ref'}); + + $str =~ s/\r//g; + $str =~ s/\n\s?//g; + + return $str; +} + + + +1; diff --git a/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Time.pm b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Time.pm new file mode 100644 index 0000000000..76969ac60d --- /dev/null +++ b/libical/src/Net-ICal-Libical/lib/Net/ICal/Libical/Time.pm @@ -0,0 +1,468 @@ +#!/usr/bin/perl -w +# -*- Mode: perl -*- +#====================================================================== +# +# This package is free software and is provided "as is" without express +# or implied warranty. It may be used, redistributed and/or modified +# under the same terms as perl itself. ( Either the Artistic License or the +# GPL. ) +# +# +#====================================================================== + + + +=pod + +=head1 NAME + +Net::ICal::Time -- represent a time and date + +=head1 SYNOPSIS + + $t = new Net::ICal::Time("19970101T120000Z"); + $t = new Net::ICal::Time("19970101T120000","America/Los_Angeles"); + $t = new Net::ICal::Time(time(),"America/Los_Angeles"); + + $t2 = $t->add(Net::Ical::Duration("1D")); + + $duration = $t->subtract(Net::ICal::Time("19970101T110000Z")) + + # Add 5 minutes + $t->min($t->min()+5); + + # Add 5 minutes + $t->sec($t->sec()+300); + + # Compare + if($t->compare($t2) > 0) {} + +=head1 DESCRIPTION + +I<Time> represents a time, but can also hold the time zone for the +time and indicate if the time should be treated as a date. The time +can be constructed from a variey of formats. + +=head1 METHODS + +=cut + +package Net::ICal::Libical::Time; +use Net::ICal::Libical::Duration; +use Net::ICal::Libical::Property; +use Time::Local; +use POSIX; +use Carp qw(confess cluck); +use strict; +use UNIVERSAL qw(isa); + +@Net::ICal::Libical::Time::ISA = qw(Net::ICal::Libical::Property); + +=pod + +=head2 new + +Creates a new time object given one of: + +=over 4 + +=item * ISO format string + +=item * Some other format string, maybe whatever a Date module understands + +=item * Integer representing seconds past the POSIX epoch + +=back + +The optional second argument is the timezone in Olsen place name format, +which looks like "America/Los_Angeles"; it can be used to get the standard +offset from UTC, the dates the location goes to and from Daylight Savings +Time, and the magnitude of the Daylight Savings time offset. + +=cut + +sub new{ + my $package = shift; + my $arg = shift; + + my $self; + + if (ref($arg) == 'HASH'){ + # Construct from dictionary + $self = Net::ICal::Libical::Property::new($package,$arg); + my $val=Net::ICal::Libical::icalproperty_get_value_as_string($self->{'ref'}); + $self->{'tt'} = Net::ICal::Libical::icaltime_from_string($val); + + return $self; + + } else { + + if ($#_ = 1){ + # iCalendar string + $self = Net::ICal::Libical::Property::new($package,'DTSTART'); + $self->{'tt'} = Net::ICal::Libical::icaltime_new_from_string($arg); + } else { + # Broken out time + die; + } + + $self->_update_value(); + return $self; + } + +} + + +sub _update_value { + my $self = shift; + + if(!$self->{'tt'}){ + die "Can't find reference to icaltimetype"; + } + + $self->value(Net::ICal::Libical::icaltime_as_ical_string($self->{'tt'})); + +} + +=pod + +=head2 clone() + +Create a new copy of this time. + +=cut + +# clone a Time object. +sub clone { + my $self = shift; + + bless( {%$self},ref($self)); + + $self->{'ref'} = Net::ICal::Libical::icalproperty_new_clone($self->{'ref'}); + +} + + + +=pod + +=head2 is_valid() + +TBD + +=cut + +sub is_valid{ + my $self = shift; + + return Net::ICal::Libical::icaltime_is_null_time($self->{'tt'}); + +} + + + +=pod + +=head2 is_date([true|false]) + +Accessor to the is_date flag. If true, the flag indicates that the +hour, minute and second fields are set to zero and not used in +comparisons. + +=cut + + +sub is_date { + my $self = shift; + if(@_){ + + # Convert to true or false + Net::ICal::Libical::icaltimetype_is_date_set($self->{'tt'}, + !(!($_[0]))); + } + + return Net::ICal::Libical::icaltimetype_is_date_get($self->{'tt'}); + +} + + +=pod + +=head2 is_utc([true|false]) + +Is_utc indicates if the time should be interpreted in the UTC timezone. + +=cut + +sub is_utc { + my $self = shift; + if(@_){ + + # Convert to true or false + Net::ICal::Libical::icaltimetype_is_utc_set($self->{'tt'}, + !(!($_[0]))); + } + + return Net::ICal::Libical::icaltimetype_is_utc_get($self->{'tt'}); + +} +=pod + +=head2 timezone + +Accessor to the timezone. Takes & Returns an Olsen place name +("America/Los_Angeles", etc. ) , an Abbreviation, 'UTC', or 'float' if +no zone was specified. + +=cut + +sub timezone { + my $self = shift; + my $tz = shift; + + if($tz){ + $self->set_parameter('TZID',$tz); + } + + return $self->get_parameter('TZID'); + +} + + + +=pod + +=head2 normalize() + +Adjust any out-of range values so that they are in-range. For +instance, 12:65:00 would become 13:05:00. + +=cut + +sub normalize{ + my $self = shift; + + $self->{'tt'} = Net::ICal::Libical::icaltime_normalize($self->{'tt'}); + $self->value(Net::ICal::Libical::icaltime_as_ical_string($self->{'tt'})); + +} + + +=pod + +=head2 hour([$hour]) + +Accessor to the hour. Out of range values are normalized. + +=cut + +=pod +=head2 minute([$min]) + +Accessor to the minute. Out of range values are normalized. + +=cut + +=pod +=head2 second([$dsecond]) + +Accessor to the second. Out of range values are normalized. For +instance, setting the second to -1 will decrement the minute and set +the second to 59, while setting the second to 3600 will increment the +hour. + +=cut + +=pod + +=head2 year([$year]) + +Accessor to the year. Out of range values are normalized. + +=cut + +=pod + +=head2 month([$month]) + +Accessor to the month. Out of range values are normalized. + +=cut + + +=pod + +=head2 day([$day]) + +Accessor to the month day. Out of range values are normalized. + +=cut + +sub _do_accessor { +no strict; + my $self = shift; + my $type = shift; + my $value = shift; + + $type = lc($type); + + if($value){ + my $set = "Net::ICal::Libical::icaltimetype_${type}_set"; + + &$set($self->{'tt'},$value); + $self->normalize(); + $self->_update_value(); + + } + + my $get = "Net::ICal::Libical::icaltimetype_${type}_get"; + + return &$get($self->{'tt'}); +} + + +sub second {my $s = shift; my $v = shift; return $s->_do_accessor('SECOND',$v);} +sub minute {my $s = shift; my $v = shift;return $s->_do_accessor('MINUTE',$v);} +sub hour {my $s = shift; my $v = shift; return $s->_do_accessor('HOUR',$v);} +sub day {my $s = shift; my $v = shift; return $s->_do_accessor('DAY',$v);} +sub month {my $s = shift; my $v = shift; return $s->_do_accessor('MONTH',$v);} +sub year {my $s = shift; my $v = shift; return $s->_do_accessor('YEAR',$v);} + + +=pod + +=head2 add($duration) + +Takes a I<Duration> and returns a I<Time> that is the sum of the time +and the duration. Does not modify this time. + +=cut +sub add { + my $self = shift; + my $dur = shift; + + cluck "Net::ICal::Time::add argument 1 requires a Net::ICal::Duration" if !isa($dur,'Net::ICal::Duration'); + + my $c = $self->clone(); + + $c->second($dur->as_int()); + + $c->normalize(); + + return $c; + +} + +=pod + +=head2 subtract($time) + +Subtract out a time of type I<Time> and return a I<Duration>. Does not +modify this time. + +=cut +sub subtract { + my $self = shift; + my $t = shift; + + cluck "Net::ICal::Time::subtract argrument 1 requires a Net::ICal::Time" if !isa($t,'Net::ICal::Time'); + + my $tint1 = $self->as_int(); + my $tint2 = $t->as_int(); + + return new Net::ICal::Duration($tint1 - $tint2); + +} + +=pod + +=head2 move_to_zone($zone); + +Change the time to what it would be in the named timezone. +The zone can be an Olsen placename or "UTC". + +=cut + +# XXX this needs implementing. +sub move_to_zone { + confess "Not Implemented\n"; +} + + + +=pod + +=head2 as_int() + +Convert the time to an integer that represents seconds past the POSIX +epoch + +=cut +sub as_int { + my $self = shift; + + return Net::ICal::Libical::icaltime_as_timet($self->{'tt'}); +} + +=pod + +=head2 as_localtime() + +Convert to list format, as per localtime() + +=cut +sub as_localtime { + my $self = shift; + + return localtime($self->as_int()); + +} + +=pod + +=head2 as_gmtime() + +Convert to list format, as per gmtime() + +=cut +sub as_gmtime { + my $self = shift; + + return gmtime($self->as_int()); + +} + +=pod + +=head2 compare($time) + +Compare a time to this one and return -1 if the argument is earlier +than this one, 1 if it is later, and 0 if it is the same. The routine +does the comparision after converting the time to UTC. It converts +floating times using the system notion of the timezone. + +=cut +sub compare { + my $self = shift; + my $a = $self->as_int(); + + my $arg = shift; + + if(!isa($arg,'Net::ICal::Time')){ + $arg = new Net::ICal::Time($arg); + } + + my $b = $arg->as_int(); + + if($a < $b){ + return -1; + } elsif ($a > $b) { + return 1; + } else { + return 0; + } + +} + +1; + |