Interval Operations - Edge Cases¶
Let’s explore how interval operations handle various edge cases:
Adjacent Intervals¶
When intervals are exactly adjacent (end of one equals start of another), the union operation will merge them into a single interval:
# Create adjacent intervals [1, 2] and [2, 3]
adjacent = Interval(start=[1, 2], end=[2, 3])
# Union will merge them into [1, 3]
merged = adjacent | adjacent
print(merged.start) # [1]
print(merged.end) # [3]
Point Intervals¶
Intervals where start equals end (zero duration) are handled gracefully:
# Create point interval [2, 2]
point = Interval(start=[2], end=[2])
# Intersection with another interval containing that point
other = Interval(start=[1], end=[3])
intersection = point & other
print(intersection.start) # [2]
print(intersection.end) # [2]
Empty Intervals¶
Operations with empty intervals (no time periods) return appropriate results:
# Create an empty interval
empty = Interval(start=[], end=[])
# Any intersection with an empty interval is empty
some_interval = Interval(start=[1], end=[2])
intersection = empty & some_interval
print(len(intersection.start)) # 0
# Union with an empty interval returns the non-empty interval
union = empty | some_interval
print(union.start) # [1]
print(union.end) # [2]
Overlapping Input Intervals¶
If you try to perform operations on intervals that aren’t disjoint or sorted, the operations will raise a ValueError:
# Create overlapping intervals [1, 3] and [2, 4]
overlapping = Interval(start=[1, 2], end=[3, 4])
try:
# This will raise a ValueError
overlapping & some_interval
except ValueError as e:
print(e) # "left Interval object must be disjoint."
# Fix by making intervals disjoint first
fixed = overlapping | overlapping # Merges overlapping intervals
result = fixed & some_interval # Now works correctly
Exact Matches¶
When interval boundaries exactly match, both intersection and union handle them appropriately:
# Create two identical intervals
a = Interval(start=[1, 5], end=[3, 7])
b = Interval(start=[1, 5], end=[3, 7])
# Intersection returns the same intervals
intersection = a & b
print(intersection.start) # [1, 5]
print(intersection.end) # [3, 7]
# Union also returns the same intervals
union = a | b
print(union.start) # [1, 5]
print(union.end) # [3, 7]
These edge cases are important to consider when working with intervals, especially in data processing pipelines where unexpected interval patterns might occur.