Skip to content

Commit 363c9a1

Browse files
authored
Implement custom PulseSchedule.toString (#166)
Closes #165
1 parent 0eb015d commit 363c9a1

File tree

2 files changed

+97
-3
lines changed

2 files changed

+97
-3
lines changed

src/commonMain/kotlin/io/github/kevincianfarini/cardiologist/PulseSchedule.kt

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import kotlinx.datetime.number
1111
* A [Pulse] schedule that can be used with [schedulePulse] to define complex schedules.
1212
*/
1313
@Poko
14-
public class PulseSchedule internal constructor(
14+
public class PulseSchedule private constructor(
1515
public val atSeconds: List<Int>,
1616
public val atMinutes: List<Int>,
1717
public val atHours: List<Int>,
@@ -58,6 +58,57 @@ public class PulseSchedule internal constructor(
5858
// expressions.
5959
}
6060

61+
override fun toString(): String = buildString {
62+
append("PulseSchedule{atSeconds=[")
63+
appendRanges(atSeconds) { it }
64+
append("], atMinutes=[")
65+
appendRanges(atMinutes) { it }
66+
append("], atHours=[")
67+
appendRanges(atHours) { it }
68+
append("], onDaysOfMonth=[")
69+
appendRanges(onDaysOfMonth) { it }
70+
append("], inMonths=[")
71+
appendRanges(inMonths, Enum<*>::ordinal)
72+
if (onDaysOfWeek.isNotEmpty()) {
73+
append("], onDaysOfWeek=[")
74+
appendRanges(onDaysOfWeek, Enum<*>::ordinal)
75+
}
76+
append("]}")
77+
}
78+
79+
private fun <T : Any> StringBuilder.appendRanges(elements: Collection<T>, value: (T) -> Int) {
80+
val iterator = elements.iterator()
81+
82+
// All collections are guaranteed to be non-empty.
83+
val first = iterator.next()
84+
var startValue = value(first)
85+
append(first)
86+
87+
var last = first
88+
var lastValue = startValue
89+
while (iterator.hasNext()) {
90+
val current = iterator.next()
91+
val currentValue = value(current)
92+
if (currentValue != lastValue + 1) {
93+
if (lastValue > startValue) {
94+
append('-')
95+
append(last)
96+
}
97+
append(", ")
98+
append(current)
99+
100+
startValue = currentValue
101+
}
102+
last = current
103+
lastValue = currentValue
104+
}
105+
106+
if (lastValue > startValue) {
107+
append('-')
108+
append(last)
109+
}
110+
}
111+
61112
public companion object {
62113
/**
63114
* Parse a cron [expression] into a [PulseSchedule].
@@ -332,4 +383,4 @@ private fun MutableSet<DayOfWeek>.addAllDaysOfWeek(range: ClosedRange<DayOfWeek>
332383
*/
333384
public fun buildPulseSchedule(builder: PulseScheduleBuilder.() -> Unit): PulseSchedule {
334385
return PulseScheduleBuilder().apply(builder).build()
335-
}
386+
}

src/commonTest/kotlin/io/github/kevincianfarini/cardiologist/PulseScheduleTest.kt

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import kotlinx.datetime.Month
44
import kotlin.test.Test
55
import kotlin.test.assertEquals
66
import kotlin.test.assertFails
7+
import kotlinx.datetime.DayOfWeek
78

89
class PulseScheduleTest {
910

@@ -168,4 +169,46 @@ class PulseScheduleTest {
168169
actual = e.message,
169170
)
170171
}
171-
}
172+
173+
@Test
174+
fun toStrings() {
175+
// Minimal elements.
176+
assertEquals(
177+
"PulseSchedule{atSeconds=[0], atMinutes=[0], atHours=[0], onDaysOfMonth=[1], inMonths=[JANUARY]}",
178+
PulseSchedule(
179+
atSeconds = setOf(0),
180+
atMinutes = setOf(0),
181+
atHours = setOf(0),
182+
onDaysOfMonth = setOf(1),
183+
inMonths = setOf(Month.JANUARY),
184+
onDaysOfWeek = emptySet(),
185+
).toString(),
186+
)
187+
188+
// Multi-element ranges, two-element ranges, individual elements.
189+
assertEquals(
190+
"PulseSchedule{atSeconds=[0-2, 4-5, 7], atMinutes=[0, 2-3, 5-7], atHours=[0-2, 4-5, 7], onDaysOfMonth=[1, 3-4, 6-8], inMonths=[JANUARY, MARCH-APRIL, JUNE-AUGUST], onDaysOfWeek=[MONDAY-WEDNESDAY, FRIDAY]}",
191+
PulseSchedule(
192+
atSeconds = setOf(0, 1, 2, 4, 5, 7),
193+
atMinutes = setOf(0, 2, 3, 5, 6, 7),
194+
atHours = setOf(0, 1, 2, 4, 5, 7),
195+
onDaysOfMonth = setOf(1, 3, 4, 6, 7, 8),
196+
inMonths = setOf(Month.JANUARY, Month.MARCH, Month.APRIL, Month.JUNE, Month.JULY, Month.AUGUST),
197+
onDaysOfWeek = setOf(DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY),
198+
).toString(),
199+
)
200+
201+
// Full element ranges.
202+
assertEquals(
203+
"PulseSchedule{atSeconds=[0-59], atMinutes=[0-59], atHours=[0-23], onDaysOfMonth=[1-31], inMonths=[JANUARY-DECEMBER], onDaysOfWeek=[MONDAY-SUNDAY]}",
204+
PulseSchedule(
205+
atSeconds = (0..59).toSet(),
206+
atMinutes = (0..59).toSet(),
207+
atHours = (0..23).toSet(),
208+
onDaysOfMonth = (1..31).toSet(),
209+
inMonths = Month.entries.toSet(),
210+
onDaysOfWeek = DayOfWeek.entries.toSet(),
211+
).toString(),
212+
)
213+
}
214+
}

0 commit comments

Comments
 (0)