在我的应用程序中,一周表示为格式为String的字符串:
{year}-{week-no} // week-no ranges from 1 to 52
例如: 2017年第7周表示为:2017-07
我想写一个方法,它需要两个星期的日期,并在这两个星期之间产生所有周。所以,如果我通过:
2017-05
和2017-08
(相同年份):该方法应返回List(2017-05,2017-06,2017-07,2017-08)
2017-05
和2019-02
(不同年份):该方法应返回List(2017-05,2017-06,.........2017-51,2017-52,2018-01,2018-02,.......2018-51,2018-52,2019-01,2019-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
}
}
我认为我的解决方案存在两个问题:
concise and functional
解决方案。1 to 9
时,我想生成2017-01
,2017-02
而不是2017-1
,2017-2
。我不想手动追加0.我正在寻找更好的方法。那么,这里最好的方法是什么?
答案 0 :(得分:2)
我可能会做以下事情:
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
}
您可以使用format
同样正确显示数字:
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)
我认为这个解决方案描述了一种使用高阶函数来解决这个问题的简洁明了的方法。它可以缩短,但我想它会失去清晰度。
答案 1 :(得分:2)
我认为最好的方法是依赖java.time api
代码看起来像这样(我不包括输入的解析):
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.temporal.IsoFields
import java.time.temporal.ChronoUnit
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAdjusters
val initialDate = LocalDate.ofYearDay(2017, 50).`with`(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 50).`with`(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
val finalDate = LocalDate.ofYearDay(2017, 50).`with`(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 8).`with`(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
for {
i <- 0 to ChronoUnit.WEEKS.between(initialDate, finalDate).toInt
} yield initialDate.plusWeeks(i).format(DateTimeFormatter.ofPattern("YYYY-ww"))
这里有demo
答案 2 :(得分:2)
您可以利用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)