-1

I want daterange for last 'n' days as a string using Scala. Below are my inputs

Input:

startingDate = "2020-08-20"

range = 30 (days)

Expected output:

"2020-08-20,2020-08-19,2020-08-18,2020-08-17,2020-08-16,2020-08-15,2020-08-14,2020-08-13,2020-08-12,2020-08-11,2020-08-10,2020-08-19,2020-08-09,2020-08-08,2020-08-07,2020-08-06,2020-08-05,2020-08-04,2020-08-03,2020-08-02,2020-08-01,2020-07-31,2020-07-30,2020-07-29,2020-07-28,2020-07-27,2020-07-26,2020-07-25,2020-07-24,2020-07-23,2020-07-22"
jwvh
  • 50,871
  • 7
  • 38
  • 64
Suresh Kumar
  • 169
  • 1
  • 1
  • 4

2 Answers2

0

I would recommend using Iterator.iterate to produce a lazy sequence of dates:

import java.time.LocalDate

def days(start: LocalDate, step: Int): Iterator[LocalDate] =
  Iterator.iterate(start)(_.plusDays(step))

You can have this iterator go forward with step > 0 or backwards with step < 0 (or stand still with step == 0, but you're unlikely to want that).

In your case you can have step = -1 to move backward one day at a time for each item in the iterator and then .take(30) items and mkString out of them:

val startingDate = LocalDate.parse("2020-08-20")

val output = days(start = startingDate, step = -1).take(30).mkString(",")

// output is 2020-08-20,2020-08-19,2020-08-18,2020-08-17,...

You can play around with this code here on Scastie.

Note that Iterators are mutable, which means that they can't be safely shared across your code. For a purely functional alternative you can use a LazyList, as shown in this Scastie snippet.

Now, the problem with this approach is that you may inadvertently cause an infinite loop: if you don't .take(30) the call to mkString will never terminate. If you prefer to have a strict collection, you can use the range method, which is defined, among others, on Lists, by first producing a range of integers and then adding each item in the range to your starting date, as in the following alternative example:

import java.time.LocalDate

def days(start: LocalDate, end: Long): List[LocalDate] =
  List.range(0, end, step = if (end < 0) -1 else 1).map(start.plusDays)

val startingDate = LocalDate.parse("2020-08-20")

val output = days(start = startingDate, end = -30).mkString(",")

// output is the same as in the previous example

Here you can find the documentation for List.range (you'll easily understand why I passed step as I did reading the documentation and maybe playing a bit around with this snippet on Scastie).

Note that you can use the same approach (the range method) with Iterators and other lazy sequences as well.

A few resources on lazy vs. strict and mutable vs. immutable collections:

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
0
import java.time.LocalDate

def previousDatesStr(startingDateStr: String, range: Int): String = {
    val startingDate = LocalDate.parse(startingDateStr)
    Range(0, range).map(d => startingDate.minusDays(d)).mkString(", ")
}

Other answers are great. but try to use as less java library as possible. since you are using scala.