https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=37707

Paul Derscheid <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |[email protected]

--- Comment #40 from Paul Derscheid <[email protected]> ---
Hi folks, started QA on this bug yesterday.

Problem: implicit timezones
- The timezone issues stem from the code being implicitly timezone-aware
without declaring which timezone is authoritative.
- When code uses .toISOString() or .toDate(), it performs timezone conversions
as side effects rather than intentional operations. This works when browser and
server timezones happen to match, but breaks otherwise.

The QA failures demonstrate this:
- PST browser: end date shifts +1 day
- NZDT browser: end date shifts +2 days
- The shift correlates directly with UTC offset

Potential fix for this: the library timezone is authoritative

I dug up some examples to check how other booking systems handle this, since
they have the same problem:
- Airbnb: Check-in/checkout times are in "local time" (property
timezone)(www.airbnb.com/help/article/41)
- Booking.com: "All timestamps returned by Booking.com's Demand API are in
UTC... convert from UTC dynamically based on user or property location" and
"Timing is based on the property's local timezone"
(developers.booking.com/demand/docs/development-guide/code-conventions,
 developers.booking.com/connectivity/docs/reporting-api/b_xml-reporting)

My understanding is that booking dates should be interpreted in the library's
timezone, not the patron's. This makes sense because:
- The item is physically (for common use cases right now) at the library
- Pickup/return happens during library hours
- Lead/trail periods align with library operations

How I implemented this:
- Form submission - Extract the DATE value the user selected (just YYYY-MM-DD),
then send as explicit UTC boundaries using dayjs.utc() to ensure startOf/endOf
operate in UTC, not browser timezone:
  dayjs.utc(startDate).startOf("day").toISOString()  //
"2026-01-20T00:00:00.000Z"
  dayjs.utc(endDate).endOf("day").toISOString()      //
"2026-01-20T23:59:59.999Z"
- This preserves the date regardless of browser timezone.
- Timeline display - Convert stored UTC back to library timezone using
$timezone(), then use $toDisplayDate() helper to create Date objects that
render consistently:
  const startServerTz = dayjs(data.start_date).tz($timezone());
  start: $toDisplayDate(startServerTz)
- This ensures staff see dates in library time, not their browser's time.
- Conflict detection - All date comparisons normalized to start-of-day to avoid
time-component interference.

The fix works, but the timezone handling should be made more explicit:
1. UI indicator - Show "(Library time)" near the date picker so patrons in
different timezones understand (conditionally, only show if needed due to tz
differences)
2. API contract - Document that booking dates represent library-local days,
stored as UTC
3. Future-proofing - When hourly bookings are added, the same principle
applies: times are in library timezone, converted to UTC for storage

This approach eliminates timezone bugs by design. I have a follow-up patch to
validate the idea and to retest what surfaced in QA. What do we think?

-- 
You are receiving this mail because:
You are watching all bug changes.
_______________________________________________
Koha-bugs mailing list
[email protected]
https://lists.koha-community.org/cgi-bin/mailman/listinfo/koha-bugs
website : http://www.koha-community.org/
git : http://git.koha-community.org/
bugs : http://bugs.koha-community.org/

Reply via email to