develooper Front page | perl.datetime | Postings from January 2003

DateTime::Set API

Thread Next
From:
Dave Rolsky
Date:
January 15, 2003 11:21
Subject:
DateTime::Set API
Message ID:
Pine.LNX.4.51.0301151233430.9186@urth.org
Ok, looks like Flavio wants to work on this, so let's start discussing
this API.

A quick summary of the existing Date::Set module.

This module handles 4 different things that I am planning to break into
3 different modules:

- Bounded, finite sets of dates (20020211T120202, 20010213T091029)

- Unbounded (left, right, both) sets of dates (every year from
20020211T12020202 onwards), which Date::Set refers to as recurrence

These two will be in DateTime::Set

- Date/Time spans, the infinite set contained between 20020211T120202 and
20020311T150010, which Date::Set refers to as periods

This will be in DateTime::Span

- Sets of disparate spans (periods)

This will be in DateTime::SpanSet


It's quite likely that these three modules will have relatively similar
APIs, and they will probably share a fair amount of common code (they'll
all inherit from Set::Infinite for one thing).

For now, I _just_ want to talk about DateTime::Set.

There are a number of different things people might use DateTime sets for.
One really obvious example is grouping together related datetimes.  For
example, I might create a set of datetimes that represent my meetings for
next month.  This would be a bounded set, since it has a _fixed_ number of
datetimes in it.

The things I'm likely to want to do with this set are:

- create it by specifying either:
-- an explicit set of datetime objects
-- a single object and a rule for generating the rest (every wednesday
from 4-6 PM starting on X)
--- a side note: rules can be arbitrarily complex (callbacks)

- add 1+ datetimes two it (IOW - union of two sets)
- remove 1+ datetimes from it (difference)
- check for the presence of 1+ datetimes in it (is X a subset of Y)
- check to see if two sets overlap (intersection)

- "sort the set" - I put this in quotes because there is no such thing as
a sorted set (despite the crackheadedness of SQL).  Sets are by definition
unordered.  To order a set, you first transform it into something else,
usually a list, and _then_ order it.

But of course we want to make this convenient, so you'll be able to say
"give me the sorted set elements", again with arbitrarily complex sorting
(callbacks!).  Minimal sorting will be built in (ascending, descending)

- iterate over sorted members.  Again, this is not a set operation, but
for convenience we will offer something like

  while ( my $dt = $dt_set->next( sort => 'asc' ) )


An unbounded set will have prety much the same API, except that the
constructor may be a little more complex, and you won't be able to
retrieve the whole set all at once, because it has an infinite number of
members.

Another side note on recurrence:  we will allow people to specify
recurring datetime generators via callbacks.  For what I hope are obvious
reasons, callbacks will have to guarantee that given a datetime X, they
always produce a datetime >X _or_ <X.  If it were both, there'd be no way
to check whether Y was a member of an unbounded set.  This will be a big
fat warning in the docs.


So here's a quick first crack at an API.

Constructors:

  # bounded
  my $dt_set =
      DateTime::Set->new( set => [ 1 or more DateTime objects ] );

  # bounded
  my $dt_set = DateTime::Set->new( start => $dt_object,
                                   end   => $dt_object,
                                   recurrence_callback => \&generate );

  # still bounded
  my $dt_set = DateTime::Set->new( start => $dt_object,
                                   end   => $dt_object,
                                   recurrence_rfc2445 => $rfc_2445_string );

  # unbounded (on "right") - $dt_object & greater datetimes
  my $dt_set = DateTime::Set->new( start => $dt_object,
                                   recurrence_callback => \&generate );

  # unbounded (on "left) - $dt_object & less
  my $dt_set = DateTime::Set->new( end => $dt_object,
                                   recurrence_callback => \&generate );

  # unbounded on both side
  my $dt_set = DateTime::Set->new
                   ( datetime => $dt_object,
                     recurrence_callback_next => \&generate_next,
                     recurrence_callback_prev => \&generate_prev,
                   );
  # again, could use RFC 2445 strings

One thing I left out would be a data structure equivalent to an RFC 2445
string.  I'll have to read RFC 2445 first!

Operations:

  $dt_set->add( set => [ Explicit set of DateTime objects ] );
  $dt_set->add( recurrence_callback => &another_generator );

  $dt_set->remove(); # same as above

  # will not be possible for certain types of unbounded sets
  if ( $dt_set->contains( $dt_object )

  # ditto
  if ( $dt_set->contains( $dt_set ) )

  my $new_dt_set = DateTime::Set->intersection( $dt_set1, $dt_set2, ... );

  # again, not always possible to determine
  if ( $dt_set->overlaps($dt_set2) )

  my $set_iterator = $dt_set->iterator;

  # may never stop!
  while ( my $dt = $set_iterator->next )

  while ( my $dt = $set_iterator->prev )

  $set_iterator->reset;

As the comments above indicate, certain operations are not possible with
certain types of sets.  For example, given two unbounded sets, both
unbounded in the same "direction" (or in both "directions") where the
recurrence generator is a callback, then there's no way to determine
overlap.  I _think_ that if recurrence is specified via a rule (RFC 2445
or data structure) it _should_ be possible to _sometimes_ determine
whether or not they overlap, based on whether or not the recurrence is
purely mathematical for both sets being checked.  That'll be a post 1.0
feature, I think ;)

Without going into _too_ much detail on implementation, and without
arguing to much about tiny things (like method names), are there other
pieces of functionality that people would want related to datetime sets?

Are there things that are known to be impossible (Flavio, especially)
besides what I mentioned already?

Does the basic outline of the API I have above look A) featureful; and B)
easy to grok?



-dave

/*=======================
House Absolute Consulting
www.houseabsolute.com
=======================*/

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About