Skip to content

Commit

Permalink
Fix calculation of events repeating every X weeks
Browse files Browse the repository at this point in the history
The previous implementation was broken in some time zones (see FossifyOrg#408
for details).

The new implementation hard-codes the start of the week to be Monday
to match the previous behaviour. Ideally this should be configurable
(see the comments in the code for more notes).

Fixes FossifyOrg#408.
  • Loading branch information
tom93 committed Jan 18, 2025
1 parent e1f575a commit 530e145
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions app/src/main/kotlin/org/fossify/calendar/models/Event.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import org.fossify.calendar.extensions.seconds
import org.fossify.calendar.helpers.*
import org.fossify.commons.extensions.addBitIf
import org.joda.time.DateTime
import org.joda.time.DateTimeConstants
import org.joda.time.DateTimeZone
import org.joda.time.Weeks
import java.io.Serializable

@Entity(tableName = "events", indices = [(Index(value = ["id"], unique = true))])
Expand Down Expand Up @@ -176,11 +178,22 @@ data class Event(
fun getCalDAVCalendarId() = if (source.startsWith(CALDAV)) (source.split("-").lastOrNull() ?: "0").toString().toInt() else 0

// check if it's the proper week, for events repeating every x weeks
// get the week number since 1970, not just in the current year
fun isOnProperWeek(startTimes: LongSparseArray<Long>): Boolean {
val initialWeekNumber = Formatter.getDateTimeFromTS(startTimes[id!!]!!).withTimeAtStartOfDay().millis / (7 * 24 * 60 * 60 * 1000f)
val currentWeekNumber = Formatter.getDateTimeFromTS(startTS).withTimeAtStartOfDay().millis / (7 * 24 * 60 * 60 * 1000f)
return (Math.round(initialWeekNumber) - Math.round(currentWeekNumber)) % (repeatInterval / WEEK) == 0
// Note that the code below hard-codes the start of the week to be Monday. This affects events that repeat on
// multiple days of the week. Ideally this should be configurable; but doing it properly will require some work.
// For example, Google Calendar uses the value of the "Start of the week" setting at the time the event is
// created/edited (critically, changing the setting does not affect existing events). That seems like the best
// approach. Implementing this would require adding a (hidden) start-of-week field to events (corresponding to
// iCal's WKST rule).
if (repeatInterval == WEEK) {
return true // optimization for events that repeat every week
}
val initialDate = Formatter.getDateFromTS(startTimes[id!!]!!)
val daysSinceWeekStart = Math.floorMod(initialDate.getDayOfWeek() - DateTimeConstants.MONDAY, 7)
val initialWeekStart = initialDate.minusDays(daysSinceWeekStart)
val currentDate = Formatter.getDateFromTS(startTS)
val weeks = Weeks.weeksBetween(initialWeekStart, currentDate).weeks
return weeks % (repeatInterval / WEEK) == 0
}

fun updateIsPastEvent() {
Expand Down

0 comments on commit 530e145

Please sign in to comment.