I think this problem is related to https://forums.bitfire.at/topic/192/provide-workaround-for-incomplete-android-exdate-support/2.
Coarse description
Recurring events with EXDATEs are not correctly synced to my Android device.
Effect is, that all occurrences are shown, regardless the exceptional state.
Workaround I found: Marking a single occurrence as “CANCELED” results in the correct sync of other deleted occurrences.
The “CANCELED”-State can thereafter easily be removed and everything is fine. Even further deletions (of occurrences of the same event) are now synced correctly. I suppose the additional VEVENT block changes the sync behavior in some way.
Log
Step 1: 1.calendar.txt (Part of DAVDroids’ Log):
Syncing recurring event with one EXDATE.
[…]
[trace] BEGIN:VEVENT
[trace] CREATED:20151125T182649Z
[trace] LAST-MODIFIED:20151125T182840Z
[trace] DTSTAMP:20151125T182840Z
[trace] UID:ee95ba33-35b8-463b-b1fa-4a0c0dbee13e
[trace] SUMMARY:Test-Event
[trace] RRULE:FREQ=DAILY;UNTIL=20151127T190000Z
[trace] EXDATE:20151125T190000Z
[trace] DTSTART;TZID=Europe/Berlin:20151123T200000
[trace] DTEND;TZID=Europe/Berlin:20151123T210000
[trace] TRANSP:OPAQUE
[trace] X-MOZ-GENERATION:3
[trace] SEQUENCE:2
[trace] END:VEVENT
[…]
Export after sync: 1.ics
No EXDATE.
[…]
BEGIN:VEVENT
DTSTAMP:20151125T183015Z
UID:ee95ba33-35b8-463b-b1fa-4a0c0dbee13e
SUMMARY:Test-Event
ORGANIZER:mailto:test
DTSTART;TZID=Europe/Berlin:20151123T200000
DURATION:PT1H
RRULE:FREQ=DAILY;UNTIL=20151127T190000Z
END:VEVENT
[…]
Step 2: 2.calendar.txt:
Syncing an other occurrence marked as “CANCELED” (of the same recurring event!).
[…]
[trace] BEGIN:VEVENT
[trace] CREATED:20151125T182649Z
[trace] LAST-MODIFIED:20151125T183026Z
[trace] DTSTAMP:20151125T183026Z
[trace] UID:ee95ba33-35b8-463b-b1fa-4a0c0dbee13e
[trace] SUMMARY:Test-Event
[trace] RRULE:FREQ=DAILY;UNTIL=20151127T190000Z
[trace] EXDATE:20151125T190000Z
[trace] DTSTART;TZID=Europe/Berlin:20151123T200000
[trace] DTEND;TZID=Europe/Berlin:20151123T210000
[trace] TRANSP:OPAQUE
[trace] X-MOZ-GENERATION:4
[trace] SEQUENCE:2
[trace] END:VEVENT
[trace] BEGIN:VEVENT
[trace] CREATED:20151125T182903Z
[trace] LAST-MODIFIED:20151125T183026Z
[trace] DTSTAMP:20151125T183026Z
[trace] UID:ee95ba33-35b8-463b-b1fa-4a0c0dbee13e
[trace] SUMMARY:Test-Event
[trace] STATUS:CANCELLED
[trace] RECURRENCE-ID;TZID=Europe/Berlin:20151124T200000
[trace] DTSTART;TZID=Europe/Berlin:20151124T200000
[trace] DTEND;TZID=Europe/Berlin:20151124T210000
[trace] TRANSP:OPAQUE
[trace] SEQUENCE:3
[trace] X-MOZ-GENERATION:4
[trace] END:VEVENT
[…]
Export after sync: 2.ics
EXDATE is now there (-> occurrence hidden). CANCELED occurrence is also hidden.
(BTW: My CANCELED occurrence is not in this .ics file?!)
[…]
BEGIN:VEVENT
DTSTAMP:20151125T183100Z
UID:ee95ba33-35b8-463b-b1fa-4a0c0dbee13e
SUMMARY:Test-Event
ORGANIZER:mailto:test
DTSTART;TZID=Europe/Berlin:20151123T200000
DURATION:PT1H
RRULE:FREQ=DAILY;UNTIL=20151127T190000Z
EXDATE:20151125T190000Z
END:VEVENT
[…]
See 3.ics and 3.calendar.filtered.txt for turning it from CANCELED to CONFIRMED.