Groovy 按星期几查找范围内日期的方法

Groovy way to find dates in range by the day of the week

完成以下 Joda Time 示例的 Groovy 方法是什么:

LocalDate startDate = new LocalDate(2016, 11, 8);
LocalDate endDate = new LocalDate(2017, 5, 1);

LocalDate thisMonday = startDate.withDayOfWeek(DateTimeConstants.MONDAY);

if (startDate.isAfter(thisMonday)) {
    startDate = thisMonday.plusWeeks(1); // start on next monday
} else {
    startDate = thisMonday; // start on this monday
}

while (startDate.isBefore(endDate)) {
    System.out.println(startDate);
    startDate = startDate.plusWeeks(1);
}

以及一周中超过 1 天的情况:例如星期一和星期二

给定您的开始和结束日期参数,以下 Groovy 代码(使用 Groovy Date.parse()Date.format() 混合函数,Groovy Date + int 另外,Groovy Stringint 强制转换,还有一点代数)似乎可以解决问题:

Date startDate = Date.parse("yyyy-MM-dd","2016-11-08")
Date endDate = Date.parse("yyyy-MM-dd","2017-05-01")

Date mondayStart = startDate + 6 - ((5 + (startDate.format("u") as int)) % 7)

while (mondayStart < endDate) {
    println mondayStart
    mondayStart += 7
}

话虽如此,底部的 while 循环有点... "open-ended"。您可以使用 Groovy 的 Range 文字语法和 List.step() 混合函数获得更具分析性的等价物。以下内容仅替换 上面的 while 循环:

(mondayStart..<endDate).step(7) { stepDate ->
    println stepDate
}

第 2 部分:超过星期一

为了与一周中的其他日子一起工作,我们需要用基于星期几的合适的子表达式替换 mondayStart 赋值中的常量 5。幸运的是,下面的表达式工作得很好:

7 - Calendar."${weekDay.toUpperCase()}"

把整个东西放在一起,稍微按摩一下,看起来像这样:

def weekDaysInDateRange(Date startDate, Date endDate, String weekDay = "monday") {
    startDate = startDate.clearTime()
    endDate = endDate.clearTime()
    def offset = 7 - Calendar."${weekDay.toUpperCase()}"
    def startDOW = startDate.format("u") as int
    def weekDayStartDate = startDate + 6 - (offset + startDOW) % 7

    (weekDayStartDate..<endDate).step(7) { stepDate ->
        println (stepDate.format("yyyy-MM-dd"))
    }
}

定义该函数后,测试代码如下:

def now = new Date()
def nextMonthIsh = new Date() + 30
println "$now --> $nextMonthIsh"
println "============================================================="

["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
.each { weekDay ->
    println """
$weekDay
=========="""
    weekDaysInDateRange(now, nextMonthIsh, weekDay)
}

给出以下结果:

Mon Sep 19 09:29:24 CDT 2016 --> Wed Oct 19 09:29:24 CDT 2016
=============================================================

sunday
==========
2016-09-25
2016-10-02
2016-10-09
2016-10-16

monday
==========
2016-09-19
2016-09-26
2016-10-03
2016-10-10
2016-10-17

tuesday
==========
2016-09-20
2016-09-27
2016-10-04
2016-10-11
2016-10-18

wednesday
==========
2016-09-21
2016-09-28
2016-10-05
2016-10-12

thursday
==========
2016-09-22
2016-09-29
2016-10-06
2016-10-13

friday
==========
2016-09-23
2016-09-30
2016-10-07
2016-10-14

saturday
==========
2016-09-24
2016-10-01
2016-10-08
2016-10-15