Repository navigation
fix(console): show prefs-page times in the browser's timezone - #219
Merged
Merged
Conversation
A reviewer on CEST saw the prefs page's "Preferences saved at" time two hours behind. The view resolved a zone on the server (Zulip's zone, then core.User.timezone, then UTC) and validated the form inside timezone.override(), but rendered the template after leaving it. Django converts aware datetimes to the zone active at render time, so the page showed UTC times under the reviewer's zone name. away_until was shown in UTC but read back in the reviewer's zone, so saving the form unchanged moved it earlier by that zone's UTC offset. The prefs page was also the only reviewer-facing surface that picked a zone on the server; the rest of the console and the bot's Zulip messages show times in the reader's own zone. So instead of only moving the render, use the browser's zone here too. The server renders times in its default zone, and the form posts back the zone they are in, in a hidden `timezone` field. prefs_form.js rewrites each away_until from its stored instant (data-utc) into the browser's zone and sets that field to match, so the server always reads a time in the zone it was shown in. Rendering stays inside the override. A posted zone the server cannot load saves nothing rather than misreading the times. The "saved at" time is a <time> element, localized by console/base.html like the rest of the console. Removes zulip_bot.services.user_timezone, which has no other caller, and with it a Zulip API call per render. Updates design doc 022 and the console/zulip_bot AGENTS.md files. core.User.timezone is now unread; dropping it is left as a follow-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bryangingechen
force-pushed
the
fix/console-prefs-timezone
branch
from
October 22, 2026 15:55
6ab7a7d to
1247614
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A reviewer reported that the "Preferences saved at" time on the console prefs page was two hours behind (they're on CEST).
The prefs view picked a zone on the server (Zulip's zone, then
core.User.timezone, then UTC) and validated the form insidetimezone.override(), but rendered the template after leaving it. Django converts aware datetimes to the zone active at render time, so the page showed UTC times under the reviewer's zone name.away_untilhad the same problem with a worse effect: it was shown in UTC but read back in the reviewer's zone, so saving the form unchanged moved it earlier by the zone's UTC offset. Existingaway_untilvalues for reviewers outside UTC may already have drifted, and the data doesn't show which ones.Rather than just moving the render, this switches the page to the browser's zone, as the rest of the console and the bot's Zulip messages already use. The server renders times in its default zone and the form posts back, in a hidden
timezonefield, the zone they are in.prefs_form.jsrewrites eachaway_untilfrom its stored instant into the browser's zone and sets that field to match, so the server always reads a time in the zone it was shown in. A posted zone the server can't load saves nothing and shows an error, rather than misreading the times. The "saved at" time is a<time>element, converted in the browser like other console timestamps. Without JS the page stays in the server's zone and says so.This removes
zulip_bot.services.user_timezone, which had no other caller, along with its Zulip API call on every page load, and updates design doc 022 and the console and zulip_bot AGENTS.md files.core.User.timezoneis now read by nothing; dropping the column is listed as a follow-up in doc 022.Tested: new tests in
console/tests/test_prefs.pyandzulip_bot/frontend/tests/prefs_form.test.js. Theconsole,coreandzulip_botsuites pass against the Compose Postgres, as domanage.py check,makemigrations --dry-run --check, vitest and ruff.🤖 Generated with Claude Code