import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
/**
* Generates all dates between startDateStr and endDateStr inclusive.
* Uses Java's java.time API (LocalDate and datesUntil) for robust, calendar-aware date math.
*
* @param startDateStr Start date in "YYYY-MM-DD" format.
* @param endDateStr End date in "YYYY-MM-DD" format.
* @return A List of date strings in "YYYY-MM-DD" format, or an empty list on error.
*/
fun getDatesBetween(startDateStr: String, endDateStr: String): List<String> {
// Standard ISO-8601 formatter for "YYYY-MM-DD"
val formatter = DateTimeFormatter.ISO_LOCAL_DATE
return try {
// 1. Parse input strings safely into immutable LocalDate instances
val startDate = LocalDate.parse(startDateStr, formatter)
val endDate = LocalDate.parse(endDateStr, formatter)
// 2. Validate that the date range is logically sound
require(!startDate.isAfter(endDate)) { "Start date cannot be after the end date." }
// 3. Generate dates inclusive of the end date using datesUntil()
// Note: datesUntil is exclusive of its bound, so we add 1 day to include the end date.
startDate.datesUntil(endDate.plusDays(1))
.map { it.format(formatter) }
.toList()
} catch (e: DateTimeParseException) {
// 4. Handle invalid date format or illegal calendar dates (e.g., "2026-02-31")
System.err.println("Error: Invalid date format or illegal calendar date. Use YYYY-MM-DD.")
emptyList()
} catch (e: IllegalArgumentException) {
// Handle logical range errors (e.g., start date after end date)
System.err.println("Error: ${e.message}")
emptyList()
}
}
fun main() {
// Example usage spanning a month boundary and leap year
val start = "2026-02-26"
val end = "2026-03-02"
val dates = getDatesBetween(start, end)
println("Dates between $start and $end:")
dates.forEach { println(it) }
}
/*
run:
Dates between 2026-02-26 and 2026-03-02:
2026-02-26
2026-02-27
2026-02-28
2026-03-01
2026-03-02
*/