Summary
timeflow already provides elapsed and unit_elapsed for computing the distance between two points in time. A natural and frequently needed companion is a first-class range/interval type that encapsulates a start and end, and exposes operations over the interval as a whole.
Without this, consumers must manually carry paired (Date, Date) tuples and re-implement containment, overlap, and iteration logic in every project.
Proposed Types
pub struct DateRange {
start: Date, // inclusive
end: Date, // inclusive
}
pub struct DateTimeRange {
start: DateTime, // inclusive
end: DateTime, // inclusive
}
Proposed API
// Construction
let range = DateRange::new(start, end)?; // Err if start > end
let range = DateRange::new_unchecked(start, end); // no validation
// Querying
range.contains(&date) -> bool
range.overlaps(&other_range) -> bool
range.is_adjacent_to(&other_range) -> bool // end + 1 day == other.start
range.duration() -> chrono::Duration
range.unit_duration(DateUnit::Month) -> i64
// Mutation
range.extend(DateUnit::Day, 3)? -> DateRange // grow end by 3 days
range.shift(DateUnit::Month, 1)? -> DateRange // shift both bounds forward by 1 month
// Iteration
range.iter_days() -> impl Iterator<Item = Date>
range.iter_months() -> impl Iterator<Item = Date> // first day of each month in range
Real-World Use Cases
- Booking / reservation systems: check if a requested period overlaps an existing booking
- Billing periods: iterate months within a contract range
- Event scheduling: test whether a datetime falls within an event window
- Token / session validity: express an access window as a
DateTimeRange
- Reporting: iterate over weeks or months within a fiscal quarter range
Implementation Notes
DateRange::new should return Err(SpanError) if start > end to prevent inverted ranges.
iter_days() should yield Date values from start to end inclusive, advancing by DateUnit::Day.
- Overlap semantics: two ranges overlap if
self.start <= other.end && self.end >= other.start (closed-interval semantics).
- Serde: serialize as
{ "start": "...", "end": "..." }, respecting BASE_*_FORMAT.
- Feature-gated by the
date / datetime features respectively.
Acceptance Criteria
Summary
timeflowalready provideselapsedandunit_elapsedfor computing the distance between two points in time. A natural and frequently needed companion is a first-class range/interval type that encapsulates a start and end, and exposes operations over the interval as a whole.Without this, consumers must manually carry paired
(Date, Date)tuples and re-implement containment, overlap, and iteration logic in every project.Proposed Types
Proposed API
Real-World Use Cases
DateTimeRangeImplementation Notes
DateRange::newshould returnErr(SpanError)ifstart > endto prevent inverted ranges.iter_days()should yieldDatevalues fromstarttoendinclusive, advancing byDateUnit::Day.self.start <= other.end && self.end >= other.start(closed-interval semantics).{ "start": "...", "end": "..." }, respectingBASE_*_FORMAT.date/datetimefeatures respectively.Acceptance Criteria
DateRange::new(start, end)returnsErrwhenstart > endcontains,overlaps,duration,unit_durationare implemented and testediter_daysanditer_monthsreturn correct sequences including edge cases (leap years, month-end)shiftandextendreturn new instances (immutable API, consistent with existing types)DateTimeRangemirrors the same API at datetime granularity