feat(caldav): return proper caldav intervals instead of FREQ=SECONDLY (#1230)

This commit is contained in:
kolaente
2025-08-04 13:41:28 +02:00
committed by GitHub
parent fd771e2b7d
commit 0a44f53759
3 changed files with 67 additions and 2 deletions

View File

@@ -104,6 +104,28 @@ func formatDuration(duration time.Duration) string {
strconv.FormatFloat(seconds, 'f', 0, 64) + `S`
}
func getRruleFromInterval(interval int64) (freq string, newInterval int64) {
const (
minute = 60
hour = minute * 60
day = hour * 24
week = day * 7
)
switch {
case interval%week == 0:
return "WEEKLY", interval / week
case interval%day == 0:
return "DAILY", interval / day
case interval%hour == 0:
return "HOURLY", interval / hour
case interval%minute == 0:
return "MINUTELY", interval / minute
default:
return "SECONDLY", interval
}
}
// ParseTodos returns a caldav vcalendar string with todos
func ParseTodos(config *Config, todos []*Todo) (caldavtodos string) {
caldavtodos = `BEGIN:VCALENDAR
@@ -172,8 +194,9 @@ PRIORITY:` + strconv.Itoa(mapPriorityToCaldav(t.Priority))
caldavtodos += `
RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02") // Day of the month
} else {
freq, interval := getRruleFromInterval(t.RepeatAfter)
caldavtodos += `
RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10)
RRULE:FREQ=` + freq + `;INTERVAL=` + strconv.FormatInt(interval, 10)
}
}

View File

@@ -578,7 +578,7 @@ STATUS:COMPLETED
DUE:20181201T011202Z
CREATED:20181201T011201Z
PRIORITY:3
RRULE:FREQ=SECONDLY;INTERVAL=86400
RRULE:FREQ=DAILY;INTERVAL=1
CATEGORIES:label1,label2
LAST-MODIFIED:20181201T011205Z
BEGIN:VALARM

42
pkg/caldav/repeat_test.go Normal file
View File

@@ -0,0 +1,42 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package caldav
import "testing"
func Test_getRruleFromInterval(t *testing.T) {
tests := []struct {
name string
interval int64
wantFreq string
wantInterval int64
}{
{"seconds", 435, "SECONDLY", 435},
{"minutes", 120, "MINUTELY", 2},
{"hours", 7200, "HOURLY", 2},
{"daily", 86400, "DAILY", 1},
{"weekly", 1209600, "WEEKLY", 2},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotFreq, gotInterval := getRruleFromInterval(tt.interval)
if gotFreq != tt.wantFreq || gotInterval != tt.wantInterval {
t.Errorf("getRruleFromInterval() = %s,%d; want %s,%d", gotFreq, gotInterval, tt.wantFreq, tt.wantInterval)
}
})
}
}