mirror of
https://github.com/InsanusMokrassar/krontab.git
synced 2024-11-26 12:08:50 +00:00
add KronTime entity and time calculation environment
This commit is contained in:
parent
9e33170d45
commit
204bbe1f35
@ -0,0 +1,110 @@
|
|||||||
|
package com.github.insanusmokrassar.krontab.parts
|
||||||
|
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
private const val millisCount = 1000
|
||||||
|
private const val secondsCount = 60
|
||||||
|
private const val minutesCount = 60
|
||||||
|
private const val hoursCount = 24
|
||||||
|
private const val weekDaysCount = 7
|
||||||
|
|
||||||
|
private const val secondsK = 1000
|
||||||
|
private const val minutesK = 60 * secondsK
|
||||||
|
private const val hoursK = 60 * minutesK
|
||||||
|
private const val daysK = 24 * hoursK
|
||||||
|
private const val weekDaysK = 7 * daysK
|
||||||
|
|
||||||
|
private fun <T> List<T>.notMaxOrNull(max: Int): List<T>? = if (size >= max) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KronTimes(
|
||||||
|
timePattern: TimePattern
|
||||||
|
): List<KronTime> {
|
||||||
|
val reversedParts = timePattern.split(" ").toMutableList().also {
|
||||||
|
it.reverse()
|
||||||
|
}
|
||||||
|
val weekDaysParts = getTimes(reversedParts.removeAt(0), 0, weekDaysCount).notMaxOrNull(weekDaysCount) ?.map {
|
||||||
|
it.toByte()
|
||||||
|
}
|
||||||
|
val hoursParts = getTimes(reversedParts.removeAt(0), 0, hoursCount).let {
|
||||||
|
(weekDaysParts ?.let { _ ->
|
||||||
|
it
|
||||||
|
} ?: it.notMaxOrNull(hoursCount)) ?.map {
|
||||||
|
it.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val minutesParts = getTimes(reversedParts.removeAt(0), 0, minutesCount).let {
|
||||||
|
(hoursParts ?.let { _ ->
|
||||||
|
it
|
||||||
|
} ?: it.notMaxOrNull(minutesCount)) ?.map {
|
||||||
|
it.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val secondsParts = getTimes(reversedParts.removeAt(0), 0, secondsCount).let {
|
||||||
|
(minutesParts ?.let { _ ->
|
||||||
|
it
|
||||||
|
} ?: it.notMaxOrNull(secondsCount)) ?.map {
|
||||||
|
it.toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val millisParts = if (reversedParts.isNotEmpty()) {
|
||||||
|
getTimes(reversedParts.removeAt(0), 0, millisCount).let {
|
||||||
|
secondsParts ?.let { _ ->
|
||||||
|
it
|
||||||
|
} ?: it.notMaxOrNull(millisCount)
|
||||||
|
} ?.map {
|
||||||
|
it.toShort()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
return millisParts ?.flatMap { millis ->
|
||||||
|
secondsParts ?.flatMap { seconds ->
|
||||||
|
minutesParts ?.flatMap { minutes ->
|
||||||
|
hoursParts ?.flatMap { hours ->
|
||||||
|
weekDaysParts ?.map { weekDay ->
|
||||||
|
KronTime(millis, seconds, minutes, hours, weekDay)
|
||||||
|
} ?: listOf(KronTime(millis, seconds, minutes, hours, null))
|
||||||
|
} ?: listOf(KronTime(millis, seconds, minutes, null, null))
|
||||||
|
} ?: listOf(KronTime(millis, seconds, null, null, null))
|
||||||
|
} ?: listOf(KronTime(millis, null, null, null, null))
|
||||||
|
} ?: listOf(KronTime(null, null, null, null, null))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KronTime(
|
||||||
|
milliseconds: Milliseconds
|
||||||
|
): KronTime {
|
||||||
|
val millis = (milliseconds % millisCount).toShort()
|
||||||
|
var currentDivided: Double = floor(milliseconds.toDouble() / millisCount)
|
||||||
|
|
||||||
|
val seconds: Byte = (currentDivided % secondsCount).toByte()
|
||||||
|
currentDivided = floor(currentDivided / secondsCount)
|
||||||
|
|
||||||
|
val minutes: Byte = (currentDivided % minutesCount).toByte()
|
||||||
|
currentDivided = floor(currentDivided / minutesCount)
|
||||||
|
|
||||||
|
val hours: Byte = (currentDivided % hoursCount).toByte()
|
||||||
|
currentDivided = floor(currentDivided / hoursCount)
|
||||||
|
|
||||||
|
val days: Byte = (currentDivided % weekDaysCount).toByte()
|
||||||
|
|
||||||
|
return KronTime(
|
||||||
|
millis,
|
||||||
|
seconds,
|
||||||
|
minutes,
|
||||||
|
hours,
|
||||||
|
days
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal data class KronTime(
|
||||||
|
val milliseconds: Milliseconds?,
|
||||||
|
val seconds: Seconds?,
|
||||||
|
val minutes: Minutes?,
|
||||||
|
val hours: Hours?,
|
||||||
|
val weekDays: WeekDays?
|
||||||
|
)
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.github.insanusmokrassar.krontab.parts
|
||||||
|
|
||||||
|
internal inline fun buildPeriodRegex(periodNumbers: Int): Regex {
|
||||||
|
val periodRegex = "\\d{1,$periodNumbers}"
|
||||||
|
return Regex("(\\*(/$periodRegex)?)|($periodRegex(-$periodRegex)?)")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractLongTermPeriod(period: String, minPeriodValue: Int, maxPeriodValue: Int): List<Int>? {
|
||||||
|
if (period.contains("-")) {
|
||||||
|
val (first, second) = period.split("-")
|
||||||
|
val firstNumber = first.toInt().let {
|
||||||
|
if (it < minPeriodValue) {
|
||||||
|
minPeriodValue
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val secondNumber = second.toInt().let {
|
||||||
|
if (it > maxPeriodValue) {
|
||||||
|
maxPeriodValue
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (firstNumber .. secondNumber).toList()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractPeriods(period: String, minPeriodValue: Int, maxPeriodValue: Int): List<Int>? {
|
||||||
|
if (period.startsWith("*")) {
|
||||||
|
val splitted = period.split("/")
|
||||||
|
when {
|
||||||
|
splitted.size > 1 -> {
|
||||||
|
val repeatPeriod = splitted[1].toInt()
|
||||||
|
return (minPeriodValue .. maxPeriodValue step repeatPeriod).toList()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
(minPeriodValue .. maxPeriodValue).toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private val oneTimeRegex = Regex("^\\d*$")
|
||||||
|
private fun extractOneTime(period: String, minPeriodValue: Int, maxPeriodValue: Int): List<Int>? {
|
||||||
|
oneTimeRegex.find(period) ?.let {
|
||||||
|
val found = it.groupValues.firstOrNull() ?: return null
|
||||||
|
val foundAsInt = found.toInt()
|
||||||
|
val resultTime = when {
|
||||||
|
minPeriodValue > foundAsInt -> minPeriodValue
|
||||||
|
maxPeriodValue < foundAsInt -> maxPeriodValue
|
||||||
|
else -> foundAsInt
|
||||||
|
}
|
||||||
|
return listOf(resultTime)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun adaptPeriod(period: String, minPeriodValue: Int, maxPeriodValue: Int): List<Int> {
|
||||||
|
return extractLongTermPeriod(
|
||||||
|
period,
|
||||||
|
minPeriodValue,
|
||||||
|
maxPeriodValue
|
||||||
|
) ?: extractPeriods(
|
||||||
|
period,
|
||||||
|
minPeriodValue,
|
||||||
|
maxPeriodValue
|
||||||
|
) ?: extractOneTime(
|
||||||
|
period,
|
||||||
|
minPeriodValue,
|
||||||
|
maxPeriodValue
|
||||||
|
) ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getTimes(
|
||||||
|
period: String,
|
||||||
|
minPeriodValue: Int,
|
||||||
|
maxPeriodValue: Int,
|
||||||
|
unconfinedVariants: Map<String, Int> = emptyMap()
|
||||||
|
): List<Int> {
|
||||||
|
return period.split(",").flatMap {
|
||||||
|
unconfinedVariants[it] ?.let {
|
||||||
|
listOf(it)
|
||||||
|
} ?: adaptPeriod(
|
||||||
|
it,
|
||||||
|
minPeriodValue,
|
||||||
|
maxPeriodValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.github.insanusmokrassar.krontab.parts
|
||||||
|
|
||||||
|
internal typealias Milliseconds = Short
|
||||||
|
internal typealias Seconds = Byte
|
||||||
|
internal typealias Minutes = Byte
|
||||||
|
internal typealias Hours = Byte
|
||||||
|
internal typealias WeekDays = Byte
|
||||||
|
internal typealias Weeks = Byte
|
||||||
|
|
||||||
|
typealias TimePattern = String
|
||||||
|
typealias TimeSubPattern = String
|
Loading…
Reference in New Issue
Block a user