mirror of
https://github.com/InsanusMokrassar/krontab.git
synced 2024-11-26 03:58:50 +00:00
rewrite system with offsets
This commit is contained in:
parent
a07027399c
commit
5844859369
@ -13,22 +13,15 @@ import dev.inmo.krontab.internal.toNearDateTime
|
|||||||
* @see dev.inmo.krontab.internal.CronDateTimeScheduler
|
* @see dev.inmo.krontab.internal.CronDateTimeScheduler
|
||||||
*/
|
*/
|
||||||
interface KronScheduler {
|
interface KronScheduler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Next [DateTime] when some action must be triggered according to settings of this instance
|
* @return Next [DateTime] when some action must be triggered according to settings of this instance
|
||||||
*
|
*
|
||||||
* @see dev.inmo.krontab.internal.CronDateTimeScheduler.next
|
* @see dev.inmo.krontab.internal.CronDateTimeScheduler.next
|
||||||
*/
|
*/
|
||||||
suspend fun next(relatively: DateTime = DateTime.now()): DateTime?
|
suspend fun next(relatively: DateTime = DateTime.now()): DateTime?
|
||||||
|
|
||||||
suspend fun next(relatively: DateTimeTz): DateTimeTz?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun KronScheduler.nextOrRelative(relatively: DateTime = DateTime.now()): DateTime = next(relatively) ?: getAnyNext(relatively)
|
suspend fun KronScheduler.nextOrRelative(relatively: DateTime = DateTime.now()): DateTime = next(relatively) ?: getAnyNext(relatively)
|
||||||
suspend fun KronScheduler.nextOrRelative(relatively: DateTimeTz): DateTimeTz = next(relatively) ?: getAnyNext(relatively)
|
|
||||||
suspend fun KronScheduler.nextOrNow(): DateTime = DateTime.now().let {
|
suspend fun KronScheduler.nextOrNow(): DateTime = DateTime.now().let {
|
||||||
next(it) ?: getAnyNext(it)
|
next(it) ?: getAnyNext(it)
|
||||||
}
|
}
|
||||||
suspend fun KronScheduler.nextOrNowWithOffset(): DateTimeTz = DateTimeTz.nowLocal().let {
|
|
||||||
next(it) ?: getAnyNext(it)
|
|
||||||
}
|
|
||||||
|
32
src/commonMain/kotlin/dev/inmo/krontab/KronSchedulerTz.kt
Normal file
32
src/commonMain/kotlin/dev/inmo/krontab/KronSchedulerTz.kt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package dev.inmo.krontab
|
||||||
|
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
import com.soywiz.klock.DateTimeTz
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface extending [KronScheduler] to use [DateTimeTz] with taking into account offset of incoming time for
|
||||||
|
* [next] operation.
|
||||||
|
*
|
||||||
|
* @see dev.inmo.krontab.internal.CronDateTimeScheduler
|
||||||
|
* @see dev.inmo.krontab.KronScheduler
|
||||||
|
*/
|
||||||
|
interface KronSchedulerTz : KronScheduler {
|
||||||
|
suspend fun next(relatively: DateTimeTz): DateTimeTz?
|
||||||
|
|
||||||
|
override suspend fun next(relatively: DateTime): DateTime? = next(relatively.localUnadjusted) ?.local
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun KronSchedulerTz.nextOrRelative(relatively: DateTimeTz): DateTimeTz = next(relatively) ?: getAnyNext(
|
||||||
|
relatively.local
|
||||||
|
).toOffsetUnadjusted(relatively.offset)
|
||||||
|
suspend fun KronSchedulerTz.nextOrNowWithOffset(): DateTimeTz = DateTimeTz.nowLocal().let {
|
||||||
|
next(it) ?: getAnyNext(
|
||||||
|
it.local
|
||||||
|
).toOffsetUnadjusted(it.offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun KronScheduler.next(relatively: DateTimeTz) = if (this is KronSchedulerTz) {
|
||||||
|
this.next(relatively)
|
||||||
|
} else {
|
||||||
|
this.next(relatively.local) ?.toOffsetUnadjusted(relatively.offset)
|
||||||
|
}
|
@ -1,8 +1,12 @@
|
|||||||
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.internal.*
|
||||||
import dev.inmo.krontab.internal.CronDateTime
|
import dev.inmo.krontab.internal.CronDateTime
|
||||||
import dev.inmo.krontab.internal.CronDateTimeScheduler
|
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]
|
||||||
@ -10,18 +14,23 @@ import dev.inmo.krontab.internal.CronDateTimeScheduler
|
|||||||
* @see CollectionKronScheduler
|
* @see CollectionKronScheduler
|
||||||
* @see CollectionKronScheduler.include
|
* @see CollectionKronScheduler.include
|
||||||
*/
|
*/
|
||||||
fun Iterator<KronScheduler>.merge(): KronScheduler {
|
fun Iterator<KronScheduler>.merge(): CollectionKronScheduler {
|
||||||
val cronDateTimes = mutableListOf<CronDateTime>()
|
val cronDateTimes = mutableListOf<CronDateTime>()
|
||||||
|
val timezonedCronDateTimes = mutableListOf<CronDateTimeSchedulerTz>()
|
||||||
val collectionScheduler = CollectionKronScheduler()
|
val collectionScheduler = CollectionKronScheduler()
|
||||||
forEach {
|
forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is CronDateTimeScheduler -> cronDateTimes.addAll(it.cronDateTimes)
|
is CronDateTimeScheduler -> cronDateTimes.addAll(it.cronDateTimes)
|
||||||
|
is CronDateTimeSchedulerTz -> timezonedCronDateTimes.add(it)
|
||||||
else -> collectionScheduler.include(it)
|
else -> collectionScheduler.include(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cronDateTimes.isNotEmpty()) {
|
if (cronDateTimes.isNotEmpty()) {
|
||||||
collectionScheduler.include(CronDateTimeScheduler(cronDateTimes))
|
collectionScheduler.include(CronDateTimeScheduler(cronDateTimes))
|
||||||
}
|
}
|
||||||
|
if (timezonedCronDateTimes.isNotEmpty()) {
|
||||||
|
collectionScheduler.includeAll(mergeCronDateTimeSchedulers(timezonedCronDateTimes))
|
||||||
|
}
|
||||||
return collectionScheduler
|
return collectionScheduler
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +41,10 @@ fun Iterator<KronScheduler>.merge(): KronScheduler {
|
|||||||
* @see CollectionKronScheduler.include
|
* @see CollectionKronScheduler.include
|
||||||
*/
|
*/
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun Iterable<KronScheduler>.merge(): KronScheduler = iterator().merge()
|
inline fun Iterable<KronScheduler>.merge(): CollectionKronScheduler = iterator().merge()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Vararg shortcut for [merge]
|
* @return Vararg shortcut for [merge]
|
||||||
*/
|
*/
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun merge(vararg kronDateTimeSchedulers: KronScheduler) = kronDateTimeSchedulers.iterator().merge()
|
inline fun merge(vararg kronDateTimeSchedulers: KronScheduler): CollectionKronScheduler = kronDateTimeSchedulers.iterator().merge()
|
||||||
|
@ -11,7 +11,6 @@ internal val anyCronDateTime by lazy {
|
|||||||
CronDateTime()
|
CronDateTime()
|
||||||
}
|
}
|
||||||
internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(relatively)!!
|
internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(relatively)!!
|
||||||
internal fun getAnyNext(relatively: DateTimeTz) = anyCronDateTime.toNearDateTime(relatively)!!
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now]
|
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now]
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package dev.inmo.krontab
|
package dev.inmo.krontab
|
||||||
|
|
||||||
|
import com.soywiz.klock.*
|
||||||
import dev.inmo.krontab.internal.*
|
import dev.inmo.krontab.internal.*
|
||||||
|
import dev.inmo.krontab.utils.Minutes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see createSimpleScheduler
|
* @see createSimpleScheduler
|
||||||
@ -52,9 +54,15 @@ typealias KrontabTemplate = String
|
|||||||
* * "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
|
||||||
*
|
*
|
||||||
|
* @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
|
||||||
|
* [createKronSchedulerWithOffset] and returned [CronDateTimeSchedulerTz]
|
||||||
|
*
|
||||||
* @see dev.inmo.krontab.internal.createKronScheduler
|
* @see dev.inmo.krontab.internal.createKronScheduler
|
||||||
*/
|
*/
|
||||||
fun createSimpleScheduler(incoming: KrontabTemplate): KronScheduler {
|
fun createSimpleScheduler(
|
||||||
|
incoming: KrontabTemplate
|
||||||
|
): KronScheduler {
|
||||||
var offsetParsed: Int? = null
|
var offsetParsed: Int? = 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 {
|
||||||
@ -81,22 +89,53 @@ fun createSimpleScheduler(incoming: KrontabTemplate): KronScheduler {
|
|||||||
val dayOfMonthParsed = parseDaysOfMonth(dayOfMonthSource)
|
val dayOfMonthParsed = parseDaysOfMonth(dayOfMonthSource)
|
||||||
val monthParsed = parseMonths(monthSource)
|
val monthParsed = parseMonths(monthSource)
|
||||||
|
|
||||||
return createKronScheduler(
|
return offsetParsed ?.let { offset ->
|
||||||
secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed, offsetParsed
|
createKronSchedulerWithOffset(
|
||||||
|
secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed, TimezoneOffset(offset.minutes)
|
||||||
)
|
)
|
||||||
|
} ?: createKronScheduler(
|
||||||
|
secondsParsed, minutesParsed, hoursParsed, dayOfMonthParsed, monthParsed, yearParsed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createSimpleScheduler(
|
||||||
|
incoming: KrontabTemplate,
|
||||||
|
defaultOffset: Minutes
|
||||||
|
): KronSchedulerTz {
|
||||||
|
val scheduler = createSimpleScheduler(incoming)
|
||||||
|
return if (scheduler is KronSchedulerTz) {
|
||||||
|
scheduler
|
||||||
|
} else {
|
||||||
|
CronDateTimeSchedulerTz(
|
||||||
|
(scheduler as CronDateTimeScheduler).cronDateTimes,
|
||||||
|
TimezoneOffset(defaultOffset.minutes)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for [createSimpleScheduler]
|
* Shortcut for [createSimpleScheduler]
|
||||||
*/
|
*/
|
||||||
fun buildSchedule(incoming: KrontabTemplate): KronScheduler = createSimpleScheduler(incoming)
|
fun buildSchedule(incoming: KrontabTemplate): KronScheduler = createSimpleScheduler(incoming)
|
||||||
|
/**
|
||||||
|
* Shortcut for [createSimpleScheduler]
|
||||||
|
*/
|
||||||
|
fun buildSchedule(incoming: KrontabTemplate, defaultOffset: Minutes): KronSchedulerTz = createSimpleScheduler(incoming, defaultOffset)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for [buildSchedule]
|
* Shortcut for [buildSchedule]
|
||||||
*/
|
*/
|
||||||
fun KrontabTemplate.toSchedule(): KronScheduler = buildSchedule(this)
|
fun KrontabTemplate.toSchedule(): KronScheduler = buildSchedule(this)
|
||||||
|
/**
|
||||||
|
* Shortcut for [buildSchedule]
|
||||||
|
*/
|
||||||
|
fun KrontabTemplate.toSchedule(defaultOffset: Minutes): KronSchedulerTz = buildSchedule(this, defaultOffset)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shortcut for [buildSchedule]
|
* Shortcut for [buildSchedule]
|
||||||
*/
|
*/
|
||||||
fun KrontabTemplate.toKronScheduler(): KronScheduler = buildSchedule(this)
|
fun KrontabTemplate.toKronScheduler(): KronScheduler = buildSchedule(this)
|
||||||
|
/**
|
||||||
|
* Shortcut for [buildSchedule]
|
||||||
|
*/
|
||||||
|
fun KrontabTemplate.toKronScheduler(defaultOffset: Minutes): KronSchedulerTz = buildSchedule(this, defaultOffset)
|
@ -1,9 +1,10 @@
|
|||||||
package dev.inmo.krontab.builder
|
package dev.inmo.krontab.builder
|
||||||
|
|
||||||
import com.soywiz.klock.TimeSpan
|
import com.soywiz.klock.*
|
||||||
import com.soywiz.klock.TimezoneOffset
|
|
||||||
import dev.inmo.krontab.KronScheduler
|
import dev.inmo.krontab.KronScheduler
|
||||||
|
import dev.inmo.krontab.KronSchedulerTz
|
||||||
import dev.inmo.krontab.internal.createKronScheduler
|
import dev.inmo.krontab.internal.createKronScheduler
|
||||||
|
import dev.inmo.krontab.internal.createKronSchedulerWithOffset
|
||||||
import dev.inmo.krontab.utils.Minutes
|
import dev.inmo.krontab.utils.Minutes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,6 +20,22 @@ fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): KronScheduler {
|
|||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will help to create an instance of [KronScheduler]
|
||||||
|
*
|
||||||
|
* @see dev.inmo.krontab.createSimpleScheduler
|
||||||
|
*/
|
||||||
|
fun buildSchedule(
|
||||||
|
offset: Minutes,
|
||||||
|
settingsBlock: SchedulerBuilder.() -> Unit
|
||||||
|
): KronSchedulerTz {
|
||||||
|
val builder = SchedulerBuilder(offset = offset)
|
||||||
|
|
||||||
|
builder.settingsBlock()
|
||||||
|
|
||||||
|
return builder.build() as KronSchedulerTz
|
||||||
|
}
|
||||||
|
|
||||||
class SchedulerBuilder(
|
class SchedulerBuilder(
|
||||||
private var seconds: Array<Byte>? = null,
|
private var seconds: Array<Byte>? = null,
|
||||||
private var minutes: Array<Byte>? = null,
|
private var minutes: Array<Byte>? = null,
|
||||||
@ -26,7 +43,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,
|
||||||
var offset: Minutes? = null
|
private val offset: Minutes? = null
|
||||||
) {
|
) {
|
||||||
private fun <I, T : TimeBuilder<I>> callAndReturn(
|
private fun <I, T : TimeBuilder<I>> callAndReturn(
|
||||||
initial: Array<I>?,
|
initial: Array<I>?,
|
||||||
@ -110,32 +127,13 @@ class SchedulerBuilder(
|
|||||||
) ?.toTypedArray()
|
) ?.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter of [offset] property
|
|
||||||
*/
|
|
||||||
fun offset(offset: Minutes?) {
|
|
||||||
this.offset = offset
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter of [offset] property
|
|
||||||
*/
|
|
||||||
fun offset(offset: TimeSpan?) {
|
|
||||||
this.offset = offset ?.minutes ?.toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setter of [offset] property
|
|
||||||
*/
|
|
||||||
fun offset(offset: TimezoneOffset?) {
|
|
||||||
this.offset = offset ?.totalMinutesInt
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Completely built and independent [KronScheduler]
|
* @return Completely built and independent [KronScheduler]
|
||||||
*
|
*
|
||||||
* @see dev.inmo.krontab.createSimpleScheduler
|
* @see dev.inmo.krontab.createSimpleScheduler
|
||||||
* @see dev.inmo.krontab.internal.createKronScheduler
|
* @see dev.inmo.krontab.internal.createKronScheduler
|
||||||
*/
|
*/
|
||||||
fun build(): KronScheduler = createKronScheduler(seconds, minutes, hours, dayOfMonth, month, year)
|
fun build(): KronScheduler = offset ?.let {
|
||||||
|
createKronSchedulerWithOffset(seconds, minutes, hours, dayOfMonth, month, year, TimezoneOffset(it.minutes))
|
||||||
|
} ?: createKronScheduler(seconds, minutes, hours, dayOfMonth, month, year)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import dev.inmo.krontab.internal.toNearDateTime
|
|||||||
*/
|
*/
|
||||||
data class CollectionKronScheduler internal constructor(
|
data class CollectionKronScheduler internal constructor(
|
||||||
internal val schedulers: MutableList<KronScheduler>
|
internal val schedulers: MutableList<KronScheduler>
|
||||||
) : KronScheduler {
|
) : KronSchedulerTz {
|
||||||
internal constructor() : this(mutableListOf())
|
internal constructor() : this(mutableListOf())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +51,6 @@ data class CollectionKronScheduler internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun next(relatively: DateTimeTz): DateTimeTz {
|
override suspend fun next(relatively: DateTimeTz): DateTimeTz {
|
||||||
return schedulers.mapNotNull { it.next(relatively) }.minOrNull() ?: getAnyNext(relatively)
|
return schedulers.mapNotNull { it.next(relatively) }.minOrNull() ?: getAnyNext(relatively.local).toOffsetUnadjusted(relatively.offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import dev.inmo.krontab.utils.Minutes
|
|||||||
* @param seconds 0-59
|
* @param seconds 0-59
|
||||||
*/
|
*/
|
||||||
internal data class CronDateTime(
|
internal data class CronDateTime(
|
||||||
val offset: Int? = 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,
|
||||||
@ -30,7 +29,6 @@ internal data class CronDateTime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal val klockDayOfMonth = dayOfMonth ?.plus(1)
|
internal val klockDayOfMonth = dayOfMonth ?.plus(1)
|
||||||
internal val klockOffset = offset ?.minutes ?.offset
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,35 +80,14 @@ internal fun CronDateTime.toNearDateTime(relativelyTo: DateTime = DateTime.now()
|
|||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
internal fun createCronDateTimeList(
|
||||||
* THIS METHOD WILL TAKE CARE ABOUT [offset] PARAMETER. It was decided due to the fact that we unable to get
|
|
||||||
* real timezone offset from simple [DateTime]
|
|
||||||
*
|
|
||||||
* @return The near [DateTime] which happens after [relativelyTo] or will be equal to [relativelyTo]
|
|
||||||
*/
|
|
||||||
internal fun CronDateTime.toNearDateTime(
|
|
||||||
relativelyTo: DateTimeTz
|
|
||||||
): DateTimeTz? {
|
|
||||||
val klockOffset = klockOffset
|
|
||||||
return if (klockOffset != null) {
|
|
||||||
toNearDateTime(relativelyTo.toOffset(klockOffset).local) ?.toOffsetUnadjusted(klockOffset) ?.toOffset(relativelyTo.offset)
|
|
||||||
} else {
|
|
||||||
toNearDateTime(relativelyTo.local) ?.toOffsetUnadjusted(relativelyTo.offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return [KronScheduler] (in fact [CronDateTimeScheduler]) based on incoming data
|
|
||||||
*/
|
|
||||||
internal fun createKronScheduler(
|
|
||||||
seconds: Array<Byte>? = null,
|
seconds: Array<Byte>? = null,
|
||||||
minutes: Array<Byte>? = null,
|
minutes: Array<Byte>? = null,
|
||||||
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
|
||||||
offset: Minutes? = null
|
): List<CronDateTime> {
|
||||||
): KronScheduler {
|
|
||||||
val resultCronDateTimes = mutableListOf(CronDateTime())
|
val resultCronDateTimes = mutableListOf(CronDateTime())
|
||||||
|
|
||||||
seconds ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
|
seconds ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
|
||||||
@ -141,9 +118,29 @@ internal fun createKronScheduler(
|
|||||||
previousCronDateTime.copy(year = currentTime)
|
previousCronDateTime.copy(year = currentTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
offset ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Int ->
|
return resultCronDateTimes.toList()
|
||||||
previousCronDateTime.copy(year = currentTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
return CronDateTimeScheduler(resultCronDateTimes.toList())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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,
|
||||||
|
years: Array<Int>? = null
|
||||||
|
): KronScheduler = CronDateTimeScheduler(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years))
|
||||||
|
/**
|
||||||
|
* @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,
|
||||||
|
offset: TimezoneOffset
|
||||||
|
): KronScheduler = CronDateTimeSchedulerTz(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years), offset)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package dev.inmo.krontab.internal
|
package dev.inmo.krontab.internal
|
||||||
|
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.*
|
||||||
import com.soywiz.klock.DateTimeTz
|
|
||||||
import dev.inmo.krontab.*
|
import dev.inmo.krontab.*
|
||||||
import dev.inmo.krontab.collection.plus
|
import dev.inmo.krontab.collection.plus
|
||||||
|
|
||||||
@ -30,10 +29,6 @@ internal data class CronDateTimeScheduler internal constructor(
|
|||||||
override suspend fun next(relatively: DateTime): DateTime {
|
override suspend fun next(relatively: DateTime): DateTime {
|
||||||
return cronDateTimes.mapNotNull { it.toNearDateTime(relatively) }.minOrNull() ?: getAnyNext(relatively)
|
return cronDateTimes.mapNotNull { it.toNearDateTime(relatively) }.minOrNull() ?: getAnyNext(relatively)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun next(relatively: DateTimeTz): DateTimeTz {
|
|
||||||
return cronDateTimes.mapNotNull { it.toNearDateTime(relatively) }.minOrNull() ?: getAnyNext(relatively)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun mergeCronDateTimeSchedulers(schedulers: List<CronDateTimeScheduler>) = CronDateTimeScheduler(
|
internal fun mergeCronDateTimeSchedulers(schedulers: List<CronDateTimeScheduler>) = CronDateTimeScheduler(
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package dev.inmo.krontab.internal
|
||||||
|
|
||||||
|
import com.soywiz.klock.*
|
||||||
|
import dev.inmo.krontab.*
|
||||||
|
import dev.inmo.krontab.collection.plus
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cron-oriented realisation of [KronScheduler] with taking into account [offset] for list of [cronDateTimes]
|
||||||
|
*
|
||||||
|
* @see CronDateTime
|
||||||
|
*/
|
||||||
|
internal data class CronDateTimeSchedulerTz internal constructor(
|
||||||
|
internal val cronDateTimes: List<CronDateTime>,
|
||||||
|
internal val offset: TimezoneOffset
|
||||||
|
) : KronSchedulerTz {
|
||||||
|
override suspend fun next(relatively: DateTimeTz): DateTimeTz? {
|
||||||
|
val dateTimeWithActualOffset = relatively.utc.toOffset(offset).local
|
||||||
|
return cronDateTimes.mapNotNull {
|
||||||
|
it.toNearDateTime(dateTimeWithActualOffset)
|
||||||
|
}.minOrNull() ?.toOffset(relatively.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun mergeCronDateTimeSchedulers(
|
||||||
|
schedulers: List<CronDateTimeSchedulerTz>
|
||||||
|
) = schedulers.groupBy {
|
||||||
|
it.offset
|
||||||
|
}.map { (offset, schedulers) ->
|
||||||
|
CronDateTimeSchedulerTz(schedulers.flatMap { it.cronDateTimes }, offset)
|
||||||
|
}
|
@ -6,8 +6,3 @@ internal val dayOfMonthRange = 0 .. 30
|
|||||||
internal val hoursRange = 0 .. 23
|
internal val hoursRange = 0 .. 23
|
||||||
internal val minutesRange = 0 .. 59
|
internal val minutesRange = 0 .. 59
|
||||||
internal val secondsRange = minutesRange
|
internal val secondsRange = minutesRange
|
||||||
|
|
||||||
/**
|
|
||||||
* From 0 - 1439 minutes (1440 == 24 hours, that is the same as 0 in terms of timezones)
|
|
||||||
*/
|
|
||||||
internal val offsetRange = 0 until (hoursRange.count() * minutesRange.count())
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.krontab.utils
|
package dev.inmo.krontab.utils
|
||||||
|
|
||||||
import com.soywiz.klock.DateTimeTz
|
import com.soywiz.klock.DateTimeTz
|
||||||
|
import dev.inmo.krontab.KronSchedulerTz
|
||||||
import dev.inmo.krontab.buildSchedule
|
import dev.inmo.krontab.buildSchedule
|
||||||
import dev.inmo.krontab.internal.offsetRange
|
import dev.inmo.krontab.internal.offsetRange
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -84,9 +85,8 @@ class StringParseTest {
|
|||||||
|
|
||||||
runTest {
|
runTest {
|
||||||
for (i in offsetRange) {
|
for (i in offsetRange) {
|
||||||
val kronScheduler = buildSchedule("* * 10 * * ${i}o")
|
val kronScheduler = buildSchedule("* * 10 * * ${i}o") as KronSchedulerTz
|
||||||
val next = kronScheduler.next(now)
|
val next = kronScheduler.next(now)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package dev.inmo.krontab.utils
|
|||||||
|
|
||||||
import com.soywiz.klock.*
|
import com.soywiz.klock.*
|
||||||
import dev.inmo.krontab.builder.buildSchedule
|
import dev.inmo.krontab.builder.buildSchedule
|
||||||
|
import dev.inmo.krontab.next
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user