| Date::ICal::Duration - durations in iCalendar format, for math purposes. |
Date::ICal::Duration - durations in iCalendar format, for math purposes.
$Revision: 1.61 $
use Date::ICal::Duration;
$d = Date::ICal::Duration->new( ical => '-P1W3DT2H3M45S' );
$d = Date::ICal::Duration->new( weeks => 1,
days => 1,
hours => 6,
minutes => 15,
seconds => 45);
# a one hour duration, without other components
$d = Date::ICal::Duration->new( seconds => "3600");
# Read-only accessors:
$d->weeks;
$d->days;
$d->hours;
$d->minutes;
$d->seconds;
$d->sign;
# TODO: Resolve sign() discussion from rk-devel and update synopsis.
$d->as_seconds (); # returns just seconds
$d->as_elements (); # returns a hash of elements, like the accessors above
$d->as_ical(); # returns an iCalendar duration string
=head1 DESCRIPTION
This is a trivial class for representing duration objects, for doing math in Date::ICal
Rich Bowen, and the Reefknot team (www.reefknot.org)
Last touched by $Author: rbowen $
Date::ICal::Duration has the following methods available:
A new Date::ICal::Duration object can be created with an iCalendar string :
my $ical = Date::ICal::Duration->new ( ical => 'P3W2D' );
# 3 weeks, 2 days, positive direction
my $ical = Date::ICal::Duration->new ( ical => '-P6H3M30S' );
# 6 hours, 3 minutes, 30 seconds, negative direction
Or with a number of seconds:
my $ical = Date::ICal::Duration->new ( seconds => "3600" );
# one hour positive
Or, better still, create it with components
my $date = Date::ICal::Duration->new (
weeks => 6,
days => 2,
hours => 7,
minutes => 15,
seconds => 47,
sign => "+"
);
The sign defaults to ``+'', but ``+'' and ``-'' are legal values.
=cut
#}}}
#{{{ sub new
sub new { my ($class, %args) = @_; my $verified = {}; my $self = {}; bless $self, $class;
my $seconds_only = 1; # keep track of whether we were given length in seconds only
$seconds_only = 0 unless (defined $args{'seconds'});
# If one of the attributes is negative, then they all must be
# negative. Otherwise, we're not sure what this means.
foreach (qw(hours minutes seconds days weeks)) {
if (defined($args{$_}) ) {
# make sure this argument is all digits, optional - sign
if ($args{$_} =~ m/-?[0-9]+$/) {
if ($args{$_} < 0) {
$args{sign} = '-';
$args{$_} = abs($args{$_});
}
$verified->{$_} = $args{$_};
unless ($_ eq 'seconds') {
$seconds_only = 0;
}
} else {
carp ("Parameter $_ contains non-numeric value " . $args{$_} . "\n");
}
}
}
if (defined ($args{sign}) ) {
# make sure this argument + or -
if ($args{sign} =~ m/[+-]/) {
# if so, assign it
$self->{sign} = ($args{sign} eq "+") ? 1 : -1;
$verified->{sign} = ($args{sign} eq "+") ? '+' : '-';
} else {
carp ("Parameter sign contains a value other than + or - : "
. $args{sign} . "\n");
}
}
# If a number is given, convert it to hours, minutes, and seconds,
# but *don't* extract days -- we want it to represent an absolute
# amount of time, regardless of timezone
if ($seconds_only) { # if we were given an integer time_t
$self->_set_from_seconds($args{'seconds'});
} elsif (defined ($args{'ical'}) ) {
# A standard duration string
#warn "setting from ical\n";
$self->_set_from_ical($args{'ical'});
} elsif (not $seconds_only) {
#warn "setting from components";
#use Data::Dumper; warn Dumper $verified;
$self->_set_from_components($verified);
}
return undef unless %args;
return $self;
}
#}}}
# Accessors {{{
Read-only accessors for the elements of the object.
Returns the duration in raw seconds.
WARNING -- this folds in the number of days, assuming that they are always 86400 seconds long (which is not true twice a year in areas that honor daylight savings time). If you're using this for date arithmetic, consider using the add() method from a the Date::ICal manpage object, as this will behave better. Otherwise, you might experience some error when working with times that are specified in a time zone that observes daylight savings time.
$days = $duration->as_days;
Returns the duration as a number of days. Not to be confused with the
days method, this method returns the total number of days, rather
than mod'ing out the complete weeks. Thus, if we have a duration of 33
days, weeks will return 4, days will return 5, but as_days will
return 33.
Note that this is a lazy convenience function which is just weeks*7 + days.
Return the duration in an iCalendar format value string (e.g., ``PT2H0M0S'')
Returns the duration as a hashref of elements.
head2 GENERAL MODEL
Internally, we store 3 data values: a number of days, a number of seconds (anything shorter than a day), and a sign (1 or -1). We are assuming that a day is 24 hours for purposes of this module; yes, we know that's not completely accurate because of daylight-savings-time switchovers, but it's mostly correct. Suggestions are welcome.
NOTE: The methods below SHOULD NOT be relied on to stay the same in future versions.
Converts a RFC2445 DURATION format string to the internal storage format.
Regular expression for parsing iCalendar into usable values.
Converts from a hashref to the internal storage format. The hashref can contain elements ``sign'', ``weeks'', ``days'', ``hours'', ``minutes'', ``seconds''.
Sets internal data storage properly if we were only given seconds as a parameter.
Return an arrayref to hours, minutes, and second components, or undef if nsecs is undefined. If given an arrayref, computes the new nsecs value for the duration.
_wd()Return an arrayref to weeks and day components, or undef if ndays is undefined. If Given an arrayref, computs the new ndays value for the duration.
| Date::ICal::Duration - durations in iCalendar format, for math purposes. |