Skip to content

Commit 1f3c737

Browse files
authored
Merge pull request #1740 from navikt/fjern-comparable-fra-datointervall
fjern comparable for datointervall
2 parents 8dd2cd3 + 989f010 commit 1f3c737

File tree

11 files changed

+264
-44
lines changed

11 files changed

+264
-44
lines changed

common/domain/src/main/kotlin/no/nav/su/se/bakover/common/domain/Stønadsperiode.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import java.time.Year
1111

1212
data class Stønadsperiode private constructor(
1313
val periode: Periode,
14-
) : Comparable<Stønadsperiode> {
14+
) {
1515

1616
infix fun inneholder(periode: Periode) = this.periode.inneholder(periode)
1717
infix fun inneholder(stønadsperiode: Stønadsperiode) = this.periode.inneholder(stønadsperiode.periode)
@@ -40,7 +40,6 @@ data class Stønadsperiode private constructor(
4040
data object FraOgMedDatoKanIkkeVæreFør2021 : UgyldigStønadsperiode
4141
}
4242

43-
override fun compareTo(other: Stønadsperiode) = periode.compareTo(other.periode)
4443
fun måneder() = periode.måneder()
4544
fun toYearRange(): YearRange = YearRange(Year.of(this.periode.fraOgMed.year), Year.of(this.periode.tilOgMed.year))
4645
}

common/domain/src/main/kotlin/no/nav/su/se/bakover/common/domain/tid/periode/DatoIntervall.kt

+48-16
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package no.nav.su.se.bakover.common.tid.periode
22

33
import arrow.core.Either
44
import arrow.core.NonEmptyList
5-
import arrow.core.getOrElse
65
import arrow.core.left
76
import arrow.core.right
87
import java.time.LocalDate
@@ -18,15 +17,15 @@ import java.util.Locale
1817
open class DatoIntervall(
1918
val fraOgMed: LocalDate,
2019
val tilOgMed: LocalDate,
21-
) : Comparable<DatoIntervall> {
20+
) {
2221

2322
init {
2423
require(fraOgMed <= tilOgMed) {
2524
"fraOgMed må være før eller samme dag som tilOgMed"
2625
}
2726
}
2827

29-
override fun compareTo(other: DatoIntervall) = compareValuesBy(this, other, { it.fraOgMed }, { it.tilOgMed })
28+
constructor(dato: LocalDate) : this(dato, dato)
3029

3130
infix fun inneholder(dato: LocalDate): Boolean = dato in fraOgMed..tilOgMed
3231

@@ -92,12 +91,24 @@ open class DatoIntervall(
9291
return this == other || sluttStart == plussEnDag || sluttStart == minusEnDag || startSlutt == plussEnDag || startSlutt == minusEnDag
9392
}
9493

94+
infix fun tilstøter(other: LocalDate): Boolean {
95+
val dayBeforeStart = fraOgMed.minusDays(1)
96+
val dayAfterEnd = tilOgMed.plusDays(1)
97+
return other.isEqual(dayBeforeStart) || other.isEqual(dayAfterEnd)
98+
}
99+
95100
infix fun slåSammen(
96101
other: DatoIntervall,
97102
): Either<DatoIntervallKanIkkeSlåsSammen, DatoIntervall> {
98103
return slåSammen(other) { fraOgMed, tilOgMed -> DatoIntervall(fraOgMed, tilOgMed) }
99104
}
100105

106+
infix fun slåSammen(
107+
other: LocalDate,
108+
): Either<DatoIntervallKanIkkeSlåsSammen, DatoIntervall> {
109+
return slåSammen(DatoIntervall(other, other)) { fraOgMed, tilOgMed -> DatoIntervall(fraOgMed, tilOgMed) }
110+
}
111+
101112
/**
102113
* Slår sammen to perioder dersom minst en måned overlapper eller periodene er tilstøtende.
103114
*/
@@ -115,6 +126,13 @@ open class DatoIntervall(
115126
}
116127
}
117128

129+
/**
130+
* @return Liste med alle dager i [DatoIntervall], sortert og unike.
131+
*/
132+
fun dager(): List<LocalDate> {
133+
return (0 until antallDager()).map { fraOgMed.plusDays(it) }
134+
}
135+
118136
/**
119137
* Periode i formatet "dd.MM.yyyy - dd.MM.yyyy".
120138
*/
@@ -123,10 +141,15 @@ open class DatoIntervall(
123141
return "${this.fraOgMed.format(formatter)} - ${this.tilOgMed.format(formatter)}"
124142
}
125143

126-
override fun equals(other: Any?) = other is DatoIntervall && fraOgMed == other.fraOgMed && tilOgMed == other.tilOgMed
144+
override fun equals(other: Any?) =
145+
other is DatoIntervall && fraOgMed == other.fraOgMed && tilOgMed == other.tilOgMed
127146

128147
override fun hashCode() = 31 * fraOgMed.hashCode() + tilOgMed.hashCode()
129148

149+
override fun toString(): String {
150+
return "DatoIntervall(fraOgMed=$fraOgMed, tilOgMed=$tilOgMed)"
151+
}
152+
130153
data object DatoIntervallKanIkkeSlåsSammen
131154
}
132155

@@ -141,19 +164,21 @@ fun List<DatoIntervall>.minsteAntallSammenhengendePerioder(): List<DatoIntervall
141164
fun <T : DatoIntervall> List<T>.minsteAntallSammenhengendePerioder(
142165
create: (fraOgMed: LocalDate, tilOgMed: LocalDate) -> T,
143166
): List<T> {
144-
return sorted().fold(mutableListOf()) { slåttSammen: MutableList<T>, datoIntervall: T ->
145-
if (slåttSammen.isEmpty()) {
146-
slåttSammen.add(datoIntervall)
147-
} else if (slåttSammen.last().slåSammen(datoIntervall).isRight()) {
148-
val last = slåttSammen.removeLast()
149-
slåttSammen.add(
150-
last.slåSammen(datoIntervall, create).getOrElse { throw IllegalStateException("Skulle gått bra") },
151-
)
152-
} else {
153-
slåttSammen.add(datoIntervall)
167+
return this.dager()
168+
.fold(emptyList()) { acc, dato ->
169+
if (acc.isEmpty()) {
170+
listOf(DatoIntervall(dato, dato))
171+
} else {
172+
acc.last().slåSammen(dato).fold(
173+
{ acc + listOf(DatoIntervall(dato, dato)) },
174+
{ acc.dropLast(1) + it },
175+
)
176+
}.let {
177+
it.map {
178+
create(it.fraOgMed, it.tilOgMed)
179+
}
180+
}
154181
}
155-
slåttSammen
156-
}
157182
}
158183

159184
infix fun List<DatoIntervall>.inneholder(other: List<DatoIntervall>): Boolean =
@@ -176,3 +201,10 @@ fun List<DatoIntervall>.minAndMaxOfOrNull(): DatoIntervall? {
176201
tilOgMed = this.maxOf { it.tilOgMed },
177202
)
178203
}
204+
205+
/**
206+
* @return Liste med alle dager i alle [DatoIntervall] i listen, sortert og unike.
207+
*/
208+
fun <T : DatoIntervall> List<T>.dager(): List<LocalDate> {
209+
return this.flatMap { it.dager() }.distinct().sorted()
210+
}

common/domain/src/main/kotlin/no/nav/su/se/bakover/common/domain/tid/periode/Måned.kt

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ data class Måned private constructor(
2424
require(this.før(that))
2525
}
2626
}
27+
// TODO - her vil vi ha en egen compareTo og comaprable på måned
28+
// override fun compareTo(other: Måned): Int = this.årOgMåned.compareTo(other.årOgMåned)
2729

2830
/**
2931
* Returns a range from this value up to but excluding the specified to value.

common/domain/src/main/kotlin/no/nav/su/se/bakover/common/domain/tid/periode/Periode.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import kotlin.collections.minus as setsMinus
2727
open class Periode protected constructor(
2828
fraOgMed: LocalDate,
2929
tilOgMed: LocalDate,
30-
) : DatoIntervall(fraOgMed, tilOgMed) {
30+
) : DatoIntervall(fraOgMed, tilOgMed), Comparable<Periode> {
3131

3232
constructor(måned: YearMonth) : this(måned.atDay(1), måned.atEndOfMonth()) {
3333
validateOrThrow(fraOgMed, tilOgMed)
@@ -37,6 +37,8 @@ open class Periode protected constructor(
3737
validateOrThrow(fraOgMed, tilOgMed)
3838
}
3939

40+
override fun compareTo(other: Periode) = compareValuesBy(this, other, Periode::fraOgMed, Periode::tilOgMed)
41+
4042
/**
4143
* @throws IllegalStateException dersom fraOgMed er LocalDate.MIN eller tilOgMed er LocalDate.MAX
4244
* @throws ArithmeticException dersom antall måneder er større enn en Int.
@@ -198,7 +200,16 @@ fun List<Periode>.minAndMaxOfOrNull(): Periode? {
198200
* definert av [Periode.slåSammen].
199201
*/
200202
fun List<Periode>.minsteAntallSammenhengendePerioder(): List<Periode> {
201-
return minsteAntallSammenhengendePerioder { fraOgMed, tilOgMed -> Periode.create(fraOgMed, tilOgMed) }
203+
return this.måneder().fold(emptyList()) { acc, måned ->
204+
if (acc.isEmpty()) {
205+
listOf(måned.tilPeriode())
206+
} else {
207+
acc.last().slåSammen(måned.tilPeriode()).fold(
208+
{ acc + måned.tilPeriode() },
209+
{ acc.dropLast(1) + it },
210+
)
211+
}
212+
}
202213
}
203214

204215
fun Nel<Periode>.minsteAntallSammenhengendePerioder(): Nel<Periode> {

common/domain/src/test/kotlin/no/nav/su/se/bakover/common/domain/periode/DatoIntervallTest.kt

-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package no.nav.su.se.bakover.common.domain.periode
22

3-
import io.kotest.matchers.ints.shouldBeGreaterThan
4-
import io.kotest.matchers.ints.shouldBeLessThan
53
import io.kotest.matchers.shouldBe
64
import no.nav.su.se.bakover.common.extensions.april
75
import no.nav.su.se.bakover.common.extensions.august
@@ -27,13 +25,6 @@ import org.junit.jupiter.api.Test
2725

2826
internal class DatoIntervallTest {
2927

30-
@Test
31-
fun compareTo() {
32-
DatoIntervall(1.januar(2021), 31.januar(2021)).compareTo(DatoIntervall(1.januar(2021), 31.januar(2021))) shouldBe 0
33-
DatoIntervall(1.januar(2021), 31.januar(2021)).compareTo(DatoIntervall(1.januar(2021), 31.desember(2021))).shouldBeLessThan(0)
34-
DatoIntervall(1.januar(2021), 31.januar(2021)).compareTo(DatoIntervall(1.januar(2021), 1.januar(2021))).shouldBeGreaterThan(0)
35-
}
36-
3728
@Test
3829
fun inneholder() {
3930
DatoIntervall(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package no.nav.su.se.bakover.common.domain.periode
2+
3+
import io.kotest.matchers.shouldBe
4+
import no.nav.su.se.bakover.common.extensions.april
5+
import no.nav.su.se.bakover.common.extensions.august
6+
import no.nav.su.se.bakover.common.extensions.desember
7+
import no.nav.su.se.bakover.common.extensions.februar
8+
import no.nav.su.se.bakover.common.extensions.januar
9+
import no.nav.su.se.bakover.common.extensions.juli
10+
import no.nav.su.se.bakover.common.extensions.juni
11+
import no.nav.su.se.bakover.common.extensions.mai
12+
import no.nav.su.se.bakover.common.extensions.mars
13+
import no.nav.su.se.bakover.common.extensions.november
14+
import no.nav.su.se.bakover.common.extensions.oktober
15+
import no.nav.su.se.bakover.common.extensions.september
16+
import no.nav.su.se.bakover.common.tid.periode.DatoIntervall
17+
import no.nav.su.se.bakover.common.tid.periode.dager
18+
import no.nav.su.se.bakover.common.tid.periode.januar
19+
import no.nav.su.se.bakover.common.tid.periode.år
20+
import org.junit.jupiter.api.Test
21+
22+
internal class DatoIntervall_dagerTest {
23+
24+
@Test
25+
fun `ingen dager`() {
26+
listOf<DatoIntervall>().dager() shouldBe emptyList()
27+
}
28+
29+
@Test
30+
fun `1 dag`() {
31+
DatoIntervall(1.januar(2022), 1.januar(2022)).dager() shouldBe listOf(1.januar(2022))
32+
33+
listOf(
34+
DatoIntervall(1.januar(2022), 1.januar(2022)),
35+
DatoIntervall(1.januar(2022), 1.januar(2022)),
36+
).dager() shouldBe listOf(1.januar(2022))
37+
}
38+
39+
@Test
40+
fun `2 dager`() {
41+
DatoIntervall(1.januar(2022), 2.januar(2022)).dager() shouldBe
42+
listOf(1.januar(2022), 2.januar(2022))
43+
44+
listOf(
45+
DatoIntervall(1.januar(2022), 1.januar(2022)),
46+
DatoIntervall(1.januar(2022), 2.januar(2022)),
47+
DatoIntervall(2.januar(2022), 2.januar(2022)),
48+
).dager() shouldBe listOf(1.januar(2022), 2.januar(2022))
49+
50+
listOf(
51+
DatoIntervall(1.januar(2022), 1.januar(2022)),
52+
DatoIntervall(2.januar(2022), 2.januar(2022)),
53+
).dager() shouldBe listOf(1.januar(2022), 2.januar(2022))
54+
}
55+
56+
@Test
57+
fun `1 måned`() {
58+
januar(2022).dager() shouldBe
59+
(1..31).map { it.januar(2022) }
60+
}
61+
62+
@Test
63+
fun `1 år`() {
64+
val expected = (1..31).map { it.januar(2022) } +
65+
(1..28).map { it.februar(2022) } +
66+
(1..31).map { it.mars(2022) } +
67+
(1..30).map { it.april(2022) } +
68+
(1..31).map { it.mai(2022) } +
69+
(1..30).map { it.juni(2022) } +
70+
(1..31).map { it.juli(2022) } +
71+
(1..31).map { it.august(2022) } +
72+
(1..30).map { it.september(2022) } +
73+
(1..31).map { it.oktober(2022) } +
74+
(1..30).map { it.november(2022) } +
75+
(1..31).map { it.desember(2022) }
76+
år(2022).dager() shouldBe expected
77+
listOf(
78+
år(2022),
79+
januar(2022),
80+
DatoIntervall(3.juli(2022), 3.juli(2022)),
81+
DatoIntervall(7.februar(2022), 18.august(2022)),
82+
).dager() shouldBe expected
83+
}
84+
}

0 commit comments

Comments
 (0)