All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.internal.NearDateTimeCalculator.kt Maven / Gradle / Ivy

The newest version!
package dev.inmo.krontab.internal

import korlibs.time.*
import dev.inmo.krontab.utils.copy
import kotlin.math.min

fun interface NearDateTimeCalculator {
    /**
     * @return pair of near [DateTime] for this checker and [Boolean] flag that all previous calculations must be
     * recalculated
     */
    fun calculateNearTime(
        relativelyTo: DateTime
    ): Pair?
}

internal class CommonNearDateTimeCalculator(
    private val times: Array,
    private val partGetter: (DateTime) -> T,
    private val partSetter: (DateTime, T) -> DateTime?
) : NearDateTimeCalculator where T : Comparable, T : Number {
    /**
     * @return pair of near [DateTime] for this checker and [Boolean] flag that all previous calculations must be
     * recalculated
     */
    override fun calculateNearTime(
        relativelyTo: DateTime
    ): Pair? {
        val currentData = partGetter(relativelyTo)
        val greaterOrEquals = times.firstOrNull { it >= currentData }
        val newDateTime = when (greaterOrEquals) {
            null -> partSetter(relativelyTo, times.first()) ?: return null
            currentData -> relativelyTo
            else -> partSetter(relativelyTo, greaterOrEquals) ?: return null
        }
        return if (newDateTime == relativelyTo) {
            relativelyTo to false
        } else {
            newDateTime to true
        }
    }
}

internal fun NearDateTimeCalculatorMillis(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.milliseconds.toShort() },
    { dateTime, newOne ->
        (if (newOne < dateTime.milliseconds) {
            dateTime.plus(1.seconds)
        } else {
            dateTime
        }).copy(milliseconds = newOne.toInt())
    }
)

internal fun NearDateTimeCalculatorSeconds(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.seconds.toByte() },
    { dateTime, newOne ->
        (if (newOne < dateTime.seconds) {
            dateTime.plus(1.minutes)
        } else {
            dateTime
        }).copy(second = newOne.toInt(), milliseconds = 0)
    }
)

internal fun NearDateTimeCalculatorMinutes(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.minutes.toByte() },
    { dateTime, newOne ->
        (if (newOne < dateTime.minutes) {
            dateTime.plus(1.hours)
        } else {
            dateTime
        }).copy(minute = newOne.toInt(), second = 0, milliseconds = 0)
    }
)

internal fun NearDateTimeCalculatorHours(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.hours.toByte() },
    { dateTime, newOne ->
        (if (newOne < dateTime.hours) {
            dateTime.plus(1.days)
        } else {
            dateTime
        }).copy(hour = newOne.toInt(), minute = 0, second = 0, milliseconds = 0)
    }
)

internal fun NearDateTimeCalculatorDays(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { (it.dayOfMonth - 1).toByte() }, // index1, so, decrease
    { dateTime, newOne ->
        val dateTime = (if (newOne < dateTime.dayOfMonth) {
            dateTime.plus(1.months)
        } else {
            dateTime
        })
        val newDateTime = dateTime.copy(
            dayOfMonth = min(dateTime.month.days(dateTime.year), newOne.toInt() + 1), // index1
            hour = 0,
            minute = 0,
            second = 0,
            milliseconds = 0
        )
        // If day of month has not been changed, use old dateTime due to no changes required
        if (newDateTime.dayOfMonth == dateTime.dayOfMonth) {
            dateTime
        } else {
            newDateTime
        }
    }
)

internal fun NearDateTimeCalculatorMonths(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.month0.toByte() },
    { dateTime, newOne ->
        (if (newOne < dateTime.month0) {
            dateTime.plus(1.years)
        } else {
            dateTime
        }).copy(
            month = newOne.toInt() + 1, // index1
            dayOfMonth = 1, // index1
            hour = 0,
            minute = 0,
            second = 0,
            milliseconds = 0
        )
    }
)

internal fun NearDateTimeCalculatorWeekDays(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.dayOfWeek.index0.toByte() },
    { dateTime, newOne ->
        val currentDayOfWeek = dateTime.dayOfWeek.index0
        if (newOne.toInt() == currentDayOfWeek) return@CommonNearDateTimeCalculator dateTime
        (if (newOne < currentDayOfWeek) {
            dateTime.plus(7.days - (currentDayOfWeek - newOne).days)
        } else {
            dateTime.plus(newOne.toInt().days - currentDayOfWeek.days)
        }).copy(
            hour = 0,
            minute = 0,
            second = 0,
            milliseconds = 0
        )
    }
)

internal fun NearDateTimeCalculatorYears(
    times: Array
) = CommonNearDateTimeCalculator(
    times,
    { it.yearInt },
    { dateTime, newOne ->
        val currentYear = dateTime.yearInt
        if (newOne == currentYear) return@CommonNearDateTimeCalculator dateTime
        (if (newOne < currentYear) {
            null
        } else {
            dateTime.plus(newOne.years - currentYear.years)
        }) ?.copy(
            month = 1, // index1
            dayOfMonth = 1, // index1
            hour = 0,
            minute = 0,
            second = 0,
            milliseconds = 0
        )
    }
)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy