Evaluate date-range overlap and validity¶
Determine whether DateRange values are individually valid, overlap pairwise or across an ordered sequence, form a contiguous sequence, or contain/are matched by a given date. This operation covers every member of DateRangeExtensions that compares, validates, or filters DateRange values.
| Field | Value |
|---|---|
| Operation ID | OP-02 |
| Trigger | A consumer calls DateRangeExtensions.IsOverlapping, IsValidRange/IsOpenEnded/IsFutureRange/IsPastRange, IsContiguous, IsOverLapping (sequence form), IsInRange, AsOf<T>, ContainsDateRange, or ContainsBeginDate. |
| Inputs | range1, range2 (DateRange), optional inAllowSameDateOverlap (bool, default false); an IEnumerable<DateRange>/IEnumerable<T> where T : DateRange plus a ContiguousOptions/OverlappingOptions/DateTime/DateTime? as appropriate |
| Outputs | A bool result for the validity/overlap/contiguity/membership members; IEnumerable<T> for AsOf<T>. |
| Primary components | DateRangeExtensions.IsOverlapping, .IsValidRange, .IsOpenEnded, .IsFutureRange, .IsPastRange, .IsContiguous, .IsOverLapping, .IsInRange, .AsOf<T>, .ContainsDateRange, .ContainsBeginDate |
| Entry point | src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Extensions/DateRangeExtensions.cs |
Steps¶
Pairwise overlap (IsOverlapping)¶
- Evaluate the leading guard
range2 != null, which invokesDateRange's custom!=operator with the second operand bound to thenullliteral; the operator body dereferences that operand'sBeginDateunconditionally, so this guard throwsNullReferenceExceptionfor essentially every call — with a nullrange2or a perfectly valid one — before any other step runs. (BR-013) - (Intended algorithm, unreached in ordinary use because of step 1.) Verify both ranges pass
IsValidRange(begin <= end). (BR-012) - If either range is invalid:
IsOverlappingreturnsfalse. - (Intended algorithm, unreached in ordinary use.) Select the comparison mode:
ExclusivewheninAllowSameDateOverlapistrue, otherwiseInclusive. - (Intended algorithm, unreached in ordinary use.) Test whether either range's begin or end date
IsBetweenthe other range's dates, using the selected comparison mode, or whether the two ranges are exactly equal with begin not equal to end.
Single-range validity (IsValidRange/IsOpenEnded/IsFutureRange/IsPastRange)¶
IsValidRangereturnsBeginDate <= EndDatedirectly; this comparison itself cannot throw, but callingIsValidRangeon anullDateRangereceiver throwsNullReferenceExceptionwhenBeginDateis dereferenced, since the extension method does not null-checkrange. (BR-012)IsOpenEndedreturns whetherBeginDate == DateTime.MinValue || EndDate == DateTime.MaxValue; the same null-receiver caveat applies — anullDateRangethrowsNullReferenceExceptionon the first property access rather than returning abool.IsFutureRange/IsPastRangecallIsValidRangefirst, then compare againstDateTime.Now; results depend on the server's current clock and time zone.*
Sequence contiguity (IsContiguous)¶
- Fewer than 2 ranges in the input sequence: return
trueimmediately. (BR-014) - Order the remaining ranges by
BeginDate. - Test each consecutive pair against the selected
ContiguousOptionspolicy: StartMatchesEnd: the current range's begin must equal the previous range's end.StartIsNextDay(default): the previous range's end plus one day must equal the current range's begin.AllowGaps: the current range's begin must be at or after the previous range's end.- Return
falseas soon as any consecutive pair fails the selected policy; otherwise returntrueafter the last pair.
Sequence overlap (IsOverLapping)¶
- Fewer than 2 ranges in the input sequence: return
falseimmediately. - Order the remaining ranges by
BeginDate. - On the first iteration, skip the "ignore null date" branch check and fall through directly into the unconditional
switch (option)block below —previousis stillnullat this point. - The
switch (option)block dereferencesprevious.EndDate(DatesMayMatch:range.BeginDate < previous.EndDate;DatesMayNotMatch:range.BeginDate <= previous.EndDate) regardless of loop position, so this dereference of anullpreviousthrowsNullReferenceExceptionon the first iteration for any input of 2 or more ranges — the method cannot return normally for its only valid input size.* - (Intended algorithm, unreached because of step 4.) For later iterations, an open-ended previous range followed by a non-
MinValue/MaxValuebegin date returnstrue; otherwise the selectedOverlappingOptionspolicy decides whether consecutive ranges overlap.
Range membership and date filtering (IsInRange, AsOf-T, ContainsDateRange, ContainsBeginDate)¶
IsInRange(DateTime, IncludeComparisons)tests whetherdatefalls withinrange.BeginDate/EndDateusingIComparableExtensions.IsBetweenunder the selected boundary-inclusion mode (defaultFirstOnly: begin inclusive, end exclusive). (BR-015)IsInRange(DateTime?, IncludeComparisons)returnsfalseimmediately for anulldate, otherwise delegates to step 1.AsOf<T>(ranges, date, rangeOption)filtersrangeswith.Where(r => r.IsInRange(date, rangeOption))and returns every matching item, not just the first. (BR-015)ContainsDateRange(ranges, range)returns whether any element ofrangeshas aBeginDateandEndDateboth exactly equal torange's, viaAny— an exact begin/end membership test, not geometric containment.ContainsBeginDate(ranges, beginDate)returns whether any element ofrangeshas aBeginDateexactly equal tobeginDate, viaAny.
Process flow¶
The following diagrams visualize each branch family's control flow separately, since they are independent code paths with distinct short-circuits and error conditions.
The first diagram covers IsOverlapping's pairwise-overlap control flow, showing the unconditional guard failure before the intended validity/overlap branches.
flowchart TD
Start([Call IsOverlapping]) --> NullGuard["Evaluate range2 != null<br>(DateRange operator !=)"]
NullGuard -->|"Always dereferences<br>the null-literal operand"| Throws([Throws NullReferenceException])
NullGuard -.->|"Intended, unreached"| ValidCheck{Both ranges<br>IsValidRange?}
ValidCheck -.->|No| ReturnFalse([Return false])
ValidCheck -.->|Yes| ModeCheck{inAllowSameDateOverlap?}
ModeCheck -.->|Yes| Exclusive[Use Exclusive comparison]
ModeCheck -.->|No| Inclusive[Use Inclusive comparison]
Exclusive -.-> Test["Test begin/end IsBetween<br>other range"]
Inclusive -.-> Test
Test -.-> End([Return bool result])
The second diagram covers the sequence-overlap (IsOverLapping) control flow, showing its own unconditional first-iteration failure, separate from the pairwise IsOverlapping guard above.
flowchart TD
S_Start([Call IsOverLapping]) --> S_CountCheck{Fewer than<br>2 ranges?}
S_CountCheck -->|Yes| S_False([Return false])
S_CountCheck -->|No| S_Order["Order ranges<br>by BeginDate"]
S_Order --> S_First["First iteration:<br>previous is still null"]
S_First --> S_Switch["Evaluate switch(option)<br>on previous.EndDate"]
S_Switch -->|"Always dereferences<br>null previous"| S_Throws([Throws NullReferenceException])
S_Switch -.->|"Intended, unreached"| S_OpenCheck{Previous open-ended<br>and current not<br>MinValue/MaxValue?}
S_OpenCheck -.->|Yes| S_True([Return true])
S_OpenCheck -.->|No| S_PolicyCheck{OverlappingOptions<br>policy satisfied?}
S_PolicyCheck -.->|Yes| S_True
S_PolicyCheck -.->|No| S_Continue(["Continue to<br>next range"])
The third diagram covers sequence contiguity (IsContiguous), which short-circuits cleanly and completes end-to-end without the null-dereference defects above.
flowchart TD
C_Start([Call IsContiguous]) --> C_CountCheck{Fewer than<br>2 ranges?}
C_CountCheck -->|Yes| C_True([Return true])
C_CountCheck -->|No| C_Order["Order ranges<br>by BeginDate"]
C_Order --> C_PairCheck{Each pair satisfies<br>selected policy?}
C_PairCheck -->|No, any pair| C_False([Return false])
C_PairCheck -->|Yes, all pairs| C_True
The fourth diagram covers single-range validity (IsValidRange/IsOpenEnded) and range membership/date filtering (IsInRange, AsOf<T>, ContainsDateRange, ContainsBeginDate), all of which complete normally for a non-null receiver/sequence.
flowchart TD
M_Start(["Call validity or<br>membership member"]) --> M_Which{Which member?}
M_Which -->|IsValidRange| M_Compare1(["Return BeginDate<br><= EndDate"])
M_Which -->|IsOpenEnded| M_Compare2(["Return BeginDate==Min<br>or EndDate==Max"])
M_Which -->|IsInRange| M_Between(["Return date.IsBetween<br>(begin, end, mode)"])
M_Which -->|AsOf-T| M_Filter(["Return Where filter<br>of matching items"])
M_Which -->|ContainsDateRange<br>or ContainsBeginDate| M_Any(["Return Any exact-<br>match test"])
Failure and edge-case behavior¶
IsOverlappingthrowsNullReferenceExceptionfrom therange2 != nullguard for essentially every call, whetherrange2isnullor a valid, non-nullDateRange; theIsValidRange/comparison-mode/IsBetweenlogic described in the steps above is the intended algorithm but is not reachable in ordinary use.*IsOverLapping(sequence form) throwsNullReferenceExceptionfor any input of 2 or more ranges, because theswitch (option)block dereferencesprevious.EndDateunconditionally on the first iteration whilepreviousis stillnull.*IsContiguousreturnstrue(not an exception) for fewer than 2 ranges; this is the one short-circuit case in this operation group that behaves as intended end-to-end.IsValidRange/IsOpenEndedperform direct date comparisons onrange's own properties with no null check of their own, so they return a normalboolfor any non-nullDateRangereceiver but throwNullReferenceExceptionif the receiver itself isnull.IsFutureRange/IsPastRangedepend onDateTime.Now, so results vary with server clock and time zone.*IsInRange(DateTime?, IncludeComparisons)returnsfalsefor anulldate rather than throwing.
Related documentation¶
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with**could not be confirmed; treat as unknown until verified.
Sources¶
src/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Extensions/DateRangeExtensions.cssrc/SAIF.NetCore.Common/SAIF.NetCore.Common/SAIF.NetCore.Common/Types/DateRange.cs