Description
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.