diff --git a/CHANGELOG.md b/CHANGELOG.md index 73a6fc1f1..7bfc75952 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed event text readability on colored backgrounds ([#1065]) - Fixed invisible current time indicator in weekly view ([#99]) - Fixed stuck zoom level in weekly view on some devices ([#621]) +- Fixed recurring events drifting by an hour after DST transitions ([#165]) ## [1.10.3] - 2026-02-14 ### Changed @@ -217,6 +218,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#135]: https://github.com/FossifyOrg/Calendar/issues/135 [#138]: https://github.com/FossifyOrg/Calendar/issues/138 [#148]: https://github.com/FossifyOrg/Calendar/issues/148 +[#165]: https://github.com/FossifyOrg/Calendar/issues/165 [#196]: https://github.com/FossifyOrg/Calendar/issues/196 [#217]: https://github.com/FossifyOrg/Calendar/issues/217 [#262]: https://github.com/FossifyOrg/Calendar/issues/262 diff --git a/app/src/main/kotlin/org/fossify/calendar/models/Event.kt b/app/src/main/kotlin/org/fossify/calendar/models/Event.kt index 74312ff04..8654c9b57 100644 --- a/app/src/main/kotlin/org/fossify/calendar/models/Event.kt +++ b/app/src/main/kotlin/org/fossify/calendar/models/Event.kt @@ -2,6 +2,7 @@ package org.fossify.calendar.models import android.provider.CalendarContract import android.provider.CalendarContract.Attendees +import android.util.Log import androidx.collection.LongSparseArray import androidx.room.ColumnInfo import androidx.room.Entity @@ -74,7 +75,7 @@ data class Event( } fun addIntervalTime(original: Event) { - val oldStart = Formatter.getDateTimeFromTS(startTS) + val oldStart = Formatter.getDateTimeFromTS(startTS, resolveTimeZone()) val newStart = when (repeatInterval) { DAY -> oldStart.plusDays(1) else -> { @@ -109,6 +110,20 @@ data class Event( endTS = newEndTS } + // Returns the event's time zone, or the device default if unset or unrecognized. + private fun resolveTimeZone(): DateTimeZone { + return if (timeZone.isNotEmpty()) { + try { + DateTimeZone.forID(timeZone) + } catch (e: IllegalArgumentException) { + Log.w("Event", "Unrecognized timezone '$timeZone', using default", e) + DateTimeZone.getDefault() + } + } else { + DateTimeZone.getDefault() + } + } + // if an event should happen on 29th Feb. with Same Day yearly repetition, show it only on leap years private fun addYearsWithSameDay(currStart: DateTime): DateTime { var newDateTime = currStart.plusYears(repeatInterval / YEAR)