diff --git a/build.gradle b/build.gradle index d44aa9b..d63dd6c 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,8 @@ kotlin { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$kotlin_coroutines_version" + + implementation "com.soywiz.korlibs.klock:klock:$klockVersion" } } jvm8Main { diff --git a/gradle.properties b/gradle.properties index 46ed143..8197dfd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,10 @@ kotlin.code.style=official -kotlin_version=1.3.31 -kotlin_coroutines_version=1.2.1 +kotlin_version=1.3.50 +kotlin_coroutines_version=1.3.2 gradle_bintray_plugin_version=1.8.4 +klockVersion=1.7.3 + project_public_name=Krontab project_public_description=It is analog of crontab util for Kotlin Coroutines diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e6380e5..5c82840 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip diff --git a/settings.gradle b/settings.gradle index 3176413..bd02020 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,3 +16,5 @@ include 'services:webservice' */ rootProject.name = 'krontab' + +enableFeaturePreview('GRADLE_METADATA') diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/CronDateTime.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/CronDateTime.kt new file mode 100644 index 0000000..775f099 --- /dev/null +++ b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/CronDateTime.kt @@ -0,0 +1,42 @@ +package com.github.insanusmokrassar.krontab.parts + +import com.soywiz.klock.* + +data class CronDateTime( + val month: Byte? = null, + val dayOfMonth: Byte? = null, + val hour: Byte? = null, + val minute: Byte? = null, + val second: Byte? = null +) + +fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime { + var current = relativelyTo + + second ?.let { + val left = it - current.seconds + current += DateTimeSpan(minutes = if (left < 0) 1 else 0, seconds = left) + } + + minute ?.let { + val left = it - current.minutes + current += DateTimeSpan(hours = if (left < 0) 1 else 0, minutes = left) + } + + hour ?.let { + val left = it - current.hours + current += DateTimeSpan(days = if (left < 0) 1 else 0, hours = left) + } + + dayOfMonth ?.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/parts/KronTime.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/KronTime.kt deleted file mode 100644 index eb12210..0000000 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/KronTime.kt +++ /dev/null @@ -1,110 +0,0 @@ -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 List.notMaxOrNull(max: Int): List? = if (size >= max) { - null -} else { - this -} - -internal fun KronTimes( - timePattern: TimePattern -): List { - 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)) - } ?: listOf(KronTime(millis, seconds, minutes)) - } ?: listOf(KronTime(millis, seconds)) - } ?: listOf(KronTime(milliseconds = millis)) - } ?: listOf(KronTime()) -} - -internal fun KronTime( - fullMillis: Milliseconds -): KronTime { - val millis = (fullMillis % millisCount).toShort() - var currentDivided: Double = floor(fullMillis.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? = null, - val seconds: Seconds? = null, - val minutes: Minutes? = null, - val hours: Hours? = null, - val weekDays: WeekDays? = null -) diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/PeriodAdapters.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/PeriodAdapters.kt deleted file mode 100644 index b7da5d5..0000000 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/PeriodAdapters.kt +++ /dev/null @@ -1,93 +0,0 @@ -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? { - 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? { - 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? { - 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 { - 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 = emptyMap() -): List { - return period.split(",").flatMap { - unconfinedVariants[it] ?.let { - listOf(it) - } ?: adaptPeriod( - it, - minPeriodValue, - maxPeriodValue - ) - } -} - diff --git a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/TimeTypeAliases.kt b/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/TimeTypeAliases.kt deleted file mode 100644 index 4487423..0000000 --- a/src/commonMain/kotlin/com/github/insanusmokrassar/krontab/parts/TimeTypeAliases.kt +++ /dev/null @@ -1,11 +0,0 @@ -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