Skip to content

Split a range by a step or period, and Values(step) on the discrete types #100

Closed

Description

@CaffeinatedCoder

Python portion has iterate(interval, step); Rust rangemap has StepLite; NodaTime's DateInterval enumerates days; Guava's ContiguousSet enumerates a discrete domain. (portion: https://raw.githubusercontent.com/AlexandreDecan/portion/master/README.md ; NodaTime: https://nodatime.org/3.2.x/api/NodaTime.DateInterval.html .) The library has Values() on the discrete types (one element per step of the domain) and nothing for a step of the consumer's choosing, nor for cutting a range into sub-ranges: the billing months inside a contract period, the 30-minute slots inside opening hours, the ISO weeks of a quarter.

Proposed API (per type, since T arithmetic is not generic):

  • DateRange.Split(DateRangeStep step) / NodaTime LocalDateRange.Split(Period) → IEnumerable<TRange>: consecutive sub-ranges of the step length, the last one clipped to the range's end.
  • DateTimeRange.Split(TimeSpan), DateTimeOffsetRange.Split(TimeSpan), TimeRange.Split(TimeSpan), InstantRange.Split(Duration); Int32Range.Split(int), Int64Range.Split(long), DecimalRange.Split(decimal).
  • Values(step) overloads for the discrete types, the stepping form of Values().

Unbounded ranges throw at the call, as Values() does. A calendar-aligned split (first of month, Monday) is where this meets #48 (calendar factories); the two should share the week rule.

Translation: none. generate_series returns rows, not a scalar, which is the documented reason Values() is in-memory only (E31). Say so in docs/efcore.md#what-runs-where.

Done when: Split is documented in docs/ranges.md with the clipping rule, held by claims, and a metamorphic test holds RangeSet.From(range.Split(step)) == RangeSet.From([range]) and that pieces are pairwise adjacent.

Found by the comparable-library survey (portion, rangemap, NodaTime), 2026-10-17.

Activity

  1. added
    enhancementNew feature or request
    area/rangesRange unions, variants and the shape engines
    package/nodatimeAffects CodoMetis.ValueRanges.NodaTime
    package/coreAffects CodoMetis.ValueRanges
    on Oct 17, 2026
  2. added this to the 10.0.0 milestone on Oct 18, 2026
  3. CaffeinatedCoder commented on Oct 18, 2026

    @CaffeinatedCoder
    OwnerAuthor

    Decided in #197: the calendar split takes a function, Split(Func<DateOnly, DateRange> period), rather than the sketched DateRangeStep type. contract.Split(DateRange.Month) and quarter.Split(DateRange.IsoWeek) reuse the #48 factories and their ISO week rule. A fiscal year or billing cycle is any function returning the period that holds a day, and the LTS line gets no extra public type. Fixed steps: Split(int days) on DateRange, Split(Period) on LocalDateRange, and the element's own step type elsewhere, each boundary counted from the start.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/rangesRange unions, variants and the shape enginesenhancementNew feature or requestpackage/coreAffects CodoMetis.ValueRangespackage/nodatimeAffects CodoMetis.ValueRanges.NodaTime

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions