From 3d2ba4d0efad51f66d99c12701ac4be8c43ed5fa Mon Sep 17 00:00:00 2001 From: tibbi Date: Wed, 16 Aug 2017 22:34:18 +0200 Subject: [PATCH] properly handle multiple days lasting all-day events at caldav --- .../calendar/helpers/CalDAVEventsHandler.kt | 16 +++- .../calendar/helpers/IcsExporter.kt | 4 +- .../calendar/helpers/IcsImporter.kt | 4 +- .../calendar/helpers/Parser.kt | 81 ++++++++----------- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVEventsHandler.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVEventsHandler.kt index 5715fe97c..37d1e1262 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVEventsHandler.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVEventsHandler.kt @@ -85,7 +85,7 @@ class CalDAVEventsHandler(val context: Context) { if (endTS == 0) { val duration = cursor.getStringValue(CalendarContract.Events.DURATION) - endTS = startTS + Parser().parseDuration(duration) + endTS = startTS + Parser().parseDurationSeconds(duration) } val importId = getCalDAVEventImportId(calendarId, id) @@ -120,7 +120,6 @@ class CalDAVEventsHandler(val context: Context) { } fun addCalDAVEvent(event: Event, calendarId: Long) { - val durationMinutes = (event.endTS - event.startTS) / 1000 / 60 val uri = CalendarContract.Events.CONTENT_URI val values = ContentValues().apply { put(CalendarContract.Events.CALENDAR_ID, calendarId) @@ -128,14 +127,14 @@ class CalDAVEventsHandler(val context: Context) { put(CalendarContract.Events.DESCRIPTION, event.description) put(CalendarContract.Events.DTSTART, event.startTS * 1000L) put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0) - put(CalendarContract.Events.RRULE, Parser().getShortRepeatInterval(event)) + put(CalendarContract.Events.RRULE, Parser().getRepeatCode(event)) put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString()) if (event.getIsAllDay() && event.endTS > event.startTS) event.endTS += DAY if (event.repeatInterval > 0) { - put(CalendarContract.Events.DURATION, Parser().getDurationString(durationMinutes)) + put(CalendarContract.Events.DURATION, getDurationCode(event)) } else { put(CalendarContract.Events.DTEND, event.endTS * 1000L) } @@ -148,6 +147,15 @@ class CalDAVEventsHandler(val context: Context) { context.dbHelper.updateEventImportIdAndSource(event.id, importId, "$CALDAV-$calendarId") } + private fun getDurationCode(event: Event): String { + return if (event.getIsAllDay()) { + val dur = Math.max(1, (event.endTS - event.startTS) / DAY) + "P${dur}D" + } else { + Parser().getDurationCode((event.endTS - event.startTS) / 60) + } + } + fun getCalDAVEventReminders(eventId: Long): List { val reminders = ArrayList() val uri = CalendarContract.Reminders.CONTENT_URI diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsExporter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsExporter.kt index 845155f9a..d64b69e3b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsExporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsExporter.kt @@ -38,7 +38,7 @@ class IcsExporter { } out.writeLn("$STATUS$CONFIRMED") - Parser().getShortRepeatInterval(event).let { if (it.isNotEmpty()) out.writeLn("$RRULE$it") } + Parser().getRepeatCode(event).let { if (it.isNotEmpty()) out.writeLn("$RRULE$it") } fillReminders(event, out) fillIgnoredOccurrences(event, out) @@ -69,7 +69,7 @@ class IcsExporter { if (minutes != -1) { out.writeLn(BEGIN_ALARM) out.writeLn("$ACTION$DISPLAY") - out.writeLn("$TRIGGER${Parser().getDurationString(minutes)}") + out.writeLn("$TRIGGER-${Parser().getDurationCode(minutes)}") out.writeLn(END_ALARM) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsImporter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsImporter.kt index bcf56ab54..16341a4ae 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/IcsImporter.kt @@ -63,7 +63,7 @@ class IcsImporter { curEnd = getTimestamp(line.substring(DTEND.length)) } else if (line.startsWith(DURATION)) { val duration = line.substring(DURATION.length) - curEnd = curStart + Parser().parseDuration(duration) + curEnd = curStart + Parser().parseDurationSeconds(duration) } else if (line.startsWith(SUMMARY) && !isNotificationDescription) { curTitle = line.substring(SUMMARY.length) curTitle = getTitle(curTitle).replace("\\n", "\n") @@ -81,7 +81,7 @@ class IcsImporter { lastReminderAction = line.substring(ACTION.length) } else if (line.startsWith(TRIGGER)) { if (lastReminderAction == DISPLAY) - curReminderMinutes.add(Parser().parseDuration(line.substring(TRIGGER.length)) / 60) + curReminderMinutes.add(Parser().parseDurationSeconds(line.substring(TRIGGER.length)) / 60) } else if (line.startsWith(CATEGORIES)) { val categories = line.substring(CATEGORIES.length) tryAddCategories(categories, context) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Parser.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Parser.kt index a71d506cd..d78a5f61a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Parser.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Parser.kt @@ -50,14 +50,12 @@ class Parser { return RepeatRule(repeatInterval, repeatRule, repeatLimit) } - private fun getFrequencySeconds(interval: String): Int { - return when (interval) { - DAILY -> DAY - WEEKLY -> WEEK - MONTHLY -> MONTH - YEARLY -> YEAR - else -> 0 - } + private fun getFrequencySeconds(interval: String) = when (interval) { + DAILY -> DAY + WEEKLY -> WEEK + MONTHLY -> MONTH + YEARLY -> YEAR + else -> 0 } private fun handleRepeatRule(value: String): Int { @@ -96,7 +94,7 @@ class Parser { } // from Daily, 5x... to RRULE:FREQ=DAILY;COUNT=5 - fun getShortRepeatInterval(event: Event): String { + fun getRepeatCode(event: Event): String { val repeatInterval = event.repeatInterval if (repeatInterval == 0) return "" @@ -108,35 +106,24 @@ class Parser { return "$FREQ=$freq;$INTERVAL=$interval$repeatLimit$byDay" } - private fun getFreq(interval: Int): String { - return if (interval % YEAR == 0) - YEARLY - else if (interval % MONTH == 0) - MONTHLY - else if (interval % WEEK == 0) - WEEKLY - else - DAILY + private fun getFreq(interval: Int) = when { + interval % YEAR == 0 -> YEARLY + interval % MONTH == 0 -> MONTHLY + interval % WEEK == 0 -> WEEKLY + else -> DAILY } - private fun getInterval(interval: Int): Int { - return if (interval % YEAR == 0) - interval / YEAR - else if (interval % MONTH == 0) - interval / MONTH - else if (interval % WEEK == 0) - interval / WEEK - else - interval / DAY + private fun getInterval(interval: Int) = when { + interval % YEAR == 0 -> interval / YEAR + interval % MONTH == 0 -> interval / MONTH + interval % WEEK == 0 -> interval / WEEK + else -> interval / DAY } - private fun getRepeatLimitString(event: Event): String { - return if (event.repeatLimit == 0) - "" - else if (event.repeatLimit < 0) - ";$COUNT=${-event.repeatLimit}" - else - ";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}" + private fun getRepeatLimitString(event: Event) = when { + event.repeatLimit == 0 -> "" + event.repeatLimit < 0 -> ";$COUNT=${-event.repeatLimit}" + else -> ";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}" } private fun getByDay(event: Event): String { @@ -179,22 +166,20 @@ class Parser { return result.trimEnd(',') } - private fun getDayLetters(dayOfWeek: Int): String { - return when (dayOfWeek) { - 1 -> MO - 2 -> TU - 3 -> WE - 4 -> TH - 5 -> FR - 6 -> SA - else -> SU - } + private fun getDayLetters(dayOfWeek: Int) = when (dayOfWeek) { + 1 -> MO + 2 -> TU + 3 -> WE + 4 -> TH + 5 -> FR + 6 -> SA + else -> SU } // from P0DT1H5M0S to 3900 (seconds) - fun parseDuration(duration: String): Int { + fun parseDurationSeconds(duration: String): Int { val weeks = getDurationValue(duration, "W") - val days = getDurationValue(duration, "DT") + val days = getDurationValue(duration, "D") val hours = getDurationValue(duration, "H") val minutes = getDurationValue(duration, "M") val seconds = getDurationValue(duration, "S") @@ -210,7 +195,7 @@ class Parser { private fun getDurationValue(duration: String, char: String) = Regex("[0-9]+(?=$char)").find(duration)?.value?.toInt() ?: 0 // from 65 to P0DT1H5M0S - fun getDurationString(minutes: Int): String { + fun getDurationCode(minutes: Int): String { var days = 0 var hours = 0 var remainder = minutes @@ -222,6 +207,6 @@ class Parser { hours = Math.floor((remainder / 60).toDouble()).toInt() remainder -= hours * 60 } - return "-P${days}DT${hours}H${remainder}M0S" + return "P${days}DT${hours}H${remainder}M0S" } }