Котлин: Как перебрать все даты в интервале Joda? - PullRequest
0 голосов
/ 29 августа 2018

Я бы хотел перебрать все даты в заданном интервале Joda:

val interval = Interval(DateTime.now().minusDays(42), DateTime.now())

Как это сделать в Котлине?

Ответы [ 4 ]

0 голосов
/ 28 марта 2019

LocalDate является предпочтительным в настоящее время, поэтому мы можем просто итерировать день с номером:

for (day in minDate.toEpochDay()..maxDate.toEpochDay()) {
    // ...
}

или

(minDate.toEpochDay()..maxDate.toEpochDay()).forEach {
    // ...
}

Итерация с указанием дня в качестве даты:

generateSequence(minDate) { it.plusDays(1) }.takeWhile { it < maxDate }.forEach {
    // it ...
}

или

var day = minDate;
while (day < maxDate) {
    day = day.plusDays(1);
    // ...
}
0 голосов
/ 29 августа 2018

Сильно вдохновлено вашим текущим решением:

fun Interval.toDateTimes() = generateSequence(start) { it.plusDays(1) }
                                                 .takeWhile(::contains) 

Использование:

interval.toDateTimes()
        .forEach { println(it) }

Если вам нужен LocalDate, вы все равно можете сделать следующее:

interval.toDateTimes()
        .map(DateTime::toLocalDate)
        .forEach { println(it) }

или в качестве функции расширения для Interval снова:

fun Interval.toLocalDates() = toDateTimes().map(DateTime::toLocalDate)

Если вы хотите, чтобы конечная дата была включительной, вместо нее используйте takeWhile { it <= end }.

0 голосов
/ 29 августа 2018

Полагаю, если вам это нужно более одного раза, было бы лучше перегрузить оператор rangeTo, чтобы разрешить этот синтаксис

for (i in LocalDate.now() .. LocalDate.now().plusWeeks(1)) {
    System.out.print(i) // 2018-08-30 2018-08-31 2018-09-01 
}

Вот код расширения оператора:

operator fun LocalDate.rangeTo(other: LocalDate): LocalDateRange {
    return LocalDateRange(this, other)
}

И необходимые занятия:

class LocalDateRange(override val start: LocalDate, override val endInclusive: LocalDate)
    : ClosedRange<LocalDate>, Iterable<LocalDate> {
    override fun iterator(): Iterator<LocalDate> {
        return DateIterator(start, endInclusive)
    }
}

class DateIterator(start: LocalDate, private val endInclusive: LocalDate)
    : Iterator<LocalDate> {

    private var current = start

    override fun hasNext(): Boolean {
        return current <= endInclusive
    }

    override fun next(): LocalDate {
        current = current.plusDays(1)
        return current
    }
}
0 голосов
/ 29 августа 2018

Следующая функция расширения дает Sequence из LocalDate объектов из заданного Interval, которые можно использовать для итерации этих дат.

fun Interval.toLocalDates(): Sequence<LocalDate> = generateSequence(start) { d ->
    d.plusDays(1).takeIf { it < end }
}.map(DateTime::toLocalDate)

Использование:

val interval = Interval(DateTime.now().minusDays(42), DateTime.now())
interval.toLocalDates().forEach {
    println(it)
}

В этом решении последний день, DateTime.now() не включен в Sequence, поскольку также реализован Interval:

«Временной интервал представляет собой промежуток времени между двумя моментами. Интервалы включают момент начала и исключают конец».

Если по какой-либо причине вы хотите включить в него последний день, просто измените условие takeIf на it <= end.

...