Skip to content

Commit 5c4ef08

Browse files
committed
Filtered RDATE and EXDATE from exceptions
1 parent 8481c39 commit 5c4ef08

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

lib/src/main/kotlin/at/bitfire/ical4android/validation/EventValidator.kt

+8-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package at.bitfire.ical4android.validation
66

77
import androidx.annotation.VisibleForTesting
88
import at.bitfire.ical4android.Event
9-
import at.bitfire.ical4android.Ical4Android
109
import at.bitfire.ical4android.util.DateUtils
1110
import at.bitfire.ical4android.util.TimeApiExtensions.toIcal4jDate
1211
import at.bitfire.ical4android.util.TimeApiExtensions.toLocalDate
@@ -47,7 +46,7 @@ object EventValidator {
4746
val dtStart = correctStartAndEndTime(event)
4847
sameTypeForDtStartAndRruleUntil(dtStart, event.rRules)
4948
removeRRulesWithUntilBeforeDtStart(dtStart, event.rRules)
50-
removeRRulesOfExceptions(event.exceptions)
49+
removeRecurrenceOfExceptions(event.exceptions)
5150
}
5251

5352

@@ -169,15 +168,19 @@ object EventValidator {
169168

170169

171170
/**
172-
* Removes RRULEs of exceptions of (potentially recurring) events
171+
* Removes all recurrence information of exceptions of (potentially recurring) events. This is:
172+
* `RRULE`, `RDATE` and `EXDATE`.
173173
* Note: This repair step needs to be applied after all exceptions have been found
174174
*
175175
* @param exceptions exceptions of an event
176176
*/
177177
@VisibleForTesting
178-
internal fun removeRRulesOfExceptions(exceptions: List<Event>) {
179-
for (exception in exceptions)
178+
internal fun removeRecurrenceOfExceptions(exceptions: List<Event>) {
179+
for (exception in exceptions) {
180180
exception.rRules.clear() // Drop all RRULEs for the exception
181+
exception.rDates.clear() // Drop all RDATEs for the exception
182+
exception.exDates.clear() // Drop all EXDATEs for the exception
183+
}
181184
}
182185

183186

lib/src/test/kotlin/at/bitfire/ical4android/validation/EventValidatorTest.kt

+49-4
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,23 @@ package at.bitfire.ical4android.validation
77
import at.bitfire.ical4android.Event
88
import at.bitfire.ical4android.util.DateUtils
99
import net.fortuna.ical4j.model.Date
10+
import net.fortuna.ical4j.model.DateList
1011
import net.fortuna.ical4j.model.DateTime
12+
import net.fortuna.ical4j.model.Property
13+
import net.fortuna.ical4j.model.PropertyList
1114
import net.fortuna.ical4j.model.Recur
15+
import net.fortuna.ical4j.model.TimeZone
1216
import net.fortuna.ical4j.model.TimeZoneRegistry
1317
import net.fortuna.ical4j.model.TimeZoneRegistryFactory
18+
import net.fortuna.ical4j.model.component.VTimeZone
19+
import net.fortuna.ical4j.model.parameter.Value
1420
import net.fortuna.ical4j.model.property.DtEnd
1521
import net.fortuna.ical4j.model.property.DtStart
22+
import net.fortuna.ical4j.model.property.ExDate
23+
import net.fortuna.ical4j.model.property.RDate
1624
import net.fortuna.ical4j.model.property.RRule
1725
import net.fortuna.ical4j.model.property.RecurrenceId
26+
import net.fortuna.ical4j.model.property.TzId
1827
import org.junit.Assert.assertArrayEquals
1928
import org.junit.Assert.assertEquals
2029
import org.junit.Assert.assertFalse
@@ -394,14 +403,48 @@ class EventValidatorTest {
394403
.interval(2)
395404
.build())
396405
))
406+
rDates.addAll(listOf(
407+
RDate(DateList(Value("19970714T123000Z"))),
408+
RDate(
409+
DateList(
410+
Value("19960403T020000Z"),
411+
TimeZone(
412+
VTimeZone(
413+
PropertyList<Property>(1).apply {
414+
add(TzId("US-EASTERN"))
415+
}
416+
)
417+
)
418+
)
419+
)
420+
))
421+
exDates.addAll(listOf(
422+
ExDate(DateList(Value("19970714T123000Z"))),
423+
ExDate(
424+
DateList(
425+
Value("19960403T020000Z"),
426+
TimeZone(
427+
VTimeZone(
428+
PropertyList<Property>(1).apply {
429+
add(TzId("US-EASTERN"))
430+
}
431+
)
432+
)
433+
)
434+
)
435+
))
397436
uid = "76c08fb1-99a3-41cf-b482-2d3b06648814"
398437
})
399438
}
400439
assertTrue(manualEvent.rRules.size == 1)
401-
assertTrue(manualEvent.exceptions.first.rRules.size == 2)
402-
EventValidator.removeRRulesOfExceptions(manualEvent.exceptions) // Repair the manually created event
440+
assertTrue(manualEvent.exceptions.first().rRules.size == 2)
441+
assertTrue(manualEvent.exceptions.first().rDates.size == 2)
442+
assertTrue(manualEvent.exceptions.first().exDates.size == 2)
443+
EventValidator.removeRecurrenceOfExceptions(manualEvent.exceptions) // Repair the manually created event
403444
assertTrue(manualEvent.rRules.size == 1)
404-
assertTrue(manualEvent.exceptions.first.rRules.isEmpty())
445+
assertTrue(manualEvent.exceptions.first().rRules.isEmpty())
446+
assertTrue(manualEvent.exceptions.first().rDates.isEmpty())
447+
assertTrue(manualEvent.exceptions.first().exDates.isEmpty())
405448

406449
// Test event from reader, the reader will repair the event itself
407450
val eventFromReader = Event.eventsFromReader(StringReader(
@@ -422,14 +465,16 @@ class EventValidatorTest {
422465
"SUMMARY:exception of recurring event\n" +
423466
"RRULE:FREQ=DAILY;COUNT=6;INTERVAL=2\n" + // but remove this one
424467
"RRULE:FREQ=DAILY;COUNT=6;INTERVAL=2\n" + // and this one
468+
"EXDATE;TZID=Europe/Paris:20240704T193000\n" + // also this
469+
"RDATE;TZID=US-EASTERN:19970714T083000\n" + // and this
425470
"DTSTART;TZID=Europe/Paris:20240221T110000\n" +
426471
"DTEND;TZID=Europe/Paris:20240221T120000\n" +
427472
"UID:76c08fb1-99a3-41cf-b482-2d3b06648814\n" +
428473
"END:VEVENT\n" +
429474
"END:VCALENDAR"
430475
)).first()
431476
assertTrue(eventFromReader.rRules.size == 1)
432-
assertTrue(eventFromReader.exceptions.first.rRules.isEmpty())
477+
assertTrue(eventFromReader.exceptions.first().rRules.isEmpty())
433478
}
434479

435480
@Test

0 commit comments

Comments
 (0)