Skip to content

Fix/recurrence respect event timezone#1197

Open
kruggiero97 wants to merge 3 commits intoFossifyOrg:mainfrom
kruggiero97:fix/recurrence-respect-event-timezone
Open

Fix/recurrence respect event timezone#1197
kruggiero97 wants to merge 3 commits intoFossifyOrg:mainfrom
kruggiero97:fix/recurrence-respect-event-timezone

Conversation

@kruggiero97
Copy link
Copy Markdown

Type of change(s)

  • Bug fix
  • Feature / enhancement
  • Infrastructure / tooling (CI, build, deps, tests)
  • Documentation

What changed and why

Event.addIntervalTime now uses the event's stored timeZone for recurrence math, falling back to the device default if it's empty or not recognized.

addIntervalTime wasn't using the event's timeZone field at all, it was just defaulting to whatever zone the device was in. Once a recurring event crossed a DST boundary, every following occurrence drifted by an hour, i.e. an event created in ET but read in AST would display the right time before the DST transition and the wrong time after.

Tests performed

Built debug APK, installed on a phone in America/Puerto_Rico which doesn't observe DST. Verified against a real Outlook calendar synced to the device via the Outlook Android app.

# Source TZ Recurrence DST regime Result
1 Pacific Time Weekly US spring-forward (Mar 8 2026) Pass
2 W. Europe Time Weekly EU spring-forward (Mar 29 2026) Pass
3 Tokyo Standard Time Weekly None (Tokyo no DST) Pass *
4 AUS Eastern Time Weekly AU fall-back (Apr 5 2026) Pass *
5 Eastern Time Monthly on the 15th US spring-forward Pass
6 Eastern Time Yearly on Mar 20 (none, always EDT) Pass

For each test, occurrences before and after the DST boundary were verified against expected local times in AST. Detailed observed vs expected values posted in a follow-up comment.

* Notes for tests 3 and 4:
While testing, I noticed that for events with non-local source timezones, the calendar view places each occurrence on the source-timezone date rather than the device-local date. This affected the displayed dates in tests 3 and 4 (times were correct, dates were off). Confirmed the same date behavior in release 1.10.3, seems to be unrelated to this PR.

May also address #506, #535, and possibly #71/#262, but I haven't verified against those reporters reproduction steps.

Closes the following issue(s)

Checklist

  • I read the contribution guidelines.
  • I manually tested my changes on device/emulator (if applicable).
  • I updated the "Unreleased" section in CHANGELOG.md (if applicable).
  • I have self-reviewed my pull request (no typos, formatting errors, etc.).
  • I understand every change in this pull request.

addIntervalTime wasn't using the event's timeZone field at all, it
was just defaulting to whatever zone the device was in. Once a recurring
event crossed a DST boundary, every following occurrence drifted by an
hour, i.e. an event created in ET but read in AST would display the right
time before the DST transition and the wrong time after.

The fix reads the event's timeZone, falls back to the device default if
it's empty or Joda-Time doesn't recognize it, and passes the resolved
zone into Formatter.getDateTimeFromTS. Joda already does DST math
correctly.

Closes FossifyOrg#165
@kruggiero97 kruggiero97 requested a review from naveensingh as a code owner May 9, 2026 23:07
@kruggiero97
Copy link
Copy Markdown
Author

Test 1 Pacific Standard Time

Created recurring event:

  • Start 23Feb2026 at 9:00 AM Pacific Time (UTC-08:00)
    • Observe event on 02Mar2026 (before DST)
      • Expected 01:00 PM Atlantic Time (UTC-04:00)
      • Observed: 01:00 PM Atlantic Time (UTC-04:00)
        • Confirm behavior correct
    • Observe event on 09Mar2026 (after DST)
      • Expected 12:00 PM Atlantic Time (UTC-04:00)
      • Observed: 12:00 PM Atlantic Time (UTC-04:00)
        • Confirm behavior correct

Test 2 West Europe Standard Time

Created recurring event:

  • Start 24Mar2026 at 10:00 AM CET (UTC+01:00)
    • Observe event on 24Mar2026 (before DST)
      • Expected 05:00 AM Atlantic Time (UTC-04:00)
      • Observed: 05:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct
    • Observe event on 31Mar2026 (after DST)
      • Expected 04:00 AM Atlantic Time (UTC-04:00)
      • Observed: 04:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct

Test 3 Tokyo Standard Time

Created recurring event:

  • Start 02Mar2026 at 09:00 AM JST (UTC+09:00)
    • Tokyo never observes DST, so all occurrences should show identical AST display
    • Observe event on 01Mar2026
      • Expected 08:00 PM Atlantic Time (UTC-04:00) on 01Mar2026
      • Observed: 08:00 PM Atlantic Time (UTC-04:00) on 02Mar2026 Time shows correctly, but date is incorrect. Confirmed on latest release that this date issue is present. The date seems to anchor to the time zone where the event was created and doesn't take into account local time zone.
        • Confirm behavior correct
    • Observe event on 29Mar2026 (after both US and EU DST transitions, neither should affect a Tokyo event)
      • Expected 08:00 PM Atlantic Time (UTC-04:00) on 29Mar2026
      • Observed: 08:00 PM Atlantic Time (UTC-04:00) on 30Mar2026 Time shows correctly, but date is incorrect. Confirmed on latest release that this date issue is present. The date seems to anchor to the time zone where the event was created and doesn't take into account local time zone.
        • Confirm behavior correct

Test 4 AUS Eastern Standard Time

Created recurring event:

  • Start 01Apr2026 at 09:00 AM AEDT (UTC+11:00)
    • Australia transitions out of DST on 05Apr2026 (falling back, AEDT -> AEST)
    • Observe event on 31Mar2026 (before DST end, AEDT)
      • Expected 06:00 PM Atlantic Time (UTC-04:00) on 31Mar2026
      • Observed: 06:00 PM Atlantic Time (UTC-04:00) on 01Apr2026 Time shows correctly, but date is incorrect. Confirmed on latest release that this date issue is present. The date seems to anchor to the time zone where the event was created and doesn't take into account local time zone.
        • Confirm behavior correct
    • Observe event on 07Apr2026 (after DST end, AEST)
      • Expected 07:00 PM Atlantic Time (UTC-04:00) on 07Apr2026
      • Observed: 07:00 PM Atlantic Time (UTC-04:00) on 08Apr2026 Time shows correctly, but date is incorrect. Confirmed on latest release that this date issue is present. The date seems to anchor to the time zone where the event was created and doesn't take into account local time zone.
        • Confirm behavior correct

Test 5 Eastern Standard Time, Monthly Recurrence

Created recurring event:

  • Start 15Feb2026 at 09:00 AM EST (UTC-05:00), monthly on the 15th
    • Tests addMonthsWithSameDay code path
    • Observe event on 15Feb2026 (EST)
      • Expected 10:00 AM Atlantic Time (UTC-04:00)
      • Observed: 10:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct
    • Observe event on 15Mar2026 (EDT, after US DST transition)
      • Expected 09:00 AM Atlantic Time (UTC-04:00)
      • Observed: 09:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct

Test 6 Eastern Standard Time, Yearly Recurrence

Created recurring event:

  • Start 20Mar2026 at 09:00 AM EDT (UTC-04:00), yearly on March 20
    • Tests addYearsWithSameDay code path
    • Mar 20 always falls after US DST transition, so all occurrences should be in EDT
    • Observe event on 20Mar2026
      • Expected 09:00 AM Atlantic Time (UTC-04:00)
      • Observed: 09:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct
    • Observe event on 20Mar2027
      • Expected 09:00 AM Atlantic Time (UTC-04:00)
      • Observed: 09:00 AM Atlantic Time (UTC-04:00)
        • Confirm behavior correct

Verified across 6 source timezones (Pacific, Berlin, Tokyo, Sydney, Eastern monthly, Eastern yearly), 4 DST transitions (US spring-forward, EU spring-forward, Australia fall-back, none for Tokyo)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect handling of DST for reoccurring events

1 participant