rewrite mechanism of calculating of near time

This commit is contained in:
InsanusMokrassar 2021-05-30 17:15:32 +06:00
parent 22ef00fe8f
commit 28f84d4e3a
12 changed files with 371 additions and 139 deletions

View File

@ -3,7 +3,9 @@
## 0.6.1 ## 0.6.1
* Versions * Versions
* `Klock`: `2.1.0` -> `2.1.2` * `Klock`: `2.1.0` -> `2.1.2
`
## 0.6.0 ## 0.6.0

View File

@ -16,13 +16,13 @@ fun Iterator<KronScheduler>.merge(): CollectionKronScheduler {
val collectionScheduler = CollectionKronScheduler() val collectionScheduler = CollectionKronScheduler()
forEach { forEach {
when (it) { when (it) {
is CronDateTimeScheduler -> cronDateTimes.addAll(it.cronDateTimes) is CronDateTimeScheduler -> cronDateTimes.add(it.cronDateTime)
is CronDateTimeSchedulerTz -> timezonedCronDateTimes.add(it) 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.merge()))
} }
if (timezonedCronDateTimes.isNotEmpty()) { if (timezonedCronDateTimes.isNotEmpty()) {
collectionScheduler.includeAll(mergeCronDateTimeSchedulers(timezonedCronDateTimes)) collectionScheduler.includeAll(mergeCronDateTimeSchedulers(timezonedCronDateTimes))

View File

@ -13,7 +13,7 @@ internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(r
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] * [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now]
*/ */
val AnyTimeScheduler: KronScheduler by lazy { val AnyTimeScheduler: KronScheduler by lazy {
CronDateTimeScheduler(listOf(anyCronDateTime)) CronDateTimeScheduler(anyCronDateTime)
} }
/** /**

View File

@ -116,7 +116,7 @@ fun createSimpleScheduler(
scheduler scheduler
} else { } else {
CronDateTimeSchedulerTz( CronDateTimeSchedulerTz(
(scheduler as CronDateTimeScheduler).cronDateTimes, (scheduler as CronDateTimeScheduler).cronDateTime,
TimezoneOffset(defaultOffset.minutes) TimezoneOffset(defaultOffset.minutes)
) )
} }

View File

@ -38,16 +38,16 @@ data class CollectionKronScheduler internal constructor(
) )
} }
is CronDateTimeSchedulerTz -> { is CronDateTimeSchedulerTz -> {
val newCronDateTimes = kronScheduler.cronDateTimes.toMutableList() val newCronDateTimes = mutableListOf(kronScheduler.cronDateTime)
val cronDateTimes = schedulers.removeAll { schedulers.removeAll {
if (it is CronDateTimeSchedulerTz && it.offset == kronScheduler.offset) { if (it is CronDateTimeSchedulerTz && it.offset == kronScheduler.offset) {
newCronDateTimes.addAll(it.cronDateTimes) newCronDateTimes.add(it.cronDateTime)
true true
} else { } else {
false false
} }
} }
schedulers.add(CronDateTimeSchedulerTz(newCronDateTimes.toList(), kronScheduler.offset)) schedulers.add(CronDateTimeSchedulerTz(newCronDateTimes.merge(), kronScheduler.offset))
} }
is CollectionKronScheduler -> kronScheduler.schedulers.forEach { is CollectionKronScheduler -> kronScheduler.schedulers.forEach {
include(it) include(it)

View File

@ -4,103 +4,125 @@ import com.soywiz.klock.*
import dev.inmo.krontab.KronScheduler import dev.inmo.krontab.KronScheduler
/** /**
* @param dayOfweek 0-6 * @param daysOfWeek 0-6
* @param year any int * @param years any int
* @param month 0-11 * @param months 0-11
* @param dayOfMonth 0-31 * @param daysOfMonth 0-31
* @param hours 0-23 * @param hours 0-23
* @param minutes 0-59 * @param minutes 0-59
* @param seconds 0-59 * @param seconds 0-59
*/ */
internal data class CronDateTime( internal data class CronDateTime(
val dayOfweek: Byte? = null, val daysOfWeek: Array<Byte>? = null,
val year: Int? = null, val years: Array<Int>? = null,
val month: Byte? = null, val months: Array<Byte>? = null,
val dayOfMonth: Byte? = null, val daysOfMonth: Array<Byte>? = null,
val hours: Byte? = null, val hours: Array<Byte>? = null,
val minutes: Byte? = null, val minutes: Array<Byte>? = null,
val seconds: Byte? = null val seconds: Array<Byte>? = null
) { ) {
init { init {
check(dayOfweek ?.let { it in dayOfWeekRange } ?: true) check(daysOfWeek ?.all { it in dayOfWeekRange } ?: true)
check(year ?.let { it in yearRange } ?: true) check(years?.all { it in yearRange } ?: true)
check(month ?.let { it in monthRange } ?: true) check(months?.all { it in monthRange } ?: true)
check(dayOfMonth ?.let { it in dayOfMonthRange } ?: true) check(daysOfMonth ?.all { it in dayOfMonthRange } ?: true)
check(hours?.let { it in hoursRange } ?: true) check(hours?.all { it in hoursRange } ?: true)
check(minutes?.let { it in minutesRange } ?: true) check(minutes?.all { it in minutesRange } ?: true)
check(seconds?.let { it in secondsRange } ?: true) check(seconds?.all { it in secondsRange } ?: true)
} }
internal val klockDayOfMonth = dayOfMonth ?.plus(1) internal val calculators = listOf(
internal val dayOfWeekInt: Int? = dayOfweek ?.toInt() NearDateTimeCalculatorMillis(arrayOf(0)),
} seconds ?.let { NearDateTimeCalculatorSeconds(it) },
minutes ?.let { NearDateTimeCalculatorMinutes(it) },
hours ?.let { NearDateTimeCalculatorHours(it) },
daysOfMonth ?.let { NearDateTimeCalculatorDays(it) },
months ?.let { NearDateTimeCalculatorMonths(it) },
years ?.let { NearDateTimeCalculatorYears(it) },
daysOfWeek ?.let { NearDateTimeCalculatorWeekDays(it) },
)
/** internal fun toNearDateTime(relativelyTo: DateTime = DateTime.now()): DateTime? {
* THIS METHOD WILL <b>NOT</b> 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: DateTime = DateTime.now()): DateTime? {
var current = relativelyTo var current = relativelyTo
whileLoop@while (true) {
val weekDay = dayOfWeekInt for (calculator in calculators) {
if (weekDay != null && current.dayOfWeek.index0 != weekDay) { val (calculated, requireRecalculation) = (calculator ?: continue).calculateNearTime(current) ?: return null
do { current = calculated
var diff = weekDay - current.dayOfWeek.index0 if (requireRecalculation) {
if (diff < 0) { continue@whileLoop
diff += 7 /* days in week */
}
current = (current + diff.days).startOfDay
val next = toNearDateTime(current)
if (next == null || next.dayOfWeek.index0 == weekDay) {
return next
}
} while (true)
}
seconds?.let {
val left = it - current.seconds
current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left)
}
minutes?.let {
val left = it - current.minutes
current += DateTimeSpan(hours = if (left < 0) 1 else 0, minutes = left)
}
hours?.let {
val left = it - current.hours
current += DateTimeSpan(days = if (left < 0) 1 else 0, hours = left)
}
klockDayOfMonth ?.let {
val left = (it - current.dayOfMonth).let { diff ->
if (diff > 0 && current.endOfMonth.run { it > dayOfMonth && current.dayOfMonth == dayOfMonth }) {
0
} else {
diff
} }
} }
current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left)
}
month ?.let {
val left = it - current.month0
current += DateTimeSpan(years = if (left < 0) 1 else 0, months = left)
}
year ?.let {
if (current.yearInt != it) {
return null
}
}
return current return current
} }
}
}
//
///**
// * THIS METHOD WILL <b>NOT</b> 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: DateTime = DateTime.now()): DateTime? {
// 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 == null || next.dayOfWeek.index0 == weekDay) {
// return next
// }
// } while (true)
// }
//
// seconds?.let {
// val left = it - current.seconds
// current += DateTimeSpan(minutes = if (left <= 0) 1 else 0, seconds = left)
// }
//
// minutes?.let {
// val left = it - current.minutes
// current += DateTimeSpan(hours = if (left < 0) 1 else 0, minutes = left)
// }
//
// hours?.let {
// val left = it - current.hours
// current += DateTimeSpan(days = if (left < 0) 1 else 0, hours = left)
// }
//
// klockDayOfMonth ?.let {
// val left = (it - current.dayOfMonth).let { diff ->
// if (diff > 0 && current.endOfMonth.run { it > dayOfMonth && current.dayOfMonth == dayOfMonth }) {
// 0
// } else {
// diff
// }
// }
// current += DateTimeSpan(months = if (left < 0) 1 else 0, days = left)
// }
//
// months?.let {
// val left = it - current.month0
// current += DateTimeSpan(years = if (left < 0) 1 else 0, months = left)
// }
//
// years?.let {
// if (current.yearInt != it) {
// return null
// }
// }
//
// return current
//}
internal fun createCronDateTimeList( internal fun createCronDateTime(
seconds: Array<Byte>? = null, seconds: Array<Byte>? = null,
minutes: Array<Byte>? = null, minutes: Array<Byte>? = null,
hours: Array<Byte>? = null, hours: Array<Byte>? = null,
@ -108,38 +130,39 @@ internal fun createCronDateTimeList(
month: Array<Byte>? = null, month: Array<Byte>? = null,
years: Array<Int>? = null, years: Array<Int>? = null,
weekDays: Array<Byte>? = null weekDays: Array<Byte>? = null
): List<CronDateTime> { ): CronDateTime {
val resultCronDateTimes = mutableListOf(CronDateTime()) return CronDateTime(weekDays, years, month, dayOfMonth, hours, minutes, seconds)
// val resultCronDateTimes = mutableListOf(CronDateTime())
seconds ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(seconds = currentTime) // seconds ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(seconds = currentTime)
// }
minutes ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(minutes = currentTime) // minutes ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(minutes = currentTime)
// }
hours ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(hours = currentTime) // hours ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(hours = currentTime)
// }
dayOfMonth ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(dayOfMonth = currentTime) // dayOfMonth ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(daysOfMonth = currentTime)
// }
month ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(month = currentTime) // month ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(months = currentTime)
// }
years ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Int -> //
previousCronDateTime.copy(year = currentTime) // years ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Int ->
} // previousCronDateTime.copy(years = currentTime)
// }
weekDays ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> //
previousCronDateTime.copy(dayOfweek = currentTime) // weekDays ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte ->
} // previousCronDateTime.copy(daysOfWeek = currentTime)
// }
return resultCronDateTimes.toList() //
// return resultCronDateTimes.toList()
} }
/** /**
@ -153,7 +176,7 @@ internal fun createKronScheduler(
month: Array<Byte>? = null, month: Array<Byte>? = null,
years: Array<Int>? = null, years: Array<Int>? = null,
weekDays: Array<Byte>? = null weekDays: Array<Byte>? = null
): KronScheduler = CronDateTimeScheduler(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years, weekDays)) ): KronScheduler = CronDateTimeScheduler(createCronDateTime(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
*/ */
@ -166,4 +189,14 @@ internal fun createKronSchedulerWithOffset(
years: Array<Int>? = null, years: Array<Int>? = null,
weekDays: Array<Byte>? = null, weekDays: Array<Byte>? = null,
offset: TimezoneOffset offset: TimezoneOffset
): KronScheduler = CronDateTimeSchedulerTz(createCronDateTimeList(seconds, minutes, hours, dayOfMonth, month, years, weekDays), offset) ): KronScheduler = CronDateTimeSchedulerTz(createCronDateTime(seconds, minutes, hours, dayOfMonth, month, years, weekDays), 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() },
)

View File

@ -19,7 +19,7 @@ import dev.inmo.krontab.collection.plus
* @see dev.inmo.krontab.builder.SchedulerBuilder * @see dev.inmo.krontab.builder.SchedulerBuilder
*/ */
internal data class CronDateTimeScheduler internal constructor( internal data class CronDateTimeScheduler internal constructor(
internal val cronDateTimes: List<CronDateTime> internal val cronDateTime: CronDateTime
) : KronScheduler { ) : KronScheduler {
/** /**
* @return Near date using [cronDateTimes] list and getting the [Iterable.minByOrNull] one * @return Near date using [cronDateTimes] list and getting the [Iterable.minByOrNull] one
@ -27,12 +27,14 @@ internal data class CronDateTimeScheduler internal constructor(
* @see toNearDateTime * @see toNearDateTime
*/ */
override suspend fun next(relatively: DateTime): DateTime? { override suspend fun next(relatively: DateTime): DateTime? {
return cronDateTimes.mapNotNull { it.toNearDateTime(relatively) }.minOrNull() return cronDateTime.toNearDateTime(relatively)
} }
} }
internal fun mergeCronDateTimeSchedulers(schedulers: List<CronDateTimeScheduler>) = CronDateTimeScheduler( internal fun mergeCronDateTimeSchedulers(
schedulers.flatMap { it.cronDateTimes } schedulers: List<CronDateTimeScheduler>
): CronDateTimeScheduler = CronDateTimeScheduler(
schedulers.map { it.cronDateTime }.merge()
) )
/** /**

View File

@ -11,14 +11,12 @@ import dev.inmo.krontab.KronSchedulerTz
* @see CronDateTime * @see CronDateTime
*/ */
internal data class CronDateTimeSchedulerTz internal constructor( internal data class CronDateTimeSchedulerTz internal constructor(
internal val cronDateTimes: List<CronDateTime>, internal val cronDateTime: CronDateTime,
internal val offset: TimezoneOffset internal val offset: TimezoneOffset
) : KronSchedulerTz { ) : KronSchedulerTz {
override suspend fun next(relatively: DateTimeTz): DateTimeTz? { override suspend fun next(relatively: DateTimeTz): DateTimeTz? {
val dateTimeWithActualOffset = relatively.toOffset(offset).local val dateTimeWithActualOffset = relatively.toOffset(offset).local
return cronDateTimes.mapNotNull { return cronDateTime.toNearDateTime(dateTimeWithActualOffset) ?.toOffsetUnadjusted(offset) ?.toOffset(relatively.offset)
it.toNearDateTime(dateTimeWithActualOffset)
}.minOrNull() ?.toOffsetUnadjusted(offset) ?.toOffset(relatively.offset)
} }
} }
@ -27,5 +25,8 @@ internal fun mergeCronDateTimeSchedulers(
) = schedulers.groupBy { ) = schedulers.groupBy {
it.offset it.offset
}.map { (offset, schedulers) -> }.map { (offset, schedulers) ->
CronDateTimeSchedulerTz(schedulers.flatMap { it.cronDateTimes }, offset) CronDateTimeSchedulerTz(
schedulers.map { it.cronDateTime }.merge(),
offset
)
} }

View File

@ -0,0 +1,171 @@
package dev.inmo.krontab.internal
import com.soywiz.klock.*
import dev.inmo.krontab.utils.copy
import kotlin.math.min
internal class NearDateTimeCalculator<T>(
private val times: Array<T>,
private val partGetter: (DateTime) -> T,
private val partSetter: (DateTime, T) -> DateTime?
) where T : Comparable<T>, T : Number {
/**
* @return pair of near [DateTime] for this checker and [Boolean] flag that all previous calculations must be
* recalculated
*/
fun calculateNearTime(
relativelyTo: DateTime
): Pair<DateTime, Boolean>? {
val currentData = partGetter(relativelyTo)
val greaterOrEquals = times.firstOrNull { it >= currentData }
val newDateTime = if (greaterOrEquals == null) {
partSetter(relativelyTo, times.first()) ?: return null
} else {
partSetter(relativelyTo, greaterOrEquals) ?: return null
}
return if (newDateTime == relativelyTo) {
relativelyTo to false
} else {
newDateTime to true
}
}
}
internal fun NearDateTimeCalculatorMillis(
times: Array<Short>
) = NearDateTimeCalculator(
times,
{ it.milliseconds.toShort() },
{ dateTime, newOne ->
(if (newOne < dateTime.milliseconds) {
dateTime.plus(1.seconds)
} else {
dateTime
}).copy(milliseconds = newOne.toInt())
}
)
internal fun NearDateTimeCalculatorSeconds(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.seconds.toByte() },
{ dateTime, newOne ->
(if (newOne < dateTime.seconds) {
dateTime.plus(1.minutes)
} else {
dateTime
}).copy(second = newOne.toInt(), milliseconds = 0)
}
)
internal fun NearDateTimeCalculatorMinutes(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.minutes.toByte() },
{ dateTime, newOne ->
(if (newOne < dateTime.minutes) {
dateTime.plus(1.hours)
} else {
dateTime
}).copy(minute = newOne.toInt(), second = 0, milliseconds = 0)
}
)
internal fun NearDateTimeCalculatorHours(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.hours.toByte() },
{ dateTime, newOne ->
(if (newOne < dateTime.hours) {
dateTime.plus(1.days)
} else {
dateTime
}).copy(hour = newOne.toInt(), minute = 0, second = 0, milliseconds = 0)
}
)
internal fun NearDateTimeCalculatorDays(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.dayOfMonth.toByte() },
{ dateTime, newOne ->
(if (newOne < dateTime.dayOfMonth) {
dateTime.plus(1.months)
} else {
dateTime
}).copy(
dayOfMonth = min(dateTime.month.days(dateTime.year), newOne.toInt() + 1), // index1
hour = 0,
minute = 0,
second = 0,
milliseconds = 0
)
}
)
internal fun NearDateTimeCalculatorMonths(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.dayOfMonth.toByte() },
{ dateTime, newOne ->
(if (newOne < dateTime.month0) {
dateTime.plus(1.years)
} else {
dateTime
}).copy(
month = newOne.toInt() + 1, // index1
dayOfMonth = 1, // index1
hour = 0,
minute = 0,
second = 0,
milliseconds = 0
)
}
)
internal fun NearDateTimeCalculatorWeekDays(
times: Array<Byte>
) = NearDateTimeCalculator(
times,
{ it.dayOfWeek.index0.toByte() },
{ dateTime, newOne ->
val currentDayOfWeek = dateTime.dayOfWeek.index0
(if (newOne < currentDayOfWeek) {
dateTime.plus(7.days - (currentDayOfWeek - newOne).days)
} else {
dateTime.plus(newOne.toInt().days - currentDayOfWeek.days)
}).copy(
hour = 0,
minute = 0,
second = 0,
milliseconds = 0
)
}
)
internal fun NearDateTimeCalculatorYears(
times: Array<Int>
) = NearDateTimeCalculator(
times,
{ it.yearInt },
{ dateTime, newOne ->
val currentYear = dateTime.yearInt
(if (newOne < currentYear) {
null
} else {
dateTime.plus(newOne.years - currentYear.years)
}) ?.copy(
month = 1, // index1
dayOfMonth = 1, // index1
hour = 0,
minute = 0,
second = 0,
milliseconds = 0
)
}
)

View File

@ -8,7 +8,7 @@ private fun <T> createSimpleScheduler(from: String, dataRange: IntRange, dataCon
val things = from.split(",") val things = from.split(",")
val results = things.flatMap { val results = things.flatMap {
val currentToken = it.toLowerCase().replace( val currentToken = it.lowercase().replace(
"f", dataRange.first.toString() "f", dataRange.first.toString()
).replace( ).replace(
"l", dataRange.last.toString() "l", dataRange.last.toString()

View File

@ -0,0 +1,22 @@
package dev.inmo.krontab.utils
import com.soywiz.klock.*
import kotlin.math.min
fun DateTime.copy(
year: Int = yearInt,
month: Int = month1,
dayOfMonth: Int = this.dayOfMonth,
hour: Int = hours,
minute: Int = minutes,
second: Int = seconds,
milliseconds: Int = this.milliseconds
) = DateTime(
year,
month,
min(Month(month).days(yearInt), dayOfMonth),
hour,
minute,
second,
milliseconds
)

View File

@ -10,7 +10,8 @@ class TimeZoneTest {
@Test @Test
fun testDifferentTimeZonesReturnsDifferentTimes() { fun testDifferentTimeZonesReturnsDifferentTimes() {
val scheduler = buildSchedule { seconds { every(1) } } val scheduler = buildSchedule { seconds { every(1) } }
val baseDate = DateTime.now().startOfWeek val additionalMilliseconds = 100.milliseconds
val baseDate = DateTime.now().startOfWeek.copy(milliseconds = additionalMilliseconds.millisecondsInt)
runTest { runTest {
for (i in 0 until 7) { for (i in 0 until 7) {
val now = baseDate + i.days val now = baseDate + i.days
@ -18,7 +19,7 @@ class TimeZoneTest {
val nowTz = now.toOffset(j.hours) val nowTz = now.toOffset(j.hours)
val next = scheduler.next(nowTz)!! val next = scheduler.next(nowTz)!!
assertEquals( assertEquals(
(nowTz + 1.seconds).utc.unixMillisLong, next.utc.unixMillisLong (nowTz + 1.seconds - additionalMilliseconds).utc.unixMillisLong, next.utc.unixMillisLong
) )
} }
} }