保持状态的日期间隔

时间:2017-12-28 09:14:27

标签: scala

我的任务是编写函数,它接受2个LocalDateTime实例并生成间隔列表,分割15分钟

case class Interval(start:LocalDateTime, end:LocalDateTime)

所以,例如,如果startDate = 2017年8月2日14:30:15而且endDate是2017年8月2日15:00:00,则间隔应为

List(Interval(2 Aug 2017 14:30:15, 2 Aug 2017 14:45:15), Interval(2 Aug 2017 14:45:15, 2 Aug 2017 15:00:00))

这里有2个主要并发症(至少对我而言) 1)如果结束日期小于prevDate + 15分钟,那么我们需要从最小值(prevdate + 15 min,endDate)开始 2)我们需要以某种方式保持状态,因为每个间隔的开始是前一个间隔的结束。

我能够创建命令式版本,但我想在功能样式中做,请帮忙!)

x => {
  var start = x.startTime
  var end = min(findRightBorder(start), x.endTime)
  var result = ListBuffer(Interval(start, end))
  while (end.isBefore(x.endTime)) {
    start = end
    end = min(start.plusMinutes(QUARTER_MINUTES), x.endTime)
    result += Interval(start, end)
  }
  result.toList
}

private def findRightBorder(dt: LocalDateTime): LocalDateTime = {
  val minute = dt.getMinute
  if (minute >= 0 && minute < 15) dt.withMinute(15)
  else if (minute >= 15 && minute < 30) dt.withMinute(30)
  else if (minute >= 30 && minute < 45) dt.withMinute(45)
  else if (minute >= 45 && minute < 60) dt.withMinute(0).plusHours(1)
  else dt
}

private def min(dt1: LocalDateTime, dt2: LocalDateTime): LocalDateTime = {
  if (dt1.compareTo(dt2) < 0) dt1 else dt2
}

2 个答案:

答案 0 :(得分:1)

这是解决这个问题的一种方法。

import java.time.LocalDateTime

case class Interval(start:LocalDateTime, end:LocalDateTime)

val dt1: LocalDateTime = ??? //some start DateTime
val dt2: LocalDateTime = ??? //some end DateTime

// a (potentially) infinite Stream of dates at 15 minute intervals
// starting at dt1 but ending before dt2
val dates = Stream.iterate(dt1)(_.plusMinutes(15L))
                  .takeWhile(_.isBefore(dt2))

val result = dates.sliding(2)  //pair the dates together
                  .toSeq       //a Seq is easier to append to
                  .map{case Seq(from,to) => Interval(from,to)}  //make Intervals
                  .:+(Interval(dates.last,dt2)) //append the final Interval
                  .toList      //if you need a List result

答案 1 :(得分:1)

使用流的另一种解决方案:

x => {
  Stream
    .from(0)
    .map(i => x.startTime.plusMinutes(i * QUARTER_MINUTES))
    .takeWhile(_.isBefore(x.endTime))
    .map(s => Interval(s, min(s.plusMinutes(QUARTER_MINUTES), x.endTime)))
    .toList
}