All-day events span multiple days after changing time zones
Checklist
- [x] I can reproduce the bug with the latest version given here.
- [x] I made sure that there are no existing issues - open or closed - to which I could contribute my information.
- [x] I made sure that there are no existing discussions - open or closed - to which I could contribute my information.
- [x] I have read the FAQs inside the app (Menu -> About -> FAQs) and my problem isn't listed.
- [x] I have taken the time to fill in all the required details. I understand that the bug report will be dismissed otherwise.
- [x] This issue contains only one bug.
- [x] I have read and understood the contribution guidelines.
Affected app version
1.6.1 now, but this has existed for many, many months. Unsure which version I noticed it.
Affected Android/Custom ROM version
LineageOS 22.2 / Android 15
Affected device model
Pixel 6a
How did you install the app?
F-Droid / IzzyOnDroid
Which calendar service or provider do you use, if any?
None
Which sync adapter app do you use for calendar synchronization, if any?
None
Steps to reproduce the bug
- Add an all-day event.
- Change your time zone in the android settings, or by physically traveling to a different time zone.
- Observe that your event now shows as occurring on multiple days.
Expected behavior
An all-day event placed on a date (say, May 20th) should appear on [May 20th] regardless of which time zone you're in or change to.
Actual behavior
As stated, changing the phone's time zone causes the event to span multiple days.
Screenshots/Screen recordings
No response
Additional information
I haven't looked through the code, but it almost seems like an "all-day" event is entered as beginning at 00:01 and ending at 23:59 on that particular day, or something like that. If true, this would cause the time to shift into the previous or next day when changing time zones.
Related: https://github.com/FossifyOrg/Calendar/issues/568
More details: Events created in time zone A seem to get "corrupted" if I travel to time zone B and then back to time zone A (yes, even after the return to the original time zone...). They appear as described above, on both the designated day and the day prior. In any events exhibiting this issue, if I export the events to a .ics file, the ICS data shows the INCORRECT time stamp (includes the prior day as well). In the app, all the views (monthly, weekly, event list, etc) indicate the event being on the INCORRECT dates. However, if I open the "Edit Event" view, it indicates the CORRECT dates. Tapping the check mark to save doesn't fix the issue.
I think the problem is caused by interpreting the date/time string in terms of the current (default) time zone. All-day events are sort of a special case, in that they don't really have a start and end TIME, but rather just start and end DATES. When a new event is created, the "event" object is created with a time zone (the current/default zone). The "all-day" option removes the user's ability to manipulate the time zone for that event. Therefore, we can reasonably assume that the assigned dates will be in reference to whatever the user perceives as "my current time." So, when calling the "Formatter.getDayCodeFromTS" function, we could pass it "event.timeZone" to make the date accurate. Currently, this function utilizes the event's timestamps (which were generated based on the user's original time zone), and the "default time zone" given by the OS. This mismatched combination is what causes the date errors. Passing event.timeZone as an argument will make the dates line up with whatever the user perceived as the correct dates when the event was created. I'm not great at using git or github, but I've made changes on a local copy of the code which fixes this. I'll try to pass it along somehow... more to follow.
I've spent two days scouring the code trying to fix this, but alas, I'm just a novice. Still, for someone who is familiar with this code, these ideas make sense to me:
- Split all-day events off into their own database / arraylist, then handle them separately, setting the start date and end date without respect to time zones, or only with respect to the origin time zone when the event was created.
- OR, edit the functions that determine how each event is displayed on each particular view. Something similar to this messy code:
val tz = try {
DateTimeZone.forID(event.timeZone)
} catch (ignored: IllegalArgumentException) {
DateTimeZone.getDefault()
}
val tempstartdaycode = Formatter.getDayCodeFromTS(event.startTS, tz)
val tempstartts = Formatter.getLocalDateTimeFromCode(tempstartdaycode)
val tempenddaycode = Formatter.getDayCodeFromTS(event.endTS + TWELVE_HOURS, tz)
val tempendts = Formatter.getLocalDateTimeFromCode(tempenddaycode)
val startDateTime = tempstartts
val endDateTime = tempendts
This makes a day code based on the original time zone (to get an accurate start date and end date). Then, it creates timestamps for the start (00:00 in the local time zone) and end (12:00 in the local time zone). This should get the dates to show correctly based on what the user intended when creating the event. I couldn't get it to work, because I can't figure out the finer details of how the events are drawn, and every test I did ended up buggy. But in theory it should work.