Skip to content

Commit

Permalink
Hjelpefunksjoner til tidslinjer (#862)
Browse files Browse the repository at this point in the history
* Flytt join-funksjoner til egen fil

* Flytt bifunksjoner til egen fil og legg til bifunksjon for tre tidslinjer

* Flytt kombinering-funksjoner til egen fil

* Legg til div hjelpefunksjoner

* Endre typen på TidslinjePeriode::lengde til Long i stedet for Int
  • Loading branch information
MagnusTonnessen authored Feb 25, 2025
1 parent 776c72f commit e2e2ab0
Show file tree
Hide file tree
Showing 12 changed files with 534 additions and 407 deletions.
10 changes: 10 additions & 0 deletions tidslinje/src/main/kotlin/no/nav/familie/tidslinje/Periode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ data class Periode<T>(
fun tilTidslinjePeriodeMedDato() = TidslinjePeriodeMedDato(verdi, fom, tom)
}

fun <T> Periode<T>.tilTidslinje(): Tidslinje<T> = listOf(this).tilTidslinje()

fun <T> List<Periode<T>>.tilTidslinje(): Tidslinje<T> =
this
.map { it.tilTidslinjePeriodeMedDato() }
Expand All @@ -24,6 +26,14 @@ fun <T> List<Periode<T>>.filtrerIkkeNull(): List<Periode<T & Any>> =

fun <T> List<Periode<T>>.verdier(): List<T> = this.map { it.verdi }

fun <V> Periode<V>.omfatter(tidspunkt: LocalDate) =
when {
fom == null && tom == null -> true
fom == null -> tom!!.isSameOrAfter(tidspunkt)
tom == null -> fom.isSameOrBefore(tidspunkt)
else -> fom.isSameOrBefore(tidspunkt) && tom.isSameOrAfter(tidspunkt)
}

data class IkkeNullbarPeriode<T>(
val verdi: T,
val fom: LocalDate,
Expand Down
66 changes: 14 additions & 52 deletions tidslinje/src/main/kotlin/no/nav/familie/tidslinje/Tidslinje.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package no.nav.familie.tidslinje

import no.nav.familie.tidslinje.utvidelser.klipp
import no.nav.familie.tidslinje.utvidelser.kombinerMed
import no.nav.familie.tidslinje.utvidelser.map
import no.nav.familie.tidslinje.utvidelser.mapper
import no.nav.familie.tidslinje.utvidelser.tilPerioder
Expand Down Expand Up @@ -48,16 +47,16 @@ open class Tidslinje<T>(
}
}

fun erTom() = innhold.sumOf { it.lengde } == 0
fun erTom() = innhold.sumOf { it.lengde } == 0L

/**
* Kalkulerer slutttidspunkt som en LocalDate.
* Funksjonen returnerer den siste dagen som er med i tidslinja
* Om tidslinja er uendelig, kastes det et unntak
*/
fun kalkulerSluttTidspunkt(): LocalDate {
val antallTidsEnheter: Int = this.innhold.sumOf { it.lengde }
val sluttTidspunkt = this.startsTidspunkt.plus(antallTidsEnheter.toLong() - 1, mapper[this.tidsEnhet])
val antallTidsEnheter = this.innhold.sumOf { it.lengde }
val sluttTidspunkt = this.startsTidspunkt.plus(antallTidsEnheter - 1, mapper[this.tidsEnhet])

return when (this.tidsEnhet) {
TidsEnhetR -> sluttTidspunkt.with(TemporalAdjusters.lastDayOfYear())
Expand All @@ -67,6 +66,16 @@ open class Tidslinje<T>(
}
}

fun kopier(): Tidslinje<T> =
Tidslinje(
startsTidspunkt = startsTidspunkt,
perioder = innhold,
tidsEnhet = tidsEnhet,
).also {
it.tittel = tittel
it.foreldre.addAll(foreldre)
}

private fun kalkulerSluttTidspunkt(sluttDato: LocalDate): LocalDate =
when (this.tidsEnhet) {
TidsEnhetR -> sluttDato.with(TemporalAdjusters.lastDayOfYear())
Expand Down Expand Up @@ -143,59 +152,12 @@ fun <T> tomTidslinje(
tidsEnhet: TidsEnhet = TidsEnhet.DAG,
): Tidslinje<T> = Tidslinje(startsTidspunkt = startsTidspunkt ?: PRAKTISK_TIDLIGSTE_DAG, emptyList(), tidsEnhet)

fun <K, V, H, R> Map<K, Tidslinje<V>>.leftJoin(
yreTidslinjer: Map<K, Tidslinje<H>>,
kombinator: (V?, H?) -> R?,
): Map<K, Tidslinje<R>> {
val venstreTidslinjer = this
val venstreNøkler = venstreTidslinjer.keys

return venstreNøkler.associateWith { nøkkel ->
val venstreTidslinje = venstreTidslinjer.getOrDefault(nøkkel, tomTidslinje())
val høyreTidslinje = høyreTidslinjer.getOrDefault(nøkkel, tomTidslinje())

venstreTidslinje.kombinerMed(høyreTidslinje, kombinator)
}
}

fun <K, V, H, R> Map<K, Tidslinje<V>>.outerJoin(
yreTidslinjer: Map<K, Tidslinje<H>>,
kombinator: (V?, H?) -> R?,
): Map<K, Tidslinje<R>> {
val venstreTidslinjer = this
val alleNøkler = venstreTidslinjer.keys + høyreTidslinjer.keys

return alleNøkler.associateWith { nøkkel ->
val venstreTidslinje = venstreTidslinjer.getOrDefault(nøkkel, tomTidslinje())
val høyreTidslinje = høyreTidslinjer.getOrDefault(nøkkel, tomTidslinje())

venstreTidslinje.kombinerMed(høyreTidslinje, kombinator)
}
}

fun <K, A, B, C, R> Map<K, Tidslinje<A>>.outerJoin(
tidslinjer2: Map<K, Tidslinje<B>>,
tidslinjer3: Map<K, Tidslinje<C>>,
kombinator: (A?, B?, C?) -> R?,
): Map<K, Tidslinje<R>> {
val tidslinjer1 = this
val alleNøkler = tidslinjer1.keys + tidslinjer2.keys + tidslinjer3.keys

return alleNøkler.associateWith { nøkkel ->
val tidslinje1 = tidslinjer1.getOrDefault(nøkkel, tomTidslinje())
val tidslinje2 = tidslinjer2.getOrDefault(nøkkel, tomTidslinje())
val tidslinje3 = tidslinjer3.getOrDefault(nøkkel, tomTidslinje())

tidslinje1.kombinerMed(tidslinje2, tidslinje3, kombinator)
}
}

fun <T> Tidslinje<T>.beskjærEtter(tidslinje: Tidslinje<*>): Tidslinje<T> =
this.klipp(tidslinje.startsTidspunkt, tidslinje.kalkulerSluttTidspunkt())

fun <T> Tidslinje<T>.inneholder(verdi: T): Boolean = this.tilPerioder().any { it.verdi == verdi }

fun <T, R> Tidslinje<T>.mapVerdi(mapper: (T?) -> R): Tidslinje<R> =
fun <T, R> Tidslinje<T>.mapVerdi(mapper: (T?) -> R?): Tidslinje<R> =
this.map { periodeVerdi ->
when (periodeVerdi) {
is Verdi,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package no.nav.familie.tidslinje

const val INF = 1_000_000_000
const val INF = 1_000_000_000L

sealed class PeriodeVerdi<T>(
protected val _verdi: T?,
Expand Down Expand Up @@ -45,7 +45,7 @@ class Null<T> : PeriodeVerdi<T>(null) {
*/
data class TidslinjePeriode<T>(
val periodeVerdi: PeriodeVerdi<T>,
var lengde: Int,
var lengde: Long,
var erUendelig: Boolean = false,
) {
init {
Expand All @@ -60,7 +60,7 @@ data class TidslinjePeriode<T>(
}
}

constructor(periodeVerdi: T?, lengde: Int, erUendelig: Boolean = false) : this(
constructor(periodeVerdi: T?, lengde: Long, erUendelig: Boolean = false) : this(
if (periodeVerdi == null) {
Null()
} else {
Expand Down
7 changes: 5 additions & 2 deletions tidslinje/src/main/kotlin/no/nav/familie/tidslinje/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import java.time.LocalDate
val PRAKTISK_TIDLIGSTE_DAG = LocalDate.of(0, 1, 1)
val PRAKTISK_SENESTE_DAG = LocalDate.MAX.minusYears(1)

fun LocalDate.diffIDager(annen: LocalDate): Int =
fun LocalDate.diffIDager(annen: LocalDate): Long =
Duration
// legger på én dag på sluttdatoen siden den er exlusive
.between(this.atStartOfDay(), annen.plusDays(1).atStartOfDay())
.toDaysPart()
.toInt()

fun LocalDate.isSameOrBefore(toCompare: LocalDate): Boolean = this.isBefore(toCompare) || this == toCompare

fun LocalDate.isSameOrAfter(toCompare: LocalDate): Boolean = this.isAfter(toCompare) || this == toCompare
Loading

0 comments on commit e2e2ab0

Please sign in to comment.