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) {
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<Int> {
val reminders = ArrayList<Int>()
val uri = CalendarContract.Reminders.CONTENT_URI

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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"
}
}