Loading src/main/java/at/bitfire/ical4android/Event.kt +6 −2 Original line number Diff line number Diff line Loading @@ -221,8 +221,12 @@ class Event: ICalendar() { exception.dtEnd?.timeZone?.let(usedTimeZones::add) } // add VTIMEZONE components usedTimeZones.forEach { ical.components += it.vTimeZone } // add minified VTIMEZONE components usedTimeZones.forEach { val tz = it.vTimeZone dtStart?.let { minifyVTimeZone(tz, it.date) } ical.components += tz } CalendarOutputter(false).output(ical, os) } Loading src/main/java/at/bitfire/ical4android/ICalendar.kt +57 −2 Original line number Diff line number Diff line Loading @@ -12,10 +12,11 @@ import net.fortuna.ical4j.data.CalendarBuilder import net.fortuna.ical4j.data.CalendarParserFactory import net.fortuna.ical4j.data.ParserException import net.fortuna.ical4j.model.* import net.fortuna.ical4j.model.component.VAlarm import net.fortuna.ical4j.model.component.VTimeZone import net.fortuna.ical4j.model.Date import net.fortuna.ical4j.model.component.* import net.fortuna.ical4j.model.property.DateProperty import net.fortuna.ical4j.model.property.ProdId import net.fortuna.ical4j.model.property.TzUrl import net.fortuna.ical4j.util.Strings import java.io.StringReader import java.util.* Loading Loading @@ -60,6 +61,60 @@ open class ICalendar { fun isDateTime(date: DateProperty?) = date != null && date.date is DateTime /** * Minifies a VTIMEZONE so that only components after [start] are kept. * Doesn't return the smallest possible VTIMEZONE at the moment, but * reduces its size significantly. * * @param tz Time zone definition to minify. Attention: the observances of this object * will be modified! * @param start Start date for components */ fun minifyVTimeZone(tz: VTimeZone, start: Date) { // find latest matching STANDARD/DAYLIGHT component, // keep components at/after "start" val iter = tz.observances.iterator() var latestDaylight: Pair<Date, Observance>? = null var latestStandard: Pair<Date, Observance>? = null val keep = mutableSetOf<Observance>() while (iter.hasNext()) { val entry = iter.next() as Observance val latest = entry.getLatestOnset(start) if (latest == null /* observance begins after "start" */ || latest >= start /* observance has onsets at/after "start" */ ) { keep += entry continue } when (entry) { is Standard -> { if (latestStandard == null || latest.after(latestStandard.first)) latestStandard = Pair(latest, entry) } is Daylight -> { if (latestDaylight == null || latest.after(latestDaylight.first)) latestDaylight = Pair(latest, entry) } } } latestStandard?.second?.let { keep += it } latestDaylight?.second?.let { keep += it } // actually remove all observances that shall not be kept val iter2 = tz.observances.iterator() while (iter2.hasNext()) { val entry = iter2.next() as Observance if (!keep.contains(entry)) iter2.remove() } // remove TZURL tz.properties.filter { it is TzUrl }.forEach { tz.properties.remove(it) } } /** * Takes a string with a timezone definition and returns the time zone ID. * @param timezoneDef time zone definition (VCALENDAR with VTIMEZONE component) Loading Loading
src/main/java/at/bitfire/ical4android/Event.kt +6 −2 Original line number Diff line number Diff line Loading @@ -221,8 +221,12 @@ class Event: ICalendar() { exception.dtEnd?.timeZone?.let(usedTimeZones::add) } // add VTIMEZONE components usedTimeZones.forEach { ical.components += it.vTimeZone } // add minified VTIMEZONE components usedTimeZones.forEach { val tz = it.vTimeZone dtStart?.let { minifyVTimeZone(tz, it.date) } ical.components += tz } CalendarOutputter(false).output(ical, os) } Loading
src/main/java/at/bitfire/ical4android/ICalendar.kt +57 −2 Original line number Diff line number Diff line Loading @@ -12,10 +12,11 @@ import net.fortuna.ical4j.data.CalendarBuilder import net.fortuna.ical4j.data.CalendarParserFactory import net.fortuna.ical4j.data.ParserException import net.fortuna.ical4j.model.* import net.fortuna.ical4j.model.component.VAlarm import net.fortuna.ical4j.model.component.VTimeZone import net.fortuna.ical4j.model.Date import net.fortuna.ical4j.model.component.* import net.fortuna.ical4j.model.property.DateProperty import net.fortuna.ical4j.model.property.ProdId import net.fortuna.ical4j.model.property.TzUrl import net.fortuna.ical4j.util.Strings import java.io.StringReader import java.util.* Loading Loading @@ -60,6 +61,60 @@ open class ICalendar { fun isDateTime(date: DateProperty?) = date != null && date.date is DateTime /** * Minifies a VTIMEZONE so that only components after [start] are kept. * Doesn't return the smallest possible VTIMEZONE at the moment, but * reduces its size significantly. * * @param tz Time zone definition to minify. Attention: the observances of this object * will be modified! * @param start Start date for components */ fun minifyVTimeZone(tz: VTimeZone, start: Date) { // find latest matching STANDARD/DAYLIGHT component, // keep components at/after "start" val iter = tz.observances.iterator() var latestDaylight: Pair<Date, Observance>? = null var latestStandard: Pair<Date, Observance>? = null val keep = mutableSetOf<Observance>() while (iter.hasNext()) { val entry = iter.next() as Observance val latest = entry.getLatestOnset(start) if (latest == null /* observance begins after "start" */ || latest >= start /* observance has onsets at/after "start" */ ) { keep += entry continue } when (entry) { is Standard -> { if (latestStandard == null || latest.after(latestStandard.first)) latestStandard = Pair(latest, entry) } is Daylight -> { if (latestDaylight == null || latest.after(latestDaylight.first)) latestDaylight = Pair(latest, entry) } } } latestStandard?.second?.let { keep += it } latestDaylight?.second?.let { keep += it } // actually remove all observances that shall not be kept val iter2 = tz.observances.iterator() while (iter2.hasNext()) { val entry = iter2.next() as Observance if (!keep.contains(entry)) iter2.remove() } // remove TZURL tz.properties.filter { it is TzUrl }.forEach { tz.properties.remove(it) } } /** * Takes a string with a timezone definition and returns the time zone ID. * @param timezoneDef time zone definition (VCALENDAR with VTIMEZONE component) Loading