Skip to content

Feature Request: Add step functionality for date/time ranges #516

Closed as not planned
@lonelymeko

Description

@lonelymeko

Motivation:

Currently, iterating over a range of kotlinx-datetime types (LocalDate, LocalDateTime, Instant) with a specific step requires manual loop logic (e.g., using while and manually adding the step). This contrasts with standard Kotlin ranges (like IntRange, LongRange) which offer a convenient step() infix function for easy iteration.

Adding a similar step capability to kotlinx-datetime ranges would significantly improve usability for common tasks such as:

  • Generating data points at regular intervals (e.g., daily reports, hourly summaries).

  • Iterating through calendar views or schedules.

  • Processing time-series data with specific increments.

Proposed Solution (High-Level):

Introduce step infix extension functions that operate on ClosedRange where T is a kotlinx-datetime type. These functions would return an Iterable (or potentially a dedicated Progression type) allowing for iteration with a specified increment.
The appropriate step type would depend on the range type:

  • LocalDateRange: Step using DatePeriod.

  • InstantRange: Step using kotlin.time.Duration.

  • LocalDateTimeRange: Could potentially step using:

    DatePeriod (affecting the date part only).

    kotlin.time.Duration (affecting the whole date-time, but requires careful TimeZone handling).

    (Possibly DateTimePeriod as well, also requiring TimeZone handling)

Example Usage:

`import kotlinx.datetime.*
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.days

val startDate = LocalDate(2024, 1, 1)
val endDate = LocalDate(2024, 1, 10)

// Iterate Wednesdays within the range (or similar period logic)
val weeklyPeriod = DatePeriod(days = 7) // Or calculate specific period
// for (date in startDate..endDate step weeklyPeriod) { ... } // Example goal

// Iterate every 2 days
for (date in startDate..endDate step DatePeriod(days = 2)) {
println(date) // 2024-01-01, 2024-01-03, ..., 2024-01-09
}

val startInstant = Clock.System.now()
val endInstant = startInstant + 1.days

// Iterate every 6 hours
for (instant in startInstant..endInstant step 6.hours) {
println(instant)
}

val startDateTime = LocalDateTime(2024, 3, 10, 1, 30) // DST change example
val endDateTime = startDateTime + 2.days

// Iterate by DatePeriod (time remains 01:30)
for (ldt in startDateTime..endDateTime step DatePeriod(days = 1)) {
println(ldt) // 2024-03-10 01:30, 2024-03-11 01:30, 2024-03-12 01:30
}

// Iterate by Duration (requires TimeZone context)
val zone = TimeZone.of("America/New_York")
// How should TimeZone be provided? This needs discussion.
// Example hypothetical API:
// for (ldt in startDateTime..endDateTime step (6.hours using zone)) {
// println(ldt) // e.g., 2024-03-10 01:30, 2024-03-10 07:30, ... (respecting DST)
// }`

Request for Feedback:

Would the kotlinx-datetime maintainers be interested in adding such step functionality to the library? If so, what would be the preferred API design, particularly regarding the TimeZone requirement for LocalDateTime steps involving time components (Duration, DateTimePeriod)?

I'd be potentially interested in contributing an implementation if a clear direction is established.

Thank you for considering this proposal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions