Scala 如何在相同/不同年份的两周编号之间生成所有周?

Scala 如何在相同/不同年份的两周编号之间生成所有周?,scala,Scala,在我的应用程序中,一周表示为字符串,格式为: {year}-{week-no} // week-no ranges from 1 to 52 例如:2017年第7周表示为:2017-07 我想写一个方法,它需要两个星期的日期,并在这两个给定的星期之间生成所有的星期。因此,如果我通过: 2017-05和2017-08(相同年份):方法应返回列表(2017-052017-062017-072017-08) 2017-05和2019-02(不同年份):方法应返回列表(2017-052017-06,

在我的应用程序中,一周表示为字符串,格式为:

{year}-{week-no} // week-no ranges from 1 to 52
例如:2017年第7周表示为:
2017-07

我想写一个方法,它需要两个星期的日期,并在这两个给定的星期之间生成所有的星期。因此,如果我通过:

  • 2017-05
    2017-08
    (相同年份):方法应返回
    列表(2017-052017-062017-072017-08)
  • 2017-05
    2019-02
    (不同年份):方法应返回
    列表(2017-052017-06,……2017-512017-522018-012018-02,……2018-512018-522019-012019-02)
到目前为止,我已经开发了以下有效的解决方案:

def weeksGenerator(fromWeek: String,toWeek: String): List[String] = {
    val upperWeekNummber = fromWeek.split("-").toList.last.toInt
    val upperYearNummber = fromWeek.split("-").toList.head.toInt
    val lowerWeekNummber = toWeek.split("-").toList.last.toInt
    val lowerYearNummber = toWeek.split("-").toList.head.toInt

    (lowerYearNummber - upperYearNummber) match {
      case 0L => Range.inclusive(upperWeekNummber,lowerWeekNummber).map{weekNum =>
        s"${upperYearNummber.toString}-${weekNum}"
      }.toList
      case diff: Int =>
        Range.inclusive(0,diff).foreach(println)
        Range.inclusive(0,diff).flatMap{
        d => if(d==diff){
          // this is the last element
          Range.inclusive(1,lowerWeekNummber).map{weekNum =>
            s"${(upperYearNummber+d).toString}-${weekNum}"
          }
        }
        else if(d ==0) {
          // first element
          Range.inclusive(upperWeekNummber,52).map{weekNum =>
            s"${(upperYearNummber+d).toString}-${weekNum}"
          }
        }
        else {
          Range.inclusive(1,52).map{weekNum =>
            s"${(upperYearNummber+d).toString}-${weekNum}"
          }
        }
      }.toList
    }
  }
我认为我的解决方案有两个问题:

  • 我不认为这是最简洁、最实用的解决方案
  • 当周数从
    1到9时,我想生成
    2017-01
    2017-02
    ,而不是
    2017-1
    2017-2
    。我不想手动附加0。我正在寻找更好的方法

那么,这里最好的方法是什么呢?

我可能会做以下几点:

def weeksGenerator(fromWeek: String,toWeek: String): List[String] = {
  val maxWeeks = 52
  val minWeeks = 1

  val year1 = fromWeek.split("-")(0).toInt
  val year2 = toWeek.split("-")(0).toInt
  val week1 = fromWeek.split("-")(1).toInt
  val week2 = toWeek.split("-")(1).toInt

  val wholeWeeks = minWeeks to maxWeeks
  val years = year1 to year2
  val headWeeks = week1 to maxWeeks
  val lastWeeks = minWeeks to week2

  val enumeratedYears = years.zip(1 to years.length)
  val yearsAndWeeksZip = enumeratedYears.map{case (year, index) => if (index == 1) (year, headWeeks) else if (index == years.length) (year, lastWeeks) else (year, wholeWeeks)}
  val yearsAndWeeks = yearsAndWeeksZip.flatMap{case (year, weeks) => weeks.map(week => year.toString + "-" + "%02d".format(week))}

  yearsAndWeeks.toList
}
您可以使用
格式
正确显示数字:

scala> "%02d".format(4)
res15: String = 04

scala> "%02d".format(50)
res16: String = 50
在REPL上:

scala> weeksGenerator("2017-10", "2018-01")
res3: List[String] = List(2017-10, 2017-11, 2017-12, 2017-13, 2017-14, 2017-15, 2017-16, 2017-17, 2017-18, 2017-19, 2017-20, 2017-21, 2017-22, 2017-23, 2017-24, 2017-25, 2017-26, 2017-27, 2017-28, 2017-29, 2017-30, 2017-31, 2017-32, 2017-33, 2017-34, 2017-35, 2017-36, 2017-37, 2017-38, 2017-39, 2017-40, 2017-41, 2017-42, 2017-43, 2017-44, 2017-45, 2017-46, 2017-47, 2017-48, 2017-49, 2017-50, 2017-51, 2017-52, 2018-01)

我认为这个解决方案描述了一种使用高阶函数来解决这个问题的简洁明了的方法。它可以缩短,但我想它会失去清晰度。

我可能会这样做:

def weeksGenerator(fromWeek: String,toWeek: String): List[String] = {
  val maxWeeks = 52
  val minWeeks = 1

  val year1 = fromWeek.split("-")(0).toInt
  val year2 = toWeek.split("-")(0).toInt
  val week1 = fromWeek.split("-")(1).toInt
  val week2 = toWeek.split("-")(1).toInt

  val wholeWeeks = minWeeks to maxWeeks
  val years = year1 to year2
  val headWeeks = week1 to maxWeeks
  val lastWeeks = minWeeks to week2

  val enumeratedYears = years.zip(1 to years.length)
  val yearsAndWeeksZip = enumeratedYears.map{case (year, index) => if (index == 1) (year, headWeeks) else if (index == years.length) (year, lastWeeks) else (year, wholeWeeks)}
  val yearsAndWeeks = yearsAndWeeksZip.flatMap{case (year, weeks) => weeks.map(week => year.toString + "-" + "%02d".format(week))}

  yearsAndWeeks.toList
}
您可以使用
格式
正确显示数字:

scala> "%02d".format(4)
res15: String = 04

scala> "%02d".format(50)
res16: String = 50
在REPL上:

scala> weeksGenerator("2017-10", "2018-01")
res3: List[String] = List(2017-10, 2017-11, 2017-12, 2017-13, 2017-14, 2017-15, 2017-16, 2017-17, 2017-18, 2017-19, 2017-20, 2017-21, 2017-22, 2017-23, 2017-24, 2017-25, 2017-26, 2017-27, 2017-28, 2017-29, 2017-30, 2017-31, 2017-32, 2017-33, 2017-34, 2017-35, 2017-36, 2017-37, 2017-38, 2017-39, 2017-40, 2017-41, 2017-42, 2017-43, 2017-44, 2017-45, 2017-46, 2017-47, 2017-48, 2017-49, 2017-50, 2017-51, 2017-52, 2018-01)

我认为这个解决方案描述了一种使用高阶函数来解决这个问题的简洁明了的方法。它可以缩短,但我想它会失去清晰性。

我认为最好的方法是依赖java.time api

代码可能如下所示(我不包括对输入的解析):

import java.time.DayOfWeek
导入java.time.LocalDate
导入java.time.temporal.IsoFields
导入java.time.temporal.ChronoUnit
导入java.time.format.DateTimeFormatter
导入java.time.temporal.TemporalAdjusters
val initialDate=LocalDate.ofYearDay(2017年,50)。`with`(IsoFields.WEEK\u OF the u WEEK\u OF u BASED\u YEAR,50)。`with`(temporaladjusts.previousorname(DayOfWeek.MONDAY))
val finalDate=LocalDate.ofYearDay(2017年,50)。`with`(IsoFields.WEEK,OF OF OF OF OF OF OF OF OF OF OF OF OF WEEK,OF U BASED OF U YEAR,8)。`with`(TemporalAdjusters.PreviousorName(DayOfWeek.MONDAY))
为了{

我认为最好的方法是依赖java.time api

代码可能如下所示(我不包括对输入的解析):

import java.time.DayOfWeek
导入java.time.LocalDate
导入java.time.temporal.IsoFields
导入java.time.temporal.ChronoUnit
导入java.time.format.DateTimeFormatter
导入java.time.temporal.TemporalAdjusters
val initialDate=LocalDate.ofYearDay(2017年,50)。`with`(IsoFields.WEEK\u OF the u WEEK\u OF u BASED\u YEAR,50)。`with`(temporaladjusts.previousorname(DayOfWeek.MONDAY))
val finalDate=LocalDate.ofYearDay(2017年,50)。`with`(IsoFields.WEEK,OF OF OF OF OF OF OF OF OF OF OF OF OF WEEK,OF U BASED OF U YEAR,8)。`with`(TemporalAdjusters.PreviousorName(DayOfWeek.MONDAY))
为了{

i您可以利用java time API为您完成繁重的工作(处理闰周等)。只需将您的输入解析为
LocalDate
,然后使用Chrono API获取其间的周数

import java.time.LocalDate
import java.time.temporal.ChronoUnit
import java.time.format.DateTimeFormatter

def listOfWeeks(initialWeekString: String, finalWeekString: String): List[String] = {
  val dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-ww-EEE")
  val dateTimeFormatter2 = DateTimeFormatter.ofPattern("YYYY-ww")

  val initialDate = LocalDate.parse(initialWeekString + "-Mon", dateTimeFormatter)
  val finalDate = LocalDate.parse(finalWeekString + "-Mon", dateTimeFormatter)

  val weeksCount = ChronoUnit.WEEKS.between(initialDate, finalDate).toInt

  (0 to weeksCount)
    .map(i => initialDate.plusWeeks(i).format(dateTimeFormatter2))
    .toList
}

println(listOfWeeks("2017-05", "2017-06"))

// List(2017-05, 2017-06)

您可以利用java time API为您完成繁重的工作(如处理闰周等)。只需将您的输入解析为
LocalDate
,然后使用Chrono API获取其间的周数

import java.time.LocalDate
import java.time.temporal.ChronoUnit
import java.time.format.DateTimeFormatter

def listOfWeeks(initialWeekString: String, finalWeekString: String): List[String] = {
  val dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY-ww-EEE")
  val dateTimeFormatter2 = DateTimeFormatter.ofPattern("YYYY-ww")

  val initialDate = LocalDate.parse(initialWeekString + "-Mon", dateTimeFormatter)
  val finalDate = LocalDate.parse(finalWeekString + "-Mon", dateTimeFormatter)

  val weeksCount = ChronoUnit.WEEKS.between(initialDate, finalDate).toInt

  (0 to weeksCount)
    .map(i => initialDate.plusWeeks(i).format(dateTimeFormatter2))
    .toList
}

println(listOfWeeks("2017-05", "2017-06"))

// List(2017-05, 2017-06)

根据您的使用情况,您可能需要考虑闰周,这将使解决方案变得复杂一些。根据您的使用情况,您可能需要考虑闰周,这将使解决方案变得复杂一些。如何稍微修改解决方案,以使用适当的DateTimeFormatter更好地匹配问题要求ement?对解决方案稍加修改,以使用适当的DateTimeFormatter更好地匹配问题要求如何?很好的努力。但解决方案不起作用,因为基于周的日历和公历之间存在偏差。更准确地说,一年没有52周。很好的努力。但解决方案不起作用因为周为基础的日历和公历之间存在偏差。更确切地说,一年没有52周。