import java.time.LocalDate
import java.time.format.{DateTimeFormatter, DateTimeParseException}
import scala.jdk.CollectionConverters.*
import scala.util.{Try, Success, Failure}
object DateRangeGenerator {
/**
* Generates all dates between startDateStr and endDateStr inclusive.
* Uses Java's java.time API interoperability 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.
*/
def getDatesBetween(startDateStr: String, endDateStr: String): List[String] = {
// Standard ISO-8601 formatter for "YYYY-MM-DD"
val formatter = DateTimeFormatter.ISO_LOCAL_DATE
val dateRangeTry = 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
if (startDate.isAfter(endDate)) {
throw new IllegalArgumentException("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))
.iterator()
.asScala // Convert Java Iterator to Scala Iterator
.map(_.format(formatter))
.toList
}
// 4. Handle parsing errors or invalid calendar dates gracefully (e.g., "2026-02-31")
dateRangeTry match {
case Success(dates) => dates
case Failure(ex) =>
System.err.println(s"Error: Invalid date format or illegal calendar date. Details: ${ex.getMessage}")
List.empty[String]
}
}
def main(args: Array[String]): Unit = {
// 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(s"Dates between $start and $end:")
dates.foreach(println)
}
}
/*
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
*/