diff --git a/CHANGELOG.md b/CHANGELOG.md index 08ceae5..ed65b2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.7.3 + +* Versions + * `Kotlin`: `1.6.21` +* Several bug fixes ([#27](https://github.com/InsanusMokrassar/krontab/issues/27), [#34](https://github.com/InsanusMokrassar/krontab/issues/34)) +* New factories for `KronScheduler` and `KronSchedulerTz` (fix of [#35](https://github.com/InsanusMokrassar/krontab/issues/35)) +* Fill extensions for flow with time zones (fix of [#33](https://github.com/InsanusMokrassar/krontab/issues/33)) + ## 0.7.2 * Versions diff --git a/gradle.properties b/gradle.properties index 5eb2793..9c92126 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,10 +8,10 @@ android.useAndroidX=true android.enableJetifier=false -kotlin_version=1.6.10 +kotlin_version=1.6.21 kotlin_coroutines_version=1.6.1 -dokka_version=1.6.10 +dokka_version=1.6.21 klockVersion=2.7.0 @@ -33,5 +33,5 @@ androidx_work_version=2.7.1 ## Common -version=0.7.2 -android_code_version=13 +version=0.7.3 +android_code_version=14 diff --git a/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronScheduler.kt b/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronScheduler.kt new file mode 100644 index 0000000..5bef0a6 --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronScheduler.kt @@ -0,0 +1,13 @@ +package dev.inmo.krontab + +import com.soywiz.klock.DateTime + +class LambdaKronScheduler( + private val onNext: suspend (DateTime) -> DateTime? +) : KronScheduler { + override suspend fun next(relatively: DateTime): DateTime? = onNext(relatively) +} + +fun KronScheduler( + onNext: suspend (DateTime) -> DateTime? +) = LambdaKronScheduler(onNext) diff --git a/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronSchedulerTz.kt b/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronSchedulerTz.kt new file mode 100644 index 0000000..35327ed --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/krontab/LambdaKronSchedulerTz.kt @@ -0,0 +1,13 @@ +package dev.inmo.krontab + +import com.soywiz.klock.DateTimeTz + +class LambdaKronSchedulerTz( + private val onNext: suspend (DateTimeTz) -> DateTimeTz? +) : KronSchedulerTz { + override suspend fun next(relatively: DateTimeTz): DateTimeTz? = onNext(relatively) +} + +fun KronSchedulerTz( + onNext: suspend (DateTimeTz) -> DateTimeTz? +) = LambdaKronSchedulerTz(onNext) diff --git a/src/commonMain/kotlin/dev/inmo/krontab/StringParser.kt b/src/commonMain/kotlin/dev/inmo/krontab/StringParser.kt index 9e1e6da..1a3b1e2 100644 --- a/src/commonMain/kotlin/dev/inmo/krontab/StringParser.kt +++ b/src/commonMain/kotlin/dev/inmo/krontab/StringParser.kt @@ -57,13 +57,13 @@ typealias KrontabTemplate = String * * "0/5,L * * * *" for every five seconds triggering and on 59 second * * "0/15 30 * * *" for every 15th seconds in a half of each hour * * "0/15 30 * * * 500ms" for every 15th seconds in a half of each hour when milliseconds equal to 500 - * * "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 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 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 - * * "1 2 3 F,4,L 5 2021 60o 0-2w 500ms" 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 when milliseconds will be equal to 500 + * * "1 2 3 F,4,L 5" for triggering in near first second of second minute of third hour of first, fifth and last days of may + * * "1 2 3 F,4,L 5 60o" for triggering in near first second of second minute of third hour of first, fifth and last days 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 first, fifth and last days 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 first, fifth and last days 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 first, fifth and last days 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 first, fifth and last days of may of 2021st year if it will be in Sunday-Tuesday week days with timezone UTC+01:00 + * * "1 2 3 F,4,L 5 2021 60o 0-2w 500ms" for triggering in near first second of second minute of third hour of first, fifth and last days of may of 2021st year if it will be in Sunday-Tuesday week days with timezone UTC+01:00 when milliseconds will be equal to 500 * * @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 diff --git a/src/commonMain/kotlin/dev/inmo/krontab/internal/CronDateTime.kt b/src/commonMain/kotlin/dev/inmo/krontab/internal/CronDateTime.kt index 729a784..a27e330 100644 --- a/src/commonMain/kotlin/dev/inmo/krontab/internal/CronDateTime.kt +++ b/src/commonMain/kotlin/dev/inmo/krontab/internal/CronDateTime.kt @@ -8,7 +8,7 @@ import dev.inmo.krontab.KronScheduler * @param daysOfWeek 0-6 * @param years any int * @param months 0-11 - * @param daysOfMonth 0-31 + * @param daysOfMonth 0-30 * @param hours 0-23 * @param minutes 0-59 * @param seconds 0-59 diff --git a/src/commonMain/kotlin/dev/inmo/krontab/internal/NearDateTimeCalculator.kt b/src/commonMain/kotlin/dev/inmo/krontab/internal/NearDateTimeCalculator.kt index 714a3f6..2e3576b 100644 --- a/src/commonMain/kotlin/dev/inmo/krontab/internal/NearDateTimeCalculator.kt +++ b/src/commonMain/kotlin/dev/inmo/krontab/internal/NearDateTimeCalculator.kt @@ -101,13 +101,14 @@ internal fun NearDateTimeCalculatorDays( times: Array ) = CommonNearDateTimeCalculator( times, - { it.dayOfMonth.toByte() }, + { (it.dayOfMonth - 1).toByte() }, // index1, so, decrease { dateTime, newOne -> - (if (newOne < dateTime.dayOfMonth) { + val dateTime = (if (newOne < dateTime.dayOfMonth) { dateTime.plus(1.months) } else { dateTime - }).copy( + }) + dateTime.copy( dayOfMonth = min(dateTime.month.days(dateTime.year), newOne.toInt() + 1), // index1 hour = 0, minute = 0, @@ -121,7 +122,7 @@ internal fun NearDateTimeCalculatorMonths( times: Array ) = CommonNearDateTimeCalculator( times, - { it.dayOfMonth.toByte() }, + { it.month0.toByte() }, { dateTime, newOne -> (if (newOne < dateTime.month0) { dateTime.plus(1.years) diff --git a/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/Filters.kt b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeFilters.kt similarity index 100% rename from src/commonMain/kotlin/dev/inmo/krontab/utils/flows/Filters.kt rename to src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeFilters.kt diff --git a/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeTzFilters.kt b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeTzFilters.kt new file mode 100644 index 0000000..e259ca0 --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeTzFilters.kt @@ -0,0 +1,34 @@ +package dev.inmo.krontab.utils.flows + +import com.soywiz.klock.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterSeconds(vararg seconds: Int) = filter { it.seconds in seconds } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterMinutes(vararg minutes: Int) = filter { it.minutes in minutes } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterHours(vararg hours: Int) = filter { it.hours in hours } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterDaysOfMonths(vararg daysOfMonths: Int) = filter { it.dayOfMonth in daysOfMonths } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterMonths(vararg months: Month) = filter { it.month in months } +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterMonths0(vararg months: Int) = filter { it.month0 in months } +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterMonths1(vararg months: Int) = filter { it.month1 in months } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterYears(year: Year) = filter { it.year == year } +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterYears(vararg years: Int) = filter { it.yearInt in years } + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterWeekDays(vararg weekDays: DayOfWeek) = filter { it.dayOfWeek in weekDays } +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.filterWeekDays(vararg weekDays: Int) = filter { it.dayOfWeekInt in weekDays } diff --git a/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/When.kt b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeTzWhen.kt similarity index 100% rename from src/commonMain/kotlin/dev/inmo/krontab/utils/flows/When.kt rename to src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeTzWhen.kt diff --git a/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeWhen.kt b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeWhen.kt new file mode 100644 index 0000000..9867254 --- /dev/null +++ b/src/commonMain/kotlin/dev/inmo/krontab/utils/flows/DateTimeWhen.kt @@ -0,0 +1,25 @@ +package dev.inmo.krontab.utils.flows + +import com.soywiz.klock.* +import kotlinx.coroutines.flow.Flow + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfMinutes() = filterSeconds(0) + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfHours() = filterMinutes(0).onlyStartsOfMinutes() + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfDays() = filterHours(0).onlyStartsOfHours() + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfMondays() = filterWeekDays(DayOfWeek.Monday).onlyStartsOfDays() + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfSundays() = filterWeekDays(DayOfWeek.Sunday).onlyStartsOfDays() + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfMonths() = filterDaysOfMonths(1).onlyStartsOfDays() + +@Suppress("NOTHING_TO_INLINE") +inline fun Flow.onlyStartsOfYears() = filterMonths(Month.January).onlyStartsOfMonths() diff --git a/src/commonTest/kotlin/dev/inmo/krontab/utils/CheckMonthsAndDaysCorrectWork.kt b/src/commonTest/kotlin/dev/inmo/krontab/utils/CheckMonthsAndDaysCorrectWork.kt new file mode 100644 index 0000000..60c7d03 --- /dev/null +++ b/src/commonTest/kotlin/dev/inmo/krontab/utils/CheckMonthsAndDaysCorrectWork.kt @@ -0,0 +1,22 @@ +package dev.inmo.krontab.utils + +import com.soywiz.klock.DateTime +import com.soywiz.klock.days +import dev.inmo.krontab.buildSchedule +import kotlin.test.* + +class CheckMonthsAndDaysCorrectWork { + @Test + fun checkMonthsAndDaysCorrectWork() { + val now = DateTime.now().startOfYear.startOfDay + for (i in 0 until now.year.days) { + val scheduleDateTime = (now + i.days) + runTest { + assertEquals( + scheduleDateTime, + buildSchedule("0 0 0 ${scheduleDateTime.dayOfMonth - 1} ${scheduleDateTime.month0}").next(now) + ) + } + } + } +}