Interval Guide¶
The Interval class represents time intervals with start and end points, supporting comprehensive operations like intersection, union, and overlap detection.
Overview¶
Intervals are half-open: [start, end) - inclusive start, exclusive end. This means the start time is included, but the end time is not.
from carbonic import DateTime, Date, Interval
# Meeting from 9:00 AM to 10:30 AM
meeting = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 10, 30)
)
# 9:00 AM is included, 10:30 AM is not
meeting.contains(DateTime(2024, 1, 15, 9, 0)) # True - start included
meeting.contains(DateTime(2024, 1, 15, 10, 30)) # False - end excluded
meeting.contains(DateTime(2024, 1, 15, 10, 29)) # True - before end
Creating Intervals¶
DateTime Intervals¶
from carbonic import DateTime, Interval
# Meeting interval
meeting = Interval(
start=DateTime(2024, 1, 15, 9, 0, tz="UTC"),
end=DateTime(2024, 1, 15, 10, 30, tz="UTC")
)
# Conference session
session = Interval(
start=DateTime(2024, 3, 10, 14, 0, tz="America/New_York"),
end=DateTime(2024, 3, 10, 16, 30, tz="America/New_York")
)
Date Intervals¶
from carbonic import Date, Interval
# Vacation period
vacation = Interval(
start=Date(2024, 7, 1),
end=Date(2024, 7, 15)
)
# Project sprint
sprint = Interval(
start=Date(2024, 2, 5),
end=Date(2024, 2, 19) # 2-week sprint
)
Mixed Date/DateTime Intervals¶
from carbonic import Date, DateTime, Interval
# Event spanning from a date to a specific time
event = Interval(
start=Date(2024, 6, 15), # Start of June 15th
end=DateTime(2024, 6, 16, 18, 0) # 6:00 PM on June 16th
)
Basic Properties¶
from carbonic import DateTime, Interval
meeting = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 10, 30)
)
# Duration of the interval
duration = meeting.duration()
print(duration.in_minutes()) # 90.0 minutes
# Check if interval is empty (start == end)
empty = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 9, 0)
)
print(empty.is_empty()) # True
Containment Operations¶
Contains Point in Time¶
from carbonic import DateTime, Date, Interval
# DateTime interval
meeting = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 10, 30)
)
# Check specific times
print(meeting.contains(DateTime(2024, 1, 15, 9, 15))) # True
print(meeting.contains(DateTime(2024, 1, 15, 10, 30))) # False (end excluded)
print(meeting.contains(DateTime(2024, 1, 15, 11, 0))) # False
# Date interval
vacation = Interval(start=Date(2024, 7, 1), end=Date(2024, 7, 15))
print(vacation.contains(Date(2024, 7, 5))) # True
print(vacation.contains(Date(2024, 7, 15))) # False (end excluded)
Check if One Interval Contains Another¶
from carbonic import DateTime, Interval
# Main conference day
conference = Interval(
start=DateTime(2024, 3, 10, 8, 0),
end=DateTime(2024, 3, 10, 18, 0)
)
# Morning keynote
keynote = Interval(
start=DateTime(2024, 3, 10, 9, 0),
end=DateTime(2024, 3, 10, 10, 30)
)
# Check if keynote is within conference
def contains_interval(outer, inner):
"""Check if outer interval contains inner interval."""
return (inner.start >= outer.start and inner.end <= outer.end)
keynote_within_conference = contains_interval(conference, keynote)
print(keynote_within_conference) # True
Overlap Operations¶
Check for Overlap¶
from carbonic import DateTime, Interval
morning_meeting = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 10, 30)
)
afternoon_meeting = Interval(
start=DateTime(2024, 1, 15, 14, 0),
end=DateTime(2024, 1, 15, 15, 30)
)
overlapping_meeting = Interval(
start=DateTime(2024, 1, 15, 10, 0), # Overlaps last 30 minutes
end=DateTime(2024, 1, 15, 11, 0)
)
print(morning_meeting.overlaps(afternoon_meeting)) # False
print(morning_meeting.overlaps(overlapping_meeting)) # True
Find Intersection¶
from carbonic import DateTime, Interval
meeting1 = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 11, 0)
)
meeting2 = Interval(
start=DateTime(2024, 1, 15, 10, 0),
end=DateTime(2024, 1, 15, 12, 0)
)
# Find overlapping time
overlap = meeting1.intersection(meeting2)
if overlap:
print(f"Overlap: {overlap.start} to {overlap.end}") # 10:00 to 11:00
else:
print("No overlap")
Find Union¶
from carbonic import DateTime, Interval
session1 = Interval(
start=DateTime(2024, 1, 15, 9, 0),
end=DateTime(2024, 1, 15, 10, 30)
)
session2 = Interval(
start=DateTime(2024, 1, 15, 10, 0), # Overlaps with session1
end=DateTime(2024, 1, 15, 12, 0)
)
# Combine intervals
combined = session1.union(session2)
print(f"Combined: {combined.start} to {combined.end}") # 9:00 to 12:00
Practical Examples¶
Meeting Scheduler¶
from carbonic import DateTime, Interval
def find_free_time(scheduled_meetings, work_start, work_end):
"""Find free time slots between meetings."""
work_interval = Interval(start=work_start, end=work_end)
# Sort meetings by start time
meetings = sorted(scheduled_meetings, key=lambda m: m.start)
free_slots = []
current_time = work_start
for meeting in meetings:
if current_time < meeting.start:
# Found free time before this meeting
free_slots.append(Interval(current_time, meeting.start))
current_time = max(current_time, meeting.end)
# Check for free time after last meeting
if current_time < work_end:
free_slots.append(Interval(current_time, work_end))
return free_slots
# Usage
meetings = [
Interval(DateTime(2024, 1, 15, 9, 0), DateTime(2024, 1, 15, 10, 30)),
Interval(DateTime(2024, 1, 15, 14, 0), DateTime(2024, 1, 15, 15, 30)),
]
work_day = Interval(
DateTime(2024, 1, 15, 8, 0),
DateTime(2024, 1, 15, 17, 0)
)
free_times = find_free_time(meetings, work_day.start, work_day.end)
for slot in free_times:
duration = slot.duration()
print(f"Free: {slot.start.format('H:i')} - {slot.end.format('H:i')} ({duration.in_hours():.1f}h)")
Project Timeline¶
from carbonic import Date, Interval
# Project phases
planning = Interval(Date(2024, 1, 1), Date(2024, 2, 1))
development = Interval(Date(2024, 1, 15), Date(2024, 4, 1)) # Overlaps with planning
testing = Interval(Date(2024, 3, 15), Date(2024, 4, 15))
# Find overlaps
planning_dev_overlap = planning.intersection(development)
if planning_dev_overlap:
print(f"Planning/Development overlap: {planning_dev_overlap.duration().in_days()} days")
# Check if phases contain specific dates
milestone_date = Date(2024, 2, 15)
if development.contains(milestone_date):
print("Milestone is during development phase")
Time Range Analysis¶
from carbonic import DateTime, Interval
def analyze_time_ranges(intervals):
"""Analyze a list of time intervals."""
if not intervals:
return {}
# Sort by start time
sorted_intervals = sorted(intervals, key=lambda i: i.start)
# Total time covered
earliest = sorted_intervals[0].start
latest = max(interval.end for interval in intervals)
total_span = Interval(earliest, latest)
# Total duration (sum of all intervals)
total_duration = sum(
(interval.duration() for interval in intervals),
start=Duration()
)
# Find gaps between intervals
gaps = []
for i in range(len(sorted_intervals) - 1):
current_end = sorted_intervals[i].end
next_start = sorted_intervals[i + 1].start
if current_end < next_start:
gaps.append(Interval(current_end, next_start))
return {
'total_span': total_span,
'total_duration': total_duration,
'gaps': gaps,
'utilization': total_duration.total_seconds() / total_span.duration().total_seconds()
}
Error Handling¶
from carbonic import DateTime, Interval
# Invalid interval (end before start)
try:
invalid = Interval(
start=DateTime(2024, 1, 15, 10, 0),
end=DateTime(2024, 1, 15, 9, 0)
)
except ValueError as e:
print(f"Error: {e}") # End time must be after start time
Type Compatibility¶
from carbonic import Date, DateTime, Interval
# Same types work seamlessly
date_interval = Interval(Date(2024, 1, 1), Date(2024, 1, 31))
datetime_interval = Interval(
DateTime(2024, 1, 15, 9, 0),
DateTime(2024, 1, 15, 17, 0)
)
# Mixed types are automatically handled
mixed_interval = Interval(
Date(2024, 1, 15), # Converted to start of day
DateTime(2024, 1, 16, 12, 0) # Specific time
)
See Also¶
- DateTime Guide - Working with datetimes
- Date Guide - Date-only operations
- Duration Guide - Time spans and arithmetic
- API Reference - Complete Interval API