injixo/time_frame — pull request #6 by jzernisch (2014-06-25 06:42:09+00:00)
Title: Null object

This is a possible solution for #1. It introduces the constant `TimeRange::EMPTY` which behaves as follows:

- **`#min`** and **`#max`** return `nil`
- **`#duration`**: returns `0`
- **`#inspect`** returns `'EMPTY'` (consistent with `Float::INFINITY.inspect()`, which is `'INFINITY'`)
- **`#==`**: `TimeRange::EMPTY` only equals itself.
- **`#&`** and **`.intersection`**: Intersecting with `TimeFrame::EMPTY` results in `TimeFrame::EMPTY`
- **`#cover?`**: Every covers `TimeFrame::EMPTY`, nothing is covered by it.
- **`#deviation_of`**: `TimeFrame::EMPTY` has a deviation `0` from itself, and a deviation of `Float::INFINITY` from everything else. I also fixed the (unexpected?) behavior of not returning absolute values. Now it's just the [Hausdorff Distance](http://en.wikipedia.org/wiki/Hausdorff_distance) with the canonical extension for empty sets.
- **`#split_by_interval`**, **`#without`** and **`.union`**: These methods always return arrays of **non-empty** time frames (as before). So `TimeRange::EMPTY` is simply ignored when passed to `.union` or `#without`; `#split_by_interval` and `#without` return `[]` when called on `TimeFrame::EMPTY`.
- **`#empty?`**: returns `true` for `TimeRange::EMPTY`, of course. But unlike before it now returns `false` when `#min` equals `#max` (because the the difference is that those time frames contain one point, and thus are not empty).
- **`#overlaps?`** and **`.each_overlap`**: The definition is now: "X overlaps Y if and only if their interiors have a non-empty intersection". Therefore there is nothing that overlaps with `TimeRange::EMPTY` or any one-point time frame.
- **`#shift_by`** and **`#shift_to`** raise a `TypeError` when called on `TimeRange::EMPTY` (consistent with calling `#dup` on `nil`, for example).
- **`.covering_time_frame_for`** returns `TimeRange::EMPTY` if there are no non-empty time frames within the arguments.
- `TimeRange::EMPTY` is not constructible via `TimeRange.new` (it is implemented a singleton subclass instance of `TimeRange`).