2021-05-30 11:15:32 +00:00
|
|
|
package dev.inmo.krontab.internal
|
|
|
|
|
2023-05-25 14:53:10 +00:00
|
|
|
import korlibs.time.*
|
2021-05-30 11:15:32 +00:00
|
|
|
import dev.inmo.krontab.utils.copy
|
|
|
|
import kotlin.math.min
|
|
|
|
|
2021-05-30 12:53:44 +00:00
|
|
|
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<DateTime, Boolean>?
|
|
|
|
}
|
|
|
|
|
|
|
|
internal class CommonNearDateTimeCalculator<T>(
|
2021-05-30 11:15:32 +00:00
|
|
|
private val times: Array<T>,
|
|
|
|
private val partGetter: (DateTime) -> T,
|
|
|
|
private val partSetter: (DateTime, T) -> DateTime?
|
2021-05-30 12:53:44 +00:00
|
|
|
) : NearDateTimeCalculator where T : Comparable<T>, T : Number {
|
2021-05-30 11:15:32 +00:00
|
|
|
/**
|
|
|
|
* @return pair of near [DateTime] for this checker and [Boolean] flag that all previous calculations must be
|
|
|
|
* recalculated
|
|
|
|
*/
|
2021-05-30 12:53:44 +00:00
|
|
|
override fun calculateNearTime(
|
2021-05-30 11:15:32 +00:00
|
|
|
relativelyTo: DateTime
|
|
|
|
): Pair<DateTime, Boolean>? {
|
|
|
|
val currentData = partGetter(relativelyTo)
|
|
|
|
val greaterOrEquals = times.firstOrNull { it >= currentData }
|
2021-06-03 06:37:13 +00:00
|
|
|
val newDateTime = when (greaterOrEquals) {
|
|
|
|
null -> partSetter(relativelyTo, times.first()) ?: return null
|
|
|
|
currentData -> relativelyTo
|
|
|
|
else -> partSetter(relativelyTo, greaterOrEquals) ?: return null
|
2021-05-30 11:15:32 +00:00
|
|
|
}
|
|
|
|
return if (newDateTime == relativelyTo) {
|
|
|
|
relativelyTo to false
|
|
|
|
} else {
|
|
|
|
newDateTime to true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun NearDateTimeCalculatorMillis(
|
|
|
|
times: Array<Short>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
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<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
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<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
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<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
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<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
times,
|
2022-06-15 08:46:12 +00:00
|
|
|
{ (it.dayOfMonth - 1).toByte() }, // index1, so, decrease
|
2021-05-30 11:15:32 +00:00
|
|
|
{ dateTime, newOne ->
|
2022-06-15 06:40:03 +00:00
|
|
|
val dateTime = (if (newOne < dateTime.dayOfMonth) {
|
2021-05-30 11:15:32 +00:00
|
|
|
dateTime.plus(1.months)
|
|
|
|
} else {
|
|
|
|
dateTime
|
2022-06-15 06:40:03 +00:00
|
|
|
})
|
2023-09-18 08:15:20 +00:00
|
|
|
val newDateTime = dateTime.copy(
|
2022-06-15 07:27:21 +00:00
|
|
|
dayOfMonth = min(dateTime.month.days(dateTime.year), newOne.toInt() + 1), // index1
|
2021-05-30 11:15:32 +00:00
|
|
|
hour = 0,
|
|
|
|
minute = 0,
|
|
|
|
second = 0,
|
|
|
|
milliseconds = 0
|
|
|
|
)
|
2023-09-18 08:15:20 +00:00
|
|
|
// If day of month has not been changed, use old dateTime due to no changes required
|
|
|
|
if (newDateTime.dayOfMonth == dateTime.dayOfMonth) {
|
|
|
|
dateTime
|
|
|
|
} else {
|
|
|
|
newDateTime
|
|
|
|
}
|
2021-05-30 11:15:32 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
internal fun NearDateTimeCalculatorMonths(
|
|
|
|
times: Array<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
times,
|
2022-06-15 07:27:21 +00:00
|
|
|
{ it.month0.toByte() },
|
2021-05-30 11:15:32 +00:00
|
|
|
{ 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<Byte>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
times,
|
|
|
|
{ it.dayOfWeek.index0.toByte() },
|
|
|
|
{ dateTime, newOne ->
|
|
|
|
val currentDayOfWeek = dateTime.dayOfWeek.index0
|
2021-05-30 12:53:44 +00:00
|
|
|
if (newOne.toInt() == currentDayOfWeek) return@CommonNearDateTimeCalculator dateTime
|
2021-05-30 11:15:32 +00:00
|
|
|
(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<Int>
|
2021-05-30 12:53:44 +00:00
|
|
|
) = CommonNearDateTimeCalculator(
|
2021-05-30 11:15:32 +00:00
|
|
|
times,
|
|
|
|
{ it.yearInt },
|
|
|
|
{ dateTime, newOne ->
|
|
|
|
val currentYear = dateTime.yearInt
|
2021-05-30 12:53:44 +00:00
|
|
|
if (newOne == currentYear) return@CommonNearDateTimeCalculator dateTime
|
2021-05-30 11:15:32 +00:00
|
|
|
(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
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|