Datetime tests
=========================================

The rangeset implementation doesn't explicitly
require numbers, so datetime objects should work as well.

Basic construction of rangesets for single ranges:

    >>> from rangeset import *
    >>> from datetime import datetime as D
    >>> NOW = D(2011, 12, 8, 12, 30, 0)
    >>> RangeSet(D(2011, 11, 1), D(2011, 11, 10))
    <RangeSet 2011-11-01 00:00:00 -- 2011-11-10 00:00:00>
    >>> RangeSet(NEGATIVE_INFINITY, NOW)
    <RangeSet -inf -- 2011-12-08 12:30:00>
    >>> RangeSet(INFINITY, NOW)
    <RangeSet 2011-12-08 12:30:00 -- inf>
    >>> RangeSet(NOW, NOW)
    <RangeSet 2011-12-08 12:30:00 -- 2011-12-08 12:30:00>

Static Methods
=========================

The static methods operate on individual range sets to create
more interesting ones:

    >>> RangeSet.mutual_union((D(2010, 1, 5), D(2010, 1, 6)), (D(2011, 1, 1), D(2011, 1, 2)))
    <RangeSet 2010-01-05 00:00:00 -- 2010-01-06 00:00:00, 2011-01-01 00:00:00 -- 2011-01-02 00:00:00>
    >>> RangeSet.mutual_union((D(2010, 1, 10), D(2011, 2, 10)), (NOW, INFINITY))
    <RangeSet 2010-01-10 00:00:00 -- 2011-02-10 00:00:00, 2011-12-08 12:30:00 -- inf>
    >>> RangeSet.mutual_overlaps((D(2010, 1, 10), D(2011, 2, 10)), (D(2010, 6, 10), NOW))
    <RangeSet 2010-06-10 00:00:00 -- 2011-02-10 00:00:00>


Logical Combinations
==========================

Instead of using the static methods above, one can construct rangesets
using logical combination of sets: inversion, union, intersection, difference, and symmetric_difference.

Inversion:

    >>> a = RangeSet(D(2011, 11, 1), D(2011, 11, 10))
    >>> a.invert()
    <RangeSet -inf -- 2011-11-01 00:00:00, 2011-11-10 00:00:00 -- inf>
    >>> ~a
    <RangeSet -inf -- 2011-11-01 00:00:00, 2011-11-10 00:00:00 -- inf>
    >>> ~a.invert()
    <RangeSet 2011-11-01 00:00:00 -- 2011-11-10 00:00:00>
    >>> (~a.invert()) == a
    True

Union:

    >>> a = RangeSet(D(2011, 11, 1), D(2011, 11, 10)) | RangeSet(NOW, D(2012, 1, 1))
    >>> RangeSet(D(2011, 11, 1), D(2011, 11, 10)).union(RangeSet(NOW, D(2012, 1, 1)))
    <RangeSet 2011-11-01 00:00:00 -- 2011-11-10 00:00:00, 2011-12-08 12:30:00 -- 2012-01-01 00:00:00>
    >>> a = RangeSet(D(2011, 11, 1), D(2011, 11, 10)) | RangeSet(NOW, D(2012, 1, 1))
    >>> a
    <RangeSet 2011-11-01 00:00:00 -- 2011-11-10 00:00:00, 2011-12-08 12:30:00 -- 2012-01-01 00:00:00>
    >>> ~a
    <RangeSet -inf -- 2011-11-01 00:00:00, 2011-11-10 00:00:00 -- 2011-12-08 12:30:00, 2012-01-01 00:00:00 -- inf>

Intersection:

    >>> from datetime import datetime as D
    >>> a = RangeSet(D(2011, 1, 10), D(2011, 12, 10)).intersect(RangeSet(D(2011, 6, 2), D(2011, 8, 5)))
    >>> ~a
    <RangeSet -inf -- 2011-06-02 00:00:00, 2011-08-05 00:00:00 -- inf>
    >>> (~a) & RangeSet(D(2011, 1, 10), D(2011, 12, 10))
    <RangeSet 2011-01-10 00:00:00 -- 2011-06-02 00:00:00, 2011-08-05 00:00:00 -- 2011-12-10 00:00:00>

Difference:

    >>> RangeSet(D(2010, 1, 1), D(2011, 10, 5)).difference(RangeSet(D(2010, 6, 1), NOW))
    <RangeSet 2010-01-01 00:00:00 -- 2010-06-01 00:00:00>
    >>> RangeSet(D(2010, 1, 1), D(2011, 10, 5)) - RangeSet(D(2010, 6, 1), NOW)
    <RangeSet 2010-01-01 00:00:00 -- 2010-06-01 00:00:00>

Symmetric Difference:

    >>> RangeSet(D(2010, 1, 1), D(2011, 10, 5)).symmetric_difference(RangeSet(D(2010, 6, 1), NOW))
    <RangeSet 2010-01-01 00:00:00 -- 2010-06-01 00:00:00, 2011-10-05 00:00:00 -- 2011-12-08 12:30:00>
    >>> RangeSet(D(2010, 1, 1), D(2011, 10, 5)) ^ RangeSet(D(2010, 6, 1), NOW)
    <RangeSet 2010-01-01 00:00:00 -- 2010-06-01 00:00:00, 2011-10-05 00:00:00 -- 2011-12-08 12:30:00>

Properties
=====================

There are 4 interesting properties of rangesets:

- min: The minimum element
- max: The maximum element
- range(): The difference of the maximum and the minimum
- measure(): The sum of the ranges of the maximally connected ranges

    >>> a = RangeSet(D(2010, 11, 10), NOW)
    >>> a.max
    datetime.datetime(2011, 12, 8, 12, 30)
    >>> a.min
    datetime.datetime(2010, 11, 10, 0, 0)
    >>> a.range()
    datetime.timedelta(days=393, seconds=45000)
    >>> a.measure()
    datetime.timedelta(days=393, seconds=45000)
    >>> a = RangeSet(D(2011, 12, 8, 6, 30), NOW) | RangeSet(D(2011, 12, 8, 14, 30), D(2011, 12, 8, 23, 23))
    >>> a
    <RangeSet 2011-12-08 06:30:00 -- 2011-12-08 12:30:00, 2011-12-08 14:30:00 -- 2011-12-08 23:23:00>
    >>> a.range()
    datetime.timedelta(seconds=60780)
    >>> a.measure()
    datetime.timedelta(seconds=53580)

Note that range and measure are meaningless for unbounded ranges:

    >>> a = ~RangeSet(D(2010, 11, 10), NOW)
    >>> a
    <RangeSet -inf -- 2010-11-10 00:00:00, 2011-12-08 12:30:00 -- inf>
    >>> a.max
    inf
    >>> a.min
    -inf
    >>> a.range()
    Traceback (most recent call last):
        ...
    ValueError: Cannot compute range with unlimited bounds.
    >>> a.measure()
    Traceback (most recent call last):
        ...
    ValueError: Cannot compute range with unlimited bounds.

Membership tests
=======================

Element checking. Note that boundaries are inclusive:

    >>> a = RangeSet(D(2010, 11, 10), NOW)
    >>> D(2010, 12, 10) in a
    True
    >>> D(2010, 11, 10) in a
    True
    >>> D(2010, 11, 9, 23, 59, 59) in a
    False
    >>> NOW in a
    True
    >>> NOW in RangeSet(NOW, NOW)
    True

Superset/subset checking:

 TODO!
