diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTime.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTime.kt index 8a152a7..2311ae1 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTime.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTime.kt @@ -4,6 +4,8 @@ import com.github.insanusmokrassar.krontab.utils.* import com.github.insanusmokrassar.krontab.utils.clamp import com.github.insanusmokrassar.krontab.utils.dayOfMonthRange import com.github.insanusmokrassar.krontab.utils.monthRange +import com.soywiz.klock.DateTime +import com.soywiz.klock.DateTimeSpan /** * [month] 0-11 @@ -45,3 +47,34 @@ internal data class CronDateTime( ) } } + +internal fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime { + var current = relativelyTo + + seconds?.let { + val left = it - current.seconds + current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left) + } + + minutes?.let { + val left = it - current.minutes + current += DateTimeSpan(hours = if (left < 0) 1 else 0, minutes = left) + } + + hours?.let { + val left = it - current.hours + current += DateTimeSpan(days = if (left < 0) 1 else 0, hours = left) + } + + klockDayOfMonth ?.let { + val left = it - current.dayOfMonth + current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left) + } + + month ?.let { + val left = it - current.month0 + current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left) + } + + return current +} diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTimeScheduler.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTimeScheduler.kt index 0c13ca2..ff82b57 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTimeScheduler.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronDateTimeScheduler.kt @@ -8,47 +8,16 @@ private val anyCronDateTime by lazy { CronDateTime() } -internal data class CronDateTimeScheduler( +data class CronDateTimeScheduler internal constructor( internal val cronDateTimes: List ) -internal fun CronDateTimeScheduler.next(relatively: DateTime = DateTime.now()): DateTime { +fun CronDateTimeScheduler.next(relatively: DateTime = DateTime.now()): DateTime { return cronDateTimes.map { it.toNearDateTime(relatively) }.min() ?: anyCronDateTime.toNearDateTime(relatively) } -internal suspend fun CronDateTimeScheduler.doInLoop(block: suspend () -> Boolean) { +suspend fun CronDateTimeScheduler.doInLoop(block: suspend () -> Boolean) { do { delay(next().unixMillisLong - DateTime.now().unixMillisLong) } while (block()) } - -internal fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime { - var current = relativelyTo - - seconds?.let { - val left = it - current.seconds - current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left) - } - - minutes?.let { - val left = it - current.minutes - current += DateTimeSpan(hours = if (left < 0) 1 else 0, minutes = left) - } - - hours?.let { - val left = it - current.hours - current += DateTimeSpan(days = if (left < 0) 1 else 0, hours = left) - } - - klockDayOfMonth ?.let { - val left = it - current.dayOfMonth - current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left) - } - - month ?.let { - val left = it - current.month0 - current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left) - } - - return current -} diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronParser.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronParser.kt index a66b977..6bb9950 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronParser.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/CronParser.kt @@ -5,7 +5,7 @@ import com.github.insanusmokrassar.krontab.utils.clamp import com.github.insanusmokrassar.krontab.utils.minutesRange import com.github.insanusmokrassar.krontab.utils.secondsRange -private fun parse(from: String, dataRange: IntRange): Array? { +private fun createCronDateTimeScheduler(from: String, dataRange: IntRange): Array? { val things = from.split(",") val results = things.flatMap { @@ -28,11 +28,11 @@ private fun parse(from: String, dataRange: IntRange): Array? { return results.map { it.toByte() }.toTypedArray() } -private fun parseMonths(from: String) = parse(from, monthRange) -private fun parseDaysOfMonth(from: String) = parse(from, dayOfMonthRange) -private fun parseHours(from: String) = parse(from, hoursRange) -private fun parseMinutes(from: String) = parse(from, minutesRange) -private fun parseSeconds(from: String) = parse(from, secondsRange) +private fun parseMonths(from: String) = createCronDateTimeScheduler(from, monthRange) +private fun parseDaysOfMonth(from: String) = createCronDateTimeScheduler(from, dayOfMonthRange) +private fun parseHours(from: String) = createCronDateTimeScheduler(from, hoursRange) +private fun parseMinutes(from: String) = createCronDateTimeScheduler(from, minutesRange) +private fun parseSeconds(from: String) = createCronDateTimeScheduler(from, secondsRange) private fun Array.fillWith( whereToPut: MutableList, @@ -49,14 +49,14 @@ private fun Array.fillWith( } } -internal fun parse(incoming: String): List { +fun createCronDateTimeScheduler(incoming: String): CronDateTimeScheduler { val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = incoming.split(" ") val secondsParsed = parseSeconds(secondsSource) - val minutesParsed = parseSeconds(minutesSource) - val hoursParsed = parseSeconds(hoursSource) - val dayOfMonthParsed = parseSeconds(dayOfMonthSource) - val monthParsed = parseSeconds(monthSource) + val minutesParsed = parseMinutes(minutesSource) + val hoursParsed = parseHours(hoursSource) + val dayOfMonthParsed = parseDaysOfMonth(dayOfMonthSource) + val monthParsed = parseMonths(monthSource) val resultCronDateTimes = mutableListOf(CronDateTime()) @@ -80,5 +80,5 @@ internal fun parse(incoming: String): List { previousCronDateTime.copy(month = currentTime) } - return resultCronDateTimes.toList() + return CronDateTimeScheduler(resultCronDateTimes.toList()) } diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/Scheduler.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/Scheduler.kt index a9584fe..e044a00 100644 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/Scheduler.kt +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/Scheduler.kt @@ -1,7 +1,12 @@ package com.github.insanusmokrassar.krontab +suspend inline fun executeWith( + scheduler: CronDateTimeScheduler, + noinline block: suspend () -> Boolean +) = scheduler.doInLoop(block) + suspend fun executeInfinity(scheduleConfig: String, block: suspend () -> Unit) { - val scheduler = CronDateTimeScheduler(parse(scheduleConfig)) + val scheduler = createCronDateTimeScheduler(scheduleConfig) scheduler.doInLoop { block() @@ -10,13 +15,13 @@ suspend fun executeInfinity(scheduleConfig: String, block: suspend () -> Unit) { } suspend fun executeWhile(scheduleConfig: String, block: suspend () -> Boolean) { - val scheduler = CronDateTimeScheduler(parse(scheduleConfig)) + val scheduler = createCronDateTimeScheduler(scheduleConfig) scheduler.doInLoop(block) } suspend fun executeOnce(scheduleConfig: String, block: suspend () -> Unit) { - val scheduler = CronDateTimeScheduler(parse(scheduleConfig)) + val scheduler = createCronDateTimeScheduler(scheduleConfig) scheduler.doInLoop { block() diff --git a/src/jvm8Main/kotlin/com/github/insanusmokrassar/krontab/Test.kt b/src/jvm8Main/kotlin/com/github/insanusmokrassar/krontab/Test.kt index 813cb69..82674c6 100644 --- a/src/jvm8Main/kotlin/com/github/insanusmokrassar/krontab/Test.kt +++ b/src/jvm8Main/kotlin/com/github/insanusmokrassar/krontab/Test.kt @@ -8,7 +8,6 @@ fun main() { var i = 0 executeInfinity("/10 /25 * * *") { println(DateTime.now()) - i++ } } }