Date::Interval

NAME

Date::Interval - handling of temporal intervals based on Date::Manip


SYNOPSIS

    use Date::Interval;

    ### class methods ###
    Date::Interval->setDefaultIntervalType ($Date::Interval::OPEN_INT); 
    $int_open = new Date::Interval ("10-10-1997", "10-20-1997"); 
    print "$int_open\n"        # prints  '(10-10-1997, 10-20-1997) 

    $nDefaultType = Date::Interval->getDefaultIntervalType;

    ### constructor ##
    $i1 = new Date::Interval ("10-30-1997", "12-01-1998");
    $i2 = new Date::Interval ("01-20-1996", "11-01-1997", $Date::Interval::RIGHT_OPEN_INT);

    use Date::Manip;
    $date1 = &ParseDate ("10-10-1997");
    $date2 = &ParseDate ("10-15-1997");
    $int = new Date::Interval ($d1, $d2);

    ### Overload operators ###
    $i3 = $i1 + $i2;          # + gives the sum of intervals if the overlap
    print "$i3\n";            # prints '[01-20-1997, 12-01-1998)'

    $i4 = $i1 - $i2;          # - gives difference of intervals of intervals
    print "$i4\n";            # prints '[11-01-1997, 12-01-1998)'
   
    $i5 = $i1 - $i1; 
    print "$i5\n";            # prints '<empty>'

    ### <Allen overlap type> ### 
    $X = new Date::Interval (<parameters>);
    $Y = new Date::Interval (<parameters>);
                              ###  relationship between intervals ###
    $Y->AllenBefore ($X);             YYYYYY XXXXXX

    $Y->AllenMeets ($X);              YYYYYYXXXXXX

    $Y->AllenLeftOverlaps ($X);          XXXXXX
                                      YYYYYY

    $Y->AllenLeftCovers ($X);            XXXXXX
                                      YYYYYYYYY

    $Y->AllenCovers ($X);                XXXXXX
                                      YYYYYYYYYYYY

    $Y->AllenStarts ($X);             XXXXXX
                                      YYY

    $Y->AllenEquals ($X);             XXXXXX
                                      YYYYYY
    
    $Y->AllenRightCovers ($X);        XXXXXX
                                      YYYYYYYYY

    $Y->AllenDuring ($X);             XXXXXX
                                       YYYY

    $Y->AllenFinishes ($X);           XXXXXX
                                        YYYY 

    $Y->AllenRightOverlaps ($X);      XXXXXX
                                         YYYYYY

    $Y->AllenExtends ($X);            XXXXXXYYYYYY

    $Y->AllenAfter ($X):              XXXXXX YYYYYY

    ### <overlap type> ###
    $Y->before ($X)         same as  $Y->AllenBefore ($X)
    $Y->meets  ($X)         same as  $Y->AllenMeets ($X)

    $Y->leftOverlaps ($X)   same as  $Y->AllenLeftOverlaps ($X)  or
                                     $Y->AllenStarts ($X)

    $Y->totalOverlaps ($X)  same as  $Y->AllenCovers ($X)        or
                                     $Y->AllenLeftCovers ($X)    or
                                     $Y->AllenRightCovers ($X)   or
                                     $Y->AllenEquals ($X)

    $Y->rightOverlaps ($X)  same as  $Y->AllenFinishes ($X)      or
                                     $Y->AllenRightCovers

    $Y->during ($X)         same as  $Y->AllenDuring ($X)
    $Y->extends ($X)        same as  $Y->AllenExtends ($X)
    $Y->after ($X)          same as  $Y->AllenAfter ($X)

    ### <interval type> ###
    $closed_int = new Interval ("10-10-1997", "10-20-1997", $CLOSED_INT); 
    print "$closed_int\n";      # prints [10-10-1997, 10-20-1997]

    $left_open_int = new Interval ("10-10-1997", "10-20-1997", $LEFT_OPEN_INT); 
    print "$left_open_int\n";   # prints (10-10-1997, 10-20-1997]

    $right_open_int = new Interval ("10-10-1997", "10-20-1997", $RIGHT_OPEN_INT); 
    print "$right_open_int\n";  # prints [10-10-1997, 10-20-1997)

   $open_int = new Interval ("10-10-1997", "10-20-1997", $OPEN_INT); 
   print "$open_int\n";         # prints (10-10-1997, 10-20-1997)

   ### check and get overlapping interval ###
    $i1 = new Interval ("10-30-1997", "12-01-1998");
    $i2 = new Interval ("01-20-1996", "11-01-1997");
    $i3 = new Interval ("01-01-1995", "04-30-1995");

    if ($i1->overlaps ($i2)) {
        $i4 = $i1->getOverlap($i2);
        print "$i4\n";              # prints [10-30-1997, 11-01-1997)
    }
    if ($i1->overlaps ($i3)){       # tests fails, does not print anything
        $i5 = $i1->getOverlap($i2);
        print "$i5\n";
    }


DESCRIPTION

    All strings which can be used to create a Date::Manip date object
    can be used to create an Interval. However, the start date must be
    greater than the stop date. Because Date::Manip both handles dates
    and times this module can also handle both dates and times.

    The comparison of intervals is based on the 13 ways intervals can
    overlap as defined by J.F. Allen (See the litteratur). Further, I
    have included a small number of interval comparison which are
    handy if you are only interested in getting the overlapping region
    of two intervals.


Open and Closed Intervals

    A closed interval is closed in an interval where both the start
    and the stop values are included in the interval. As an example
    [10-10-1997, 10-30-1997] both the 10th and the 30th of November is
    a part of the interval.

    An open interval is an interval where the start value or the stop
    value are not included in the interval. In the right open interval
    [10-10-1997, 10-30-1997) the 10th of November is a part of the
    interval but the 30th of November is not. 

    There are three types of open intervals
    - right open intervals, e.g., [10-10-1997, 10-30-1997)
    - left open intervals, e.g., (10-10-1997, 10-30-1997]
    - open intervals, e.g., (10-10-1997, 10-30-1997)


Absolute and Relative Intervals

    An absolute interval is an interval where the start and the stop
    values of the inteval are anchored on the time line, i.e., they
    are specific dates as 04-30-1994.

    A relative interval is an interval where the start or the stop
    value is not anchored on the time line, e.g., 'tomorrow'. When
    'tomorrow' evaluated now it has one value when evaluated a month
    from now it has a different values.

    Date::Interval fully supports absolute intervals and to a limited
    degree relative intervals. 

    The relative intervals supported currently (NOW :-)) are of the
    following type.

    $int1 = new Date::Interval("10-21-1997", 'NOBIND NOW');

    Relative start and stop values are prefixed with the word
    'NOBIND'. In the example 'NOBIND NOW' means that the current time
    (now) whenever it asked for. So if you ask for the length of $int1
    at the 24th of October you get 3 days. If you ask for the length
    of $int1 again at the 28th of October you get 7 days.

    I am working on additional support for relative Intervals.


Defaults

    The default interval type is right open intervals. Stick to this
    interval type if you want to keep life simple.

    To use Date::Manip the time zone variable must be set. It is
    default set to Central European Time (CET). For Americans, this is
    the Capital of Stockholm :-).

    To change the time zone, e.g., to Eastern Standard Time (EST) put
    in our script $Date::Manip::TZ = 'EST'; (As an European I assume
    this must be close to Atlanta, New Mexico).

    The default input format is default of Date::Manip, that is
    "10-12-1997" is the 12th of October 1997 not the 10th of December
    1997. To change the input format, e.g., put in our script
    &Date::Manip::Date_Init("DateFormat=non-US");

    The default output format is MM-DD-YYY. It Can be changed by
    calling Interval->setDisplayFormat(<string>). Where <string> is
    a UnixDate format in Date::Manip.

    The default separator when an interval is printed is the special
    variable $, $OUTPUT_FIELD_SEPARATOR. If this value is not defined
    ',' is used.


The "Fixed" Clock

    The module has a class variable $NOW which contains the current
    time. The current time must be fixed when relative intervals are
    compared, otherwise the comparison may return the wrong result. As
    an example if the two intervals [NOBIND NOW, NOBIND NOW) [NOBIND
    NOW, NOBIND NOW) are compared for equality the result is
    true. However, if the equality comparison is implemented by asking
    four time for the current time the times returned may be different
    because the *real world clock* ticks between the invocations of
    getting the current time. If the clock ticks the equality
    predicate in the example returns false.

    Because different interval objects must be compared with the same
    clock the variable must be a class variable and not an instance
    variable. $NOW is used in the method _to_date.


"Non-terminals" used in the Source Code

::= Date::Manip delta data type
::= Date::Manip data type
::= CLOSE || OPEN
::= CLOSED_INT || OPEN_INT || LEFT_OPEN_INT || RIGHT_OPEN_INT
::= ABSOLUTE || RELATIVE
::= How two intervals overlaps
::= How two intervals Allen overlaps


BUGS

    Tried my best to avoid them send me an email if you are bitten by
    a bug. 

    Note, the module cannot handle subtract intervals which overlap
    with "during" overlaps, this results in two intervals (currently
    results in an empty interval)


TODO

    - Cannot take references to dates as input parameters for the
      constructors

    - Cannot subtract intervals which overlap with "during" overlaps,
      this results in two intervals (currently results an error message and
      an empty interval is returned)

    - Implement getOverlap and overloaded operators for relative intervals


Change History

    ### Changes version 0.01 => 0.02 ###
    - Add overload  <, >, ==, !=, <=>. 
    - Add stringLength, to print length of interval in a more readable way.
    - Changed the default separator to the $, special variable
    - Added support for comparison of relative intervals 

    Changes thanks to Tim Bruce
    - Changed the module name from Interval to Date::Interval
    - Added methods getStart and getStop.
    - Added method lengthString to print nicely the length of the
      interval.
    - Changed the default output format to be similar to the 
      default input format
    - Taken BEGIN {$Date::Manip::TZ = "CET"; &Date_Init ("DateFormat=non-US");}
      out because it is anti-social :-)
    - Added to POD that the both dates and times can be used with intervals
    - Added to POD the description of open and closed intervals


LITTERATURE

    Allen, J. F., "An Interval-Based Representation of Temporal Knowledge",
    Communication of the ACM, 26(11) pp. 832-843, November 1983.


AUTHOR

Kristian Torp <torp@cs.auc.dk>