首页 > 解决方案 > 如何在Scala中生成n天的动态日期范围

问题描述

我想使用 Scala 将过去 'n' 天的日期范围作为字符串。以下是我的输入

输入

开始日期 ="2020-08-20"

范围 = 30(天)

预期输出:

"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"

标签: scala

解决方案


我建议使用Iterator.iterate来产生一个懒惰的日期序列:

import java.time.LocalDate

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

你可以让这个迭代器前进step > 0或后退step < 0(或静止不动step == 0,但你不太可能想要那个)。

在您的情况下,您可能不得不step = -1为迭代器中的每个项目一次向后移动一天,然后再从它们中移出.take(30)项目mkString

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

您可以在 Scastie 上使用此代码。

请注意,Iterators 是可变的,这意味着它们不能在您的代码中安全地共享。对于纯功能替代方案,您可以使用LazyList如此 Scastie 片段所示。

现在,这种方法的问题在于,您可能会无意中导致无限循环:如果您不这样做.take(30),对的调用mkString将永远不会终止。如果您希望有一个严格的集合,您可以使用range在 s 上定义的方法,List首先生成一个整数范围,然后将范围中的每个项目添加到您的开始日期,如下面的替代方案例子:

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

在这里你可以找到文档List.range(你会很容易理解为什么我通过了step,因为我在阅读文档时可能会在 Scastie 上玩一下这个片段)。

请注意,您也可以对s 和其他惰性序列使用相同的方法(range方法) 。Iterator

关于惰性集合与严格集合、可变集合与不可变集合的一些资源:


推荐阅读