fix(agenda): resolve all-day span days in UTC, not the device zone
Review follow-up. spanFirstDay/spanLastDay resolved every event in the device zone, but all-day events live at UTC midnights with an exclusive end — east of UTC (e.g. Europe/Berlin) that pushed spanLastDay onto the next day, so a single-day all-day event reported spansMultipleDays and leaked onto a second agenda day. Resolve all-day dates in UTC, matching the Week view and detail card. Adds eastern-zone regression tests that the prior UTC-only tests could not catch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,18 +9,27 @@ import kotlinx.datetime.plus
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
/** The first calendar day this event occupies, in [zone]. */
|
||||
/**
|
||||
* The zone the event's calendar dates live in. Timed events are resolved in the
|
||||
* device [zone]; all-day events live at UTC midnights with an exclusive end, so
|
||||
* resolving them anywhere but UTC shifts the boundaries — east of UTC that leaks
|
||||
* a one-day event onto its next day. Matches the Week view and detail card.
|
||||
*/
|
||||
private fun EventInstance.dateZone(zone: TimeZone): TimeZone =
|
||||
if (isAllDay) TimeZone.UTC else zone
|
||||
|
||||
/** The first calendar day this event occupies. */
|
||||
fun EventInstance.spanFirstDay(zone: TimeZone): LocalDate =
|
||||
start.toLocalDateTime(zone).date
|
||||
start.toLocalDateTime(dateZone(zone)).date
|
||||
|
||||
/**
|
||||
* The last calendar day this event actually occupies, in [zone]. An event ending
|
||||
* exactly at midnight (all-day events end at the exclusive next-midnight) does
|
||||
* not reach into that boundary day, so resolve the instant just before [end].
|
||||
* The last calendar day this event actually occupies. An event ending exactly at
|
||||
* midnight (all-day events end at the exclusive next-midnight) does not reach
|
||||
* into that boundary day, so resolve the instant just before [end].
|
||||
*/
|
||||
fun EventInstance.spanLastDay(zone: TimeZone): LocalDate {
|
||||
val lastInstant = if (end > start) end - 1.milliseconds else start
|
||||
return lastInstant.toLocalDateTime(zone).date
|
||||
return lastInstant.toLocalDateTime(dateZone(zone)).date
|
||||
}
|
||||
|
||||
/** Whether this event occupies more than one calendar day in [zone]. */
|
||||
|
||||
Reference in New Issue
Block a user