add support of week days

This commit is contained in:
InsanusMokrassar 2021-04-22 11:58:19 +06:00
parent 0c7ceb03ee
commit bfa546ad1f
13 changed files with 83 additions and 54 deletions

View File

@ -1,7 +1,6 @@
package dev.inmo.krontab package dev.inmo.krontab
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import dev.inmo.krontab.internal.toNearDateTime
/** /**
* This interface was created for abstraction of [next] operation. Currently, there is only * This interface was created for abstraction of [next] operation. Currently, there is only

View File

@ -1,12 +1,8 @@
package dev.inmo.krontab package dev.inmo.krontab
import com.soywiz.klock.TimezoneOffset
import dev.inmo.krontab.collection.CollectionKronScheduler import dev.inmo.krontab.collection.CollectionKronScheduler
import dev.inmo.krontab.collection.includeAll import dev.inmo.krontab.collection.includeAll
import dev.inmo.krontab.internal.* import dev.inmo.krontab.internal.*
import dev.inmo.krontab.internal.CronDateTime
import dev.inmo.krontab.internal.CronDateTimeScheduler
import dev.inmo.krontab.internal.CronDateTimeSchedulerTz
/** /**
* Create new one [CollectionKronScheduler] to include all [KronScheduler]s of [this] [Iterator] * Create new one [CollectionKronScheduler] to include all [KronScheduler]s of [this] [Iterator]

View File

@ -3,8 +3,6 @@ package dev.inmo.krontab
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import dev.inmo.krontab.builder.buildSchedule import dev.inmo.krontab.builder.buildSchedule
import dev.inmo.krontab.internal.* import dev.inmo.krontab.internal.*
import dev.inmo.krontab.internal.CronDateTime
import dev.inmo.krontab.internal.CronDateTimeScheduler
internal val anyCronDateTime by lazy { internal val anyCronDateTime by lazy {
CronDateTime() CronDateTime()

View File

@ -1,6 +1,7 @@
package dev.inmo.krontab package dev.inmo.krontab
import com.soywiz.klock.* import com.soywiz.klock.TimezoneOffset
import com.soywiz.klock.minutes
import dev.inmo.krontab.internal.* import dev.inmo.krontab.internal.*
import dev.inmo.krontab.utils.Minutes import dev.inmo.krontab.utils.Minutes
@ -19,9 +20,10 @@ typealias KrontabTemplate = String
* * dayOfMonth * * dayOfMonth
* * month * * month
* * (optional) year * * (optional) year
* * (optional) (can be placed before year) offset * * (optional) (can be placed anywhere after month) (must be marked with `o` at the end, for example: 60o == +01:00) offset
* * (optional) (can be placed anywhere after month) dayOfWeek
* *
* And each one have next format: * And each one (except of offsets) have next format:
* *
* `{number}[,{number},...]` or `*` * `{number}[,{number},...]` or `*`
* *
@ -34,6 +36,9 @@ typealias KrontabTemplate = String
* * F * * F
* * L * * L
* *
* Week days must be marked with `w` at the end, and starts with 0 which means Sunday. For example, 0w == Sunday. With
* weeks you can use syntax like with any number like seconds, for example: 0-2w means Sunday-Tuesday
*
* Additional info about ranges can be found in follow accordance: * Additional info about ranges can be found in follow accordance:
* *
* * Seconds ranges can be found in [secondsRange] * * Seconds ranges can be found in [secondsRange]
@ -42,7 +47,7 @@ typealias KrontabTemplate = String
* * Days of month ranges can be found in [dayOfMonthRange] * * Days of month ranges can be found in [dayOfMonthRange]
* * Months ranges can be found in [monthRange] * * Months ranges can be found in [monthRange]
* * Years ranges can be found in [yearRange] (in fact - any [Int]) * * Years ranges can be found in [yearRange] (in fact - any [Int])
* * Offset (timezone) ranges can be found in [offsetRange] * * WeekDay (timezone) ranges can be found in [dayOfWeekRange]
* *
* Examples: * Examples:
* *
@ -51,8 +56,10 @@ typealias KrontabTemplate = String
* * "0/15 30 * * *" for every 15th seconds in a half of each hour * * "0/15 30 * * *" for every 15th seconds in a half of each hour
* * "1 2 3 F,4,L 5" for triggering in near first second of second minute of third hour of fourth day of may * * "1 2 3 F,4,L 5" for triggering in near first second of second minute of third hour of fourth day of may
* * "1 2 3 F,4,L 5 60o" for triggering in near first second of second minute of third hour of fourth day of may with timezone UTC+01:00 * * "1 2 3 F,4,L 5 60o" for triggering in near first second of second minute of third hour of fourth day of may with timezone UTC+01:00
* * "1 2 3 F,4,L 5 60o 0-2w" for triggering in near first second of second minute of third hour of fourth day of may in case if it will be in Sunday-Tuesday week days with timezone UTC+01:00
* * "1 2 3 F,4,L 5 2021" for triggering in near first second of second minute of third hour of fourth day of may of 2021st year * * "1 2 3 F,4,L 5 2021" for triggering in near first second of second minute of third hour of fourth day of may of 2021st year
* * "1 2 3 F,4,L 5 2021 60o" for triggering in near first second of second minute of third hour of fourth day of may of 2021st year with timezone UTC+01:00 * * "1 2 3 F,4,L 5 2021 60o" for triggering in near first second of second minute of third hour of fourth day of may of 2021st year with timezone UTC+01:00
* * "1 2 3 F,4,L 5 2021 60o 0-2w" for triggering in near first second of second minute of third hour of fourth day of may of 2021st year if it will be in Sunday-Tuesday week days with timezone UTC+01:00
* *
* @return In case when offset parameter is absent in [incoming] will be used [createSimpleScheduler] method and * @return In case when offset parameter is absent in [incoming] will be used [createSimpleScheduler] method and
* returned [CronDateTimeScheduler]. In case when offset parameter there is in [incoming] [KrontabTemplate] will be used * returned [CronDateTimeScheduler]. In case when offset parameter there is in [incoming] [KrontabTemplate] will be used
@ -64,15 +71,20 @@ fun createSimpleScheduler(
incoming: KrontabTemplate incoming: KrontabTemplate
): KronScheduler { ): KronScheduler {
var offsetParsed: Int? = null var offsetParsed: Int? = null
var dayOfWeekParsed: Array<Byte>? = null
var yearParsed: Array<Int>? = null var yearParsed: Array<Int>? = null
val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = incoming.split(" ").also { val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = incoming.split(" ").also {
listOfNotNull( listOfNotNull(
it.getOrNull(5), it.getOrNull(5),
it.getOrNull(6) it.getOrNull(6),
it.getOrNull(7)
).forEach { ).forEach {
val offsetFromString = parseOffset(it) val offsetFromString = parseOffset(it)
val dayOfWeekFromString = parseWeekDay(it)
offsetParsed = offsetParsed ?: offsetFromString offsetParsed = offsetParsed ?: offsetFromString
dayOfWeekParsed = dayOfWeekParsed ?: dayOfWeekFromString
when { when {
dayOfWeekFromString != null -> return@forEach
offsetFromString == null && yearParsed == null -> { offsetFromString == null && yearParsed == null -> {
yearParsed = parseYears(it) yearParsed = parseYears(it)
} }
@ -91,10 +103,10 @@ fun createSimpleScheduler(
return offsetParsed ?.let { offset -> return offsetParsed ?.let { offset ->
createKronSchedulerWithOffset( createKronSchedulerWithOffset(
secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed, TimezoneOffset(offset.minutes) secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed, dayOfWeekParsed, TimezoneOffset(offset.minutes)
) )
} ?: createKronScheduler( } ?: createKronScheduler(
secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed, dayOfWeekParsed
) )
} }

View File

@ -1,6 +1,7 @@
package dev.inmo.krontab.builder package dev.inmo.krontab.builder
import com.soywiz.klock.* import com.soywiz.klock.TimezoneOffset
import com.soywiz.klock.minutes
import dev.inmo.krontab.KronScheduler import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.KronSchedulerTz import dev.inmo.krontab.KronSchedulerTz
import dev.inmo.krontab.internal.createKronScheduler import dev.inmo.krontab.internal.createKronScheduler
@ -43,6 +44,7 @@ class SchedulerBuilder(
private var dayOfMonth: Array<Byte>? = null, private var dayOfMonth: Array<Byte>? = null,
private var month: Array<Byte>? = null, private var month: Array<Byte>? = null,
private var year: Array<Int>? = null, private var year: Array<Int>? = null,
private var dayOfWeek: Array<Byte>? = null,
private val offset: Minutes? = null private val offset: Minutes? = null
) { ) {
private fun <I, T : TimeBuilder<I>> callAndReturn( private fun <I, T : TimeBuilder<I>> callAndReturn(
@ -105,6 +107,17 @@ class SchedulerBuilder(
) ?.toTypedArray() ) ?.toTypedArray()
} }
/**
* Starts an hours block
*/
fun dayOfWeek(block: WeekDaysBuilder.() -> Unit) {
dayOfWeek = callAndReturn(
dayOfWeek,
WeekDaysBuilder(),
block
) ?.toTypedArray()
}
/** /**
* Starts an months block * Starts an months block
*/ */
@ -134,6 +147,6 @@ class SchedulerBuilder(
* @see dev.inmo.krontab.internal.createKronScheduler * @see dev.inmo.krontab.internal.createKronScheduler
*/ */
fun build(): KronScheduler = offset ?.let { fun build(): KronScheduler = offset ?.let {
createKronSchedulerWithOffset(seconds, minutes, hours, dayOfMonth, month, year, TimezoneOffset(it.minutes)) createKronSchedulerWithOffset(seconds, minutes, hours, dayOfMonth, month, year, dayOfWeek, TimezoneOffset(it.minutes))
} ?: createKronScheduler(seconds, minutes, hours, dayOfMonth, month, year) } ?: createKronScheduler(seconds, minutes, hours, dayOfMonth, month, year, dayOfWeek)
} }

View File

@ -1,11 +1,10 @@
package dev.inmo.krontab.builder package dev.inmo.krontab.builder
import dev.inmo.krontab.internal.* import dev.inmo.krontab.internal.*
import dev.inmo.krontab.utils.clamp
/** /**
* This class was created for incapsulation of builder work with specified [restrictionsRange]. For example, * This class was created for incapsulation of builder work with specified [restrictionsRange]. For example,
* [include] function of [TimeBuilder] will always [clamp] incoming data using its [restrictionsRange] * [include] function of [TimeBuilder] will always [coerceIn] incoming data using its [restrictionsRange]
*/ */
sealed class TimeBuilder<T : Number> ( sealed class TimeBuilder<T : Number> (
private val restrictionsRange: IntRange, private val restrictionsRange: IntRange,
@ -37,7 +36,7 @@ sealed class TimeBuilder<T : Number> (
*/ */
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
infix fun include(array: Array<Int>) { infix fun include(array: Array<Int>) {
val clamped = array.map { it.clamp(restrictionsRange) } + (result ?: emptySet()) val clamped = array.map { it.coerceIn(restrictionsRange) } + (result ?: emptySet())
result = clamped.toSet() result = clamped.toSet()
} }
@ -46,7 +45,7 @@ sealed class TimeBuilder<T : Number> (
*/ */
@Suppress("unused") @Suppress("unused")
infix fun at(value: Int) { infix fun at(value: Int) {
result = (result ?: emptySet()) + value.clamp(restrictionsRange) result = (result ?: emptySet()) + value.coerceIn(restrictionsRange)
} }
@ -70,7 +69,7 @@ sealed class TimeBuilder<T : Number> (
* @see [from] * @see [from]
*/ */
infix fun Int.every(delay: Int): Array<Int> { infix fun Int.every(delay: Int): Array<Int> {
val progression = clamp(restrictionsRange) .. restrictionsRange.last step delay val progression = coerceIn(restrictionsRange) .. restrictionsRange.last step delay
val result = progression.toSet().toTypedArray() val result = progression.toSet().toTypedArray()
this@TimeBuilder include result this@TimeBuilder include result
@ -88,7 +87,7 @@ sealed class TimeBuilder<T : Number> (
*/ */
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
infix fun Int.upTo(endIncluding: Int): Array<Int> { infix fun Int.upTo(endIncluding: Int): Array<Int> {
val progression = clamp(restrictionsRange) .. endIncluding.clamp(restrictionsRange) val progression = coerceIn(restrictionsRange) .. endIncluding.coerceIn(restrictionsRange)
val result = progression.toSet().toTypedArray() val result = progression.toSet().toTypedArray()
this@TimeBuilder include result this@TimeBuilder include result
@ -129,3 +128,4 @@ class HoursBuilder : TimeBuilder<Byte>(hoursRange, intToByteConverter)
class DaysOfMonthBuilder : TimeBuilder<Byte>(dayOfMonthRange, intToByteConverter) class DaysOfMonthBuilder : TimeBuilder<Byte>(dayOfMonthRange, intToByteConverter)
class MonthsBuilder : TimeBuilder<Byte>(monthRange, intToByteConverter) class MonthsBuilder : TimeBuilder<Byte>(monthRange, intToByteConverter)
class YearsBuilder : TimeBuilder<Int>(yearRange, intToIntConverter) class YearsBuilder : TimeBuilder<Int>(yearRange, intToIntConverter)
class WeekDaysBuilder : TimeBuilder<Byte>(dayOfWeekRange, intToByteConverter)

View File

@ -4,8 +4,6 @@ import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz import com.soywiz.klock.DateTimeTz
import dev.inmo.krontab.* import dev.inmo.krontab.*
import dev.inmo.krontab.internal.* import dev.inmo.krontab.internal.*
import dev.inmo.krontab.internal.CronDateTimeScheduler
import dev.inmo.krontab.internal.toNearDateTime
/** /**
* This scheduler will be useful in case you want to unite several different [KronScheduler]s * This scheduler will be useful in case you want to unite several different [KronScheduler]s

View File

@ -2,9 +2,10 @@ package dev.inmo.krontab.internal
import com.soywiz.klock.* import com.soywiz.klock.*
import dev.inmo.krontab.KronScheduler import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.utils.Minutes
/** /**
* @param dayOfweek 0-6
* @param year any int
* @param month 0-11 * @param month 0-11
* @param dayOfMonth 0-31 * @param dayOfMonth 0-31
* @param hours 0-23 * @param hours 0-23
@ -12,6 +13,7 @@ import dev.inmo.krontab.utils.Minutes
* @param seconds 0-59 * @param seconds 0-59
*/ */
internal data class CronDateTime( internal data class CronDateTime(
val dayOfweek: Byte? = null,
val year: Int? = null, val year: Int? = null,
val month: Byte? = null, val month: Byte? = null,
val dayOfMonth: Byte? = null, val dayOfMonth: Byte? = null,
@ -20,6 +22,7 @@ internal data class CronDateTime(
val seconds: Byte? = null val seconds: Byte? = null
) { ) {
init { init {
check(dayOfweek ?.let { it in dayOfWeekRange } ?: true)
check(year ?.let { it in yearRange } ?: true) check(year ?.let { it in yearRange } ?: true)
check(month ?.let { it in monthRange } ?: true) check(month ?.let { it in monthRange } ?: true)
check(dayOfMonth ?.let { it in dayOfMonthRange } ?: true) check(dayOfMonth ?.let { it in dayOfMonthRange } ?: true)
@ -29,6 +32,7 @@ internal data class CronDateTime(
} }
internal val klockDayOfMonth = dayOfMonth ?.plus(1) internal val klockDayOfMonth = dayOfMonth ?.plus(1)
internal val dayOfWeekInt: Int? = dayOfweek ?.toInt()
} }
/** /**
@ -40,6 +44,22 @@ internal data class CronDateTime(
internal fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime? { internal fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime? {
var current = relativelyTo var current = relativelyTo
val weekDay = dayOfWeekInt
if (weekDay != null && current.dayOfWeek.index0 != weekDay) {
do {
var diff = weekDay - current.dayOfWeek.index0
if (diff < 0) {
diff += 7 /* days in week */
}
current = (current + diff.days).startOfDay
val next = toNearDateTime(current)
if (next ?.dayOfWeek ?.index0 == weekDay) {
return next
}
} while (true)
}
seconds?.let { seconds?.let {
val left = it - current.seconds val left = it - current.seconds
current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left) current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left)
@ -86,7 +106,8 @@ internal fun createCronDateTimeList(
hours: Array<Byte>? = null, hours: Array<Byte>? = null,
dayOfMonth: Array<Byte>? = null, dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null, month: Array<Byte>? = null,
years: Array<Int>? = null years: Array<Int>? = null,
weekDays: Array<Byte>? = null
): List<CronDateTime> { ): List<CronDateTime> {
val resultCronDateTimes = mutableListOf(CronDateTime()) val resultCronDateTimes = mutableListOf(CronDateTime())
@ -114,8 +135,8 @@ internal fun createCronDateTimeList(
previousCronDateTime.copy(year = currentTime) previousCronDateTime.copy(year = currentTime)
} }
years ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Int -> weekDays ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
previousCronDateTime.copy(year = currentTime) previousCronDateTime.copy(dayOfweek = currentTime)
} }
return resultCronDateTimes.toList() return resultCronDateTimes.toList()
@ -130,8 +151,9 @@ internal fun createKronScheduler(
hours: Array<Byte>? = null, hours: Array<Byte>? = null,
dayOfMonth: Array<Byte>? = null, dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null, month: Array<Byte>? = null,
years: Array<Int>? = null years: Array<Int>? = null,
): KronScheduler = CronDateTimeScheduler(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years)) weekDays: Array<Byte>? = null
): KronScheduler = CronDateTimeScheduler(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years, weekDays))
/** /**
* @return [KronScheduler] (in fact [CronDateTimeScheduler]) based on incoming data * @return [KronScheduler] (in fact [CronDateTimeScheduler]) based on incoming data
*/ */
@ -142,5 +164,6 @@ internal fun createKronSchedulerWithOffset(
dayOfMonth: Array<Byte>? = null, dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null, month: Array<Byte>? = null,
years: Array<Int>? = null, years: Array<Int>? = null,
weekDays: Array<Byte>? = null,
offset: TimezoneOffset offset: TimezoneOffset
): KronScheduler = CronDateTimeSchedulerTz(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years), offset) ): KronScheduler = CronDateTimeSchedulerTz(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years, weekDays), offset)

View File

@ -1,8 +1,9 @@
package dev.inmo.krontab.internal package dev.inmo.krontab.internal
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import dev.inmo.krontab.* import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.collection.plus import dev.inmo.krontab.collection.plus
import dev.inmo.krontab.getAnyNext
/** /**
* Cron-oriented realisation of [KronScheduler] * Cron-oriented realisation of [KronScheduler]

View File

@ -1,8 +1,9 @@
package dev.inmo.krontab.internal package dev.inmo.krontab.internal
import com.soywiz.klock.* import com.soywiz.klock.DateTimeTz
import dev.inmo.krontab.* import com.soywiz.klock.TimezoneOffset
import dev.inmo.krontab.collection.plus import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.KronSchedulerTz
/** /**
* Cron-oriented realisation of [KronScheduler] with taking into account [offset] for list of [cronDateTimes] * Cron-oriented realisation of [KronScheduler] with taking into account [offset] for list of [cronDateTimes]

View File

@ -1,7 +1,5 @@
package dev.inmo.krontab.internal package dev.inmo.krontab.internal
import dev.inmo.krontab.utils.clamp
typealias Converter<T> = (Int) -> T typealias Converter<T> = (Int) -> T
internal val intToByteConverter: Converter<Byte> = { it: Int -> it.toByte() } internal val intToByteConverter: Converter<Byte> = { it: Int -> it.toByte() }
@ -18,7 +16,7 @@ private fun <T> createSimpleScheduler(from: String, dataRange: IntRange, dataCon
when { when {
currentToken.contains("-") -> { currentToken.contains("-") -> {
val splitted = currentToken.split("-") val splitted = currentToken.split("-")
(splitted.first().toInt().clamp(dataRange) .. splitted[1].toInt().clamp(dataRange)).toList() (splitted.first().toInt().coerceIn(dataRange) .. splitted[1].toInt().coerceIn(dataRange)).toList()
} }
currentToken.contains("/") -> { currentToken.contains("/") -> {
val (start, step) = currentToken.split("/") val (start, step) = currentToken.split("/")
@ -26,18 +24,19 @@ private fun <T> createSimpleScheduler(from: String, dataRange: IntRange, dataCon
0 0
} else { } else {
start.toInt() start.toInt()
}).clamp(dataRange) }).coerceIn(dataRange)
val stepNum = step.toInt().clamp(dataRange) val stepNum = step.toInt().coerceIn(dataRange)
(startNum .. dataRange.last step stepNum).map { it } (startNum .. dataRange.last step stepNum).map { it }
} }
currentToken == "*" -> return null currentToken == "*" -> return null
else -> listOf(currentToken.toInt().clamp(dataRange)) else -> listOf(currentToken.toInt().coerceIn(dataRange))
} }
} }
return results.map(dataConverter) return results.map(dataConverter)
} }
internal fun parseWeekDay(from: String?) = from ?.let { if (it.endsWith("w")) createSimpleScheduler(it.removeSuffix("w"), dayOfWeekRange, intToByteConverter) ?.toTypedArray() else null }
internal fun parseOffset(from: String?) = from ?.let { if (it.endsWith("o")) it.removeSuffix("o").toIntOrNull() else null } internal fun parseOffset(from: String?) = from ?.let { if (it.endsWith("o")) it.removeSuffix("o").toIntOrNull() else null }
internal fun parseYears(from: String?) = from ?.let { createSimpleScheduler(from, yearRange, intToIntConverter) ?.toTypedArray() } internal fun parseYears(from: String?) = from ?.let { createSimpleScheduler(from, yearRange, intToIntConverter) ?.toTypedArray() }
internal fun parseMonths(from: String) = createSimpleScheduler(from, monthRange, intToByteConverter) ?.toTypedArray() internal fun parseMonths(from: String) = createSimpleScheduler(from, monthRange, intToByteConverter) ?.toTypedArray()

View File

@ -1,5 +1,6 @@
package dev.inmo.krontab.internal package dev.inmo.krontab.internal
internal val dayOfWeekRange = 0 .. 6
internal val yearRange = Int.MIN_VALUE .. Int.MAX_VALUE internal val yearRange = Int.MIN_VALUE .. Int.MAX_VALUE
internal val monthRange = 0 .. 11 internal val monthRange = 0 .. 11
internal val dayOfMonthRange = 0 .. 30 internal val dayOfMonthRange = 0 .. 30

View File

@ -1,12 +0,0 @@
package dev.inmo.krontab.utils
/**
* @return [min] in case if [this] less than [min]. Otherwise will check that [max] grant than [this] and return [this]
* if so or [max] otherwise
*/
internal fun Int.clamp(min: Int, max: Int): Int = if (this < min) min else if (this > max) max else this
/**
* Wrapper function for [clamp] extension
*/
internal fun Int.clamp(range: IntRange): Int = clamp(range.first, range.last)