add KronTime entity and time calculation environment

This commit is contained in:
InsanusMokrassar 2019-05-23 14:42:55 +08:00
parent 9e33170d45
commit 204bbe1f35
3 changed files with 214 additions and 0 deletions

View File

@ -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?
)

View File

@ -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
)
}
}

View File

@ -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