krontab/src/commonMain/kotlin/internal/CronDateTime.kt

137 lines
4.8 KiB
Kotlin
Raw Normal View History

2020-11-21 08:58:19 +00:00
package dev.inmo.krontab.internal
2019-10-04 18:04:00 +00:00
import korlibs.time.DateTime
import korlibs.time.TimezoneOffset
2020-11-21 08:58:19 +00:00
import dev.inmo.krontab.KronScheduler
2019-10-04 18:04:00 +00:00
/**
* @param daysOfWeek 0-6
* @param years any int
* @param months 0-11
2022-06-15 06:40:03 +00:00
* @param daysOfMonth 0-30
2020-06-03 14:19:57 +00:00
* @param hours 0-23
* @param minutes 0-59
* @param seconds 0-59
2019-10-04 18:04:00 +00:00
*/
2019-10-05 05:23:48 +00:00
internal data class CronDateTime(
val daysOfWeek: Array<Byte>? = null,
val years: Array<Int>? = null,
val months: Array<Byte>? = null,
val daysOfMonth: Array<Byte>? = null,
val hours: Array<Byte>? = null,
val minutes: Array<Byte>? = null,
2022-04-29 15:57:10 +00:00
val seconds: Array<Byte>? = null,
val milliseconds: Array<Short>? = millisecondsArrayDefault
2019-10-04 18:04:00 +00:00
) {
init {
check(daysOfWeek ?.all { it in dayOfWeekRange } ?: true)
check(years?.all { it in yearRange } ?: true)
check(months?.all { it in monthRange } ?: true)
check(daysOfMonth ?.all { it in dayOfMonthRange } ?: true)
check(hours?.all { it in hoursRange } ?: true)
check(minutes?.all { it in minutesRange } ?: true)
check(seconds?.all { it in secondsRange } ?: true)
2022-04-29 15:57:10 +00:00
check(milliseconds?.all { it in millisecondsRange } ?: true)
2019-10-04 18:04:00 +00:00
}
internal val calculators = listOf(
2021-05-30 12:53:44 +00:00
years ?.let { NearDateTimeCalculatorYears(it) },
daysOfWeek ?.let { NearDateTimeCalculatorWeekDays(it) },
2022-04-29 15:57:10 +00:00
milliseconds ?.let { NearDateTimeCalculatorMillis(it) },
seconds ?.let { NearDateTimeCalculatorSeconds(it) },
minutes ?.let { NearDateTimeCalculatorMinutes(it) },
hours ?.let { NearDateTimeCalculatorHours(it) },
daysOfMonth ?.let { NearDateTimeCalculatorDays(it) },
months ?.let { NearDateTimeCalculatorMonths(it) },
)
internal fun toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime? {
var current = relativelyTo
whileLoop@while (true) {
for (calculator in calculators) {
val (calculated, requireRecalculation) = (calculator ?: continue).calculateNearTime(current) ?: return null
current = calculated
if (requireRecalculation) {
continue@whileLoop
}
2021-04-22 05:58:19 +00:00
}
return current
}
2019-10-05 10:29:59 +00:00
}
}
internal fun createCronDateTime(
seconds: Array<Byte>? = null,
minutes: Array<Byte>? = null,
hours: Array<Byte>? = null,
dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null,
2021-04-22 05:58:19 +00:00
years: Array<Int>? = null,
2022-04-29 15:57:10 +00:00
weekDays: Array<Byte>? = null,
milliseconds: Array<Short>? = millisecondsArrayDefault
): CronDateTime {
2022-04-29 15:57:10 +00:00
return CronDateTime(weekDays, years, month, dayOfMonth, hours, minutes, seconds, milliseconds)
}
2021-04-09 18:28:08 +00:00
/**
* @return [KronScheduler] (in fact [CronDateTimeScheduler]) based on incoming data
*/
internal fun createKronScheduler(
seconds: Array<Byte>? = null,
minutes: Array<Byte>? = null,
hours: Array<Byte>? = null,
dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null,
2021-04-22 05:58:19 +00:00
years: Array<Int>? = null,
2022-04-29 15:57:10 +00:00
weekDays: Array<Byte>? = null,
milliseconds: Array<Short>? = millisecondsArrayDefault
): KronScheduler = CronDateTimeScheduler(
createCronDateTime(
seconds,
minutes,
hours,
dayOfMonth,
month,
years,
weekDays,
milliseconds
)
)
2021-04-09 18:28:08 +00:00
/**
* @return [KronScheduler] (in fact [CronDateTimeScheduler]) based on incoming data
*/
internal fun createKronSchedulerWithOffset(
seconds: Array<Byte>? = null,
minutes: Array<Byte>? = null,
hours: Array<Byte>? = null,
dayOfMonth: Array<Byte>? = null,
month: Array<Byte>? = null,
years: Array<Int>? = null,
2021-04-22 05:58:19 +00:00
weekDays: Array<Byte>? = null,
2022-04-29 15:57:10 +00:00
offset: TimezoneOffset,
milliseconds: Array<Short>? = millisecondsArrayDefault
): KronScheduler = CronDateTimeSchedulerTz(
createCronDateTime(
seconds,
minutes,
hours,
dayOfMonth,
month,
years,
weekDays,
milliseconds
),
offset
)
internal fun List<CronDateTime>.merge() = CronDateTime(
flatMap { it.daysOfWeek ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.years ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.months ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.daysOfMonth ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.hours ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.minutes ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
flatMap { it.seconds ?.toList() ?: emptyList() }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
2022-04-29 15:57:10 +00:00
flatMap { it.milliseconds ?.toList() ?: listOf(0) }.distinct().toTypedArray().takeIf { it.isNotEmpty() },
)