properly handle multiple days lasting all-day events at caldav

This commit is contained in:
tibbi 2017-08-16 22:34:18 +02:00
parent 8f0c8f6018
commit 3d2ba4d0ef
4 changed files with 49 additions and 56 deletions

View File

@ -85,7 +85,7 @@ class CalDAVEventsHandler(val context: Context) {
if (endTS == 0) { if (endTS == 0) {
val duration = cursor.getStringValue(CalendarContract.Events.DURATION) val duration = cursor.getStringValue(CalendarContract.Events.DURATION)
endTS = startTS + Parser().parseDuration(duration) endTS = startTS + Parser().parseDurationSeconds(duration)
} }
val importId = getCalDAVEventImportId(calendarId, id) val importId = getCalDAVEventImportId(calendarId, id)
@ -120,7 +120,6 @@ class CalDAVEventsHandler(val context: Context) {
} }
fun addCalDAVEvent(event: Event, calendarId: Long) { fun addCalDAVEvent(event: Event, calendarId: Long) {
val durationMinutes = (event.endTS - event.startTS) / 1000 / 60
val uri = CalendarContract.Events.CONTENT_URI val uri = CalendarContract.Events.CONTENT_URI
val values = ContentValues().apply { val values = ContentValues().apply {
put(CalendarContract.Events.CALENDAR_ID, calendarId) put(CalendarContract.Events.CALENDAR_ID, calendarId)
@ -128,14 +127,14 @@ class CalDAVEventsHandler(val context: Context) {
put(CalendarContract.Events.DESCRIPTION, event.description) put(CalendarContract.Events.DESCRIPTION, event.description)
put(CalendarContract.Events.DTSTART, event.startTS * 1000L) put(CalendarContract.Events.DTSTART, event.startTS * 1000L)
put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0) 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()) put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().toString())
if (event.getIsAllDay() && event.endTS > event.startTS) if (event.getIsAllDay() && event.endTS > event.startTS)
event.endTS += DAY event.endTS += DAY
if (event.repeatInterval > 0) { if (event.repeatInterval > 0) {
put(CalendarContract.Events.DURATION, Parser().getDurationString(durationMinutes)) put(CalendarContract.Events.DURATION, getDurationCode(event))
} else { } else {
put(CalendarContract.Events.DTEND, event.endTS * 1000L) put(CalendarContract.Events.DTEND, event.endTS * 1000L)
} }
@ -148,6 +147,15 @@ class CalDAVEventsHandler(val context: Context) {
context.dbHelper.updateEventImportIdAndSource(event.id, importId, "$CALDAV-$calendarId") 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<Int> { fun getCalDAVEventReminders(eventId: Long): List<Int> {
val reminders = ArrayList<Int>() val reminders = ArrayList<Int>()
val uri = CalendarContract.Reminders.CONTENT_URI val uri = CalendarContract.Reminders.CONTENT_URI

View File

@ -38,7 +38,7 @@ class IcsExporter {
} }
out.writeLn("$STATUS$CONFIRMED") 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) fillReminders(event, out)
fillIgnoredOccurrences(event, out) fillIgnoredOccurrences(event, out)
@ -69,7 +69,7 @@ class IcsExporter {
if (minutes != -1) { if (minutes != -1) {
out.writeLn(BEGIN_ALARM) out.writeLn(BEGIN_ALARM)
out.writeLn("$ACTION$DISPLAY") out.writeLn("$ACTION$DISPLAY")
out.writeLn("$TRIGGER${Parser().getDurationString(minutes)}") out.writeLn("$TRIGGER-${Parser().getDurationCode(minutes)}")
out.writeLn(END_ALARM) out.writeLn(END_ALARM)
} }
} }

View File

@ -63,7 +63,7 @@ class IcsImporter {
curEnd = getTimestamp(line.substring(DTEND.length)) curEnd = getTimestamp(line.substring(DTEND.length))
} else if (line.startsWith(DURATION)) { } else if (line.startsWith(DURATION)) {
val duration = line.substring(DURATION.length) val duration = line.substring(DURATION.length)
curEnd = curStart + Parser().parseDuration(duration) curEnd = curStart + Parser().parseDurationSeconds(duration)
} else if (line.startsWith(SUMMARY) && !isNotificationDescription) { } else if (line.startsWith(SUMMARY) && !isNotificationDescription) {
curTitle = line.substring(SUMMARY.length) curTitle = line.substring(SUMMARY.length)
curTitle = getTitle(curTitle).replace("\\n", "\n") curTitle = getTitle(curTitle).replace("\\n", "\n")
@ -81,7 +81,7 @@ class IcsImporter {
lastReminderAction = line.substring(ACTION.length) lastReminderAction = line.substring(ACTION.length)
} else if (line.startsWith(TRIGGER)) { } else if (line.startsWith(TRIGGER)) {
if (lastReminderAction == DISPLAY) 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)) { } else if (line.startsWith(CATEGORIES)) {
val categories = line.substring(CATEGORIES.length) val categories = line.substring(CATEGORIES.length)
tryAddCategories(categories, context) tryAddCategories(categories, context)

View File

@ -50,14 +50,12 @@ class Parser {
return RepeatRule(repeatInterval, repeatRule, repeatLimit) return RepeatRule(repeatInterval, repeatRule, repeatLimit)
} }
private fun getFrequencySeconds(interval: String): Int { private fun getFrequencySeconds(interval: String) = when (interval) {
return when (interval) { DAILY -> DAY
DAILY -> DAY WEEKLY -> WEEK
WEEKLY -> WEEK MONTHLY -> MONTH
MONTHLY -> MONTH YEARLY -> YEAR
YEARLY -> YEAR else -> 0
else -> 0
}
} }
private fun handleRepeatRule(value: String): Int { private fun handleRepeatRule(value: String): Int {
@ -96,7 +94,7 @@ class Parser {
} }
// from Daily, 5x... to RRULE:FREQ=DAILY;COUNT=5 // from Daily, 5x... to RRULE:FREQ=DAILY;COUNT=5
fun getShortRepeatInterval(event: Event): String { fun getRepeatCode(event: Event): String {
val repeatInterval = event.repeatInterval val repeatInterval = event.repeatInterval
if (repeatInterval == 0) if (repeatInterval == 0)
return "" return ""
@ -108,35 +106,24 @@ class Parser {
return "$FREQ=$freq;$INTERVAL=$interval$repeatLimit$byDay" return "$FREQ=$freq;$INTERVAL=$interval$repeatLimit$byDay"
} }
private fun getFreq(interval: Int): String { private fun getFreq(interval: Int) = when {
return if (interval % YEAR == 0) interval % YEAR == 0 -> YEARLY
YEARLY interval % MONTH == 0 -> MONTHLY
else if (interval % MONTH == 0) interval % WEEK == 0 -> WEEKLY
MONTHLY else -> DAILY
else if (interval % WEEK == 0)
WEEKLY
else
DAILY
} }
private fun getInterval(interval: Int): Int { private fun getInterval(interval: Int) = when {
return if (interval % YEAR == 0) interval % YEAR == 0 -> interval / YEAR
interval / YEAR interval % MONTH == 0 -> interval / MONTH
else if (interval % MONTH == 0) interval % WEEK == 0 -> interval / WEEK
interval / MONTH else -> interval / DAY
else if (interval % WEEK == 0)
interval / WEEK
else
interval / DAY
} }
private fun getRepeatLimitString(event: Event): String { private fun getRepeatLimitString(event: Event) = when {
return if (event.repeatLimit == 0) event.repeatLimit == 0 -> ""
"" event.repeatLimit < 0 -> ";$COUNT=${-event.repeatLimit}"
else if (event.repeatLimit < 0) else -> ";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}"
";$COUNT=${-event.repeatLimit}"
else
";$UNTIL=${Formatter.getDayCodeFromTS(event.repeatLimit)}"
} }
private fun getByDay(event: Event): String { private fun getByDay(event: Event): String {
@ -179,22 +166,20 @@ class Parser {
return result.trimEnd(',') return result.trimEnd(',')
} }
private fun getDayLetters(dayOfWeek: Int): String { private fun getDayLetters(dayOfWeek: Int) = when (dayOfWeek) {
return when (dayOfWeek) { 1 -> MO
1 -> MO 2 -> TU
2 -> TU 3 -> WE
3 -> WE 4 -> TH
4 -> TH 5 -> FR
5 -> FR 6 -> SA
6 -> SA else -> SU
else -> SU
}
} }
// from P0DT1H5M0S to 3900 (seconds) // from P0DT1H5M0S to 3900 (seconds)
fun parseDuration(duration: String): Int { fun parseDurationSeconds(duration: String): Int {
val weeks = getDurationValue(duration, "W") val weeks = getDurationValue(duration, "W")
val days = getDurationValue(duration, "DT") val days = getDurationValue(duration, "D")
val hours = getDurationValue(duration, "H") val hours = getDurationValue(duration, "H")
val minutes = getDurationValue(duration, "M") val minutes = getDurationValue(duration, "M")
val seconds = getDurationValue(duration, "S") 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 private fun getDurationValue(duration: String, char: String) = Regex("[0-9]+(?=$char)").find(duration)?.value?.toInt() ?: 0
// from 65 to P0DT1H5M0S // from 65 to P0DT1H5M0S
fun getDurationString(minutes: Int): String { fun getDurationCode(minutes: Int): String {
var days = 0 var days = 0
var hours = 0 var hours = 0
var remainder = minutes var remainder = minutes
@ -222,6 +207,6 @@ class Parser {
hours = Math.floor((remainder / 60).toDouble()).toInt() hours = Math.floor((remainder / 60).toDouble()).toInt()
remainder -= hours * 60 remainder -= hours * 60
} }
return "-P${days}DT${hours}H${remainder}M0S" return "P${days}DT${hours}H${remainder}M0S"
} }
} }