NAME
Date::Set - Date set math
SYNOPSIS
NOTE: The API is VERY unstable. Please read the POD before upgrading from an earlier version.
use Date::Set;
my $interval = Date::Set->new('20010501')->as_months();
print "This month: ". $interval. "\n\n";
$interval = $interval->as_weeks;
print "Weeks this month: ". $interval."\n\n";
#Offset syntax is subject to change. (as is everything else for now ;)
$interval->offset( mode => 'begin', unit=>'days', value => [ 2, 3] );
print "Tuesdays this month: ". $interval . "\n\n";
# TODO: add some examples of RRULE syntax.
#
DESCRIPTION
Date::Set is a module for date/time sets. It allows you to generate groups of dates, like "every Wednesday", and then find all the dates matching that pattern. It waits until you ask for a particular recurrence before calculating it.
If you want to understand the context of this module, look at IETF RFC 2445 (iCalendar), which specifies a particular syntax for describing recurring events.
It requires Date::ICal and Set::Infinite. If you don't need iCalendar functionality, use Set::Infinite instead.
METHODS
event
event( start =>$date , end => $date, default => 'full' );
Constructor. By default, with no arguments, returns a Date::Set that, by default, encompasses 'forever', that is: (-Inf .. Inf).
Takes a param hash with several optional parameters:
default => ('empty'||'full')
If you specify a default of 'full', the returned object encompasses all of time.
If you specify a default of 'empty', the returned object encompasses no time at all.
Current module behavior always defaults to 'full'.
TODO: see if there are cases where we EVER want to use empty
start => Date::ICal
If you specify a 'start' parameter, the returned set will be bounded to start on that date
end => Date::ICal
If you specify an 'end' parameter, the returned set will be bounded to end on that date
TODO: we have no idea what happens if you set default to 'empty' and also specify a start and/or end date.
TODO: We think this is an internal debugging method. but if so, it should be called _debug or at least _print. it gets used frequently in the code which makes it appear to be more critical than we think it is. --jesse & srl.
Otherwise, it should get proper documentation and be public. but if so, what would it do?
period
period( time => [time1, time2] )
or
period( start => Date::ICal, end => Date::ICal )
This routine is a constructor. Returns an "empty" time period bounded by the dates specified when called in a scalar context.
dtstart
dtstart( start => time1 )
Returns set intersection [time1 .. Inf)
'dtstart' puts a limit on when the event starts. If the event already starts AFTER dtstart, it will not change.
dtend
dtend( end => time1 )
Returns set intersection (Inf .. time1]
'dtend' puts a limit on when the event finishes. If the event already finish BEFORE dtend, it will not change.
duration
duration( unit => 'months', duration => 10 )
All intervals are modified to 'duration'.
'unit' parameter can be years, months, days, weeks, hours, minutes, or seconds.
recur_by_rule
recur_by_rule ( period => date-set, DTSTART => time,
BYMONTH => [ list ], BYWEEKNO => [ list ],
BYYEARDAY => [ list ], BYMONTHDAY => [ list ],
BYDAY => [ list ], BYHOUR => [ list ],
BYMINUTE => [ list ], BYSECOND => [ list ],
BYSETPOS => [ list ],
UNTIL => time, FREQ => freq, INTERVAL => n, COUNT => n,
WKST => day,
RRULE => rrule-string,
include_dtstart => 1 )
All parameters may be upper or lower case.
Implements RRULE from RFC2445.
FREQ can be: SECONDLY MINUTELY HOURLY DAILY WEEKLY MONTHLY or YEARLY
WKST and BYDAY list may contain: SU MO TU WE TH FR SA. By default, weeks start on monday (MO)
BYxxx items must be array references (must be bracketed) if the list has more than one item:
BYMOHTH => 10 or
BYMONTH => [ 10 ] or
BYMONTH => [ 10, 11, 12 ] or
BYMONTH => [ qw(10 11 12) ]
but NOT:
BYMONTH => 10, 11, 12 # NOT!
DTSTART value can be given explicitly, otherwise it will be taken from 'period' or from the set.
NOTE: "DTSTART" is *ALWAYS* included in the recurrence set, whether or not it matches the rule. Use "include_dtstart => 0" to override this.
NOTE: Some recurrences may give very big or even infinity sized sets. The currenct implementation does not detect some of these cases and they might crash your system.
NOTE: The RFC specifies that FREQ is *not* optional.
There are two operating modes: without 'period' it will filter out the rule from the set; with 'period' it will filter out the rule from the period, then add the list to the set.
The datatype for 'period' is Date-Set.
exclude_by_rule
exclude_by_rule ( period => date-set, DTSTART => time,
BYMONTH => [ list ], BYWEEKNO => [ list ],
BYYEARDAY => [ list ], BYMONTHDAY => [ list ],
BYDAY => [ list ], BYHOUR => [ list ],
BYMINUTE => [ list ], BYSECOND => [ list ],
BYSETPOS => [ list ],
UNTIL => time, FREQ => freq, INTERVAL => n, COUNT => n,
WKST => day )
Implements EXRULE (exclusion-rule) from RFC2445.
'period' is optional.
recur_by_date
recur_by_date( list => [time1, time2, ...] )
Adds the (scalar) list to the set, or creates a new list.
This Date::Set will recur on each item of the list provided. This method lets you add items to a set of dates. If you call it multiple times, entries from previous calls will be preserved. If you need to delete them again, use exclude_by_date.
exclude_by_date
exclude_by_date( list => [time1, time2, ...] )
Removes each element of the list from the set.
occurrences
occurrences( period => date-set )
Returns the occurrences for a given period. In other words, "when does this event occur during the given period?"
next_year, next_month, next_week, next_day, next_hour, next_minute, next_day ($date_set)
this_year, this_month, this_week, this_day, this_hour, this_minute, this_day ($date_set)
prev_year, prev_month, prev_week, prev_day, prev_hour, prev_minute, prev_day ($date_set)
next_month( date-set )
this_year ( date-set ) # [20010101..20020101)
Returns the next/prev/this unit of time for a given period.
It answers questions like, "when is next month for the given period?", "which years are covered by this period?"
TODO: explain this and give more examples, cookbook-style.
as_years, as_months, as_weeks, as_days, as_hours, as_minutes, as_days ($date_set)
as_months( date-set )
as_weeks ( date-set )
Returns the given period in a 'unit of time' form.
It answers questions like, "which months we have in this period?", "which years are covered by this period?"
TODO: explain this and give more examples, cookbook-style.
NEW API
Not all of this has been properly implemented or solidified yet. We're assuming Date::Set deals with ICal dates. This still feels a bit weird
Date::Set->new($arg)
Creates a new Date::Set.
$arg can be a string, another Date::Set::ICal object, a Date::ICal object, or a Set::Infinite::Element_Inf object.
start_date ([$date])
sets or gets the starting date(/time?) of the set. If called with no argument, gets the current value; otherwise, sets it.
end_date ([$date])
sets or gets the ending date(/time?) of the set. If called with no argument, gets the current value; otherwise, sets it.
duration (duration_before, duration_after ?)
period (= start_date + end_date, or start_date + duration_after, or duration_before + end_date)
dates_by_rule
date_by_rule or include_dates
huh?
include_period (=union) (syntactic sugar for Set::Infinite::union)
exclude_period (=complement) (syntactic sugar for Set::Infinite::complement)
overlapping_periods_with ($set)
(syntactic sugar for Set::Infinite::intersection)
Returns a Date::Set of the overlaps between $self and another Date::Set.
This can be thought of as "conflicting periods with" or "common periods with", depending on the scheduling application. Free/busy times are more easily thought of as "common periods free", where events are more easily thought of as "periods that conflict with one another" if you've overscheduled.
overlaps_with ( $set )
(syntactic sugar for Set::Infinite::intersects)
Returns true if $self overlaps with $set, a Date::Set. Otherwise returns false.
add_days, add_weeks, add_years ... (=offset)
as_list (=list)
(?) (=iterate)
final_occurrence_before ($date)
$date should be a Date::ICal.
Last occurrence before today;
returns a single-instance Date::Set ("tuesday, 21 january 2000 from 3pm to 4pm")
rule(...)->before(today)->last;
first_occurrence_after ($date)
$date should be a Date::ICal.
Next occurrence;
returns a single-instance Date::Set ("tuesday, 21 january 2000 from 3pm to 4pm")
rule(...)->after(now)->first;
INHERITED METHODS
These methods are inherited from Set::Infinite.
Logic
$logic = $a->intersects($b);
$logic = $a->contains($b);
$logic = $a->is_null;
Set
$i = $a->union($b);
$i = $a->intersection($b);
$i = $a->complement;
Note: 'unit' parameter can be years, months, days, weeks, hours, minutes, or seconds.
BUGS
'duration' and 'period' methods may change in future versions, to generate open-ended sets.
AUTHOR
Flavio Soibelmann Glock <fglock@pucrs.br> with the Reefknot team.