Repository navigation
Type admin times on the event's clock, in 24-hour time - #316
Merged
Merged
Conversation
EventLocalTimes generalises what Event and Message each did by hand: datetime-local strings are re-parsed in the event's zone at validation, and forms/views get the time back on that clock. Scan contexts, incidents and non-flight travel times now declare it too. Rows on those three tables saved before this hold the typed wall-clock as UTC. A times_in_event_zone flag (false for existing rows) keeps them rendering on UTC as before; the first time a legacy row's times are resubmitted, all of them move onto the event's clock and the flag flips. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012JmwPzDWunz2cS7cuhGMiW
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012JmwPzDWunz2cS7cuhGMiW
…ght clock Incident occurred_at is typed and prefilled on the event's clock and shown that way in admin, Slack and the HQ escalation, with legacy rows still on UTC. Every admin datetime-local field gets lang="en-GB" and a note saying which zone it's in; bans have no event, so they stay UTC and say so. The incident Slack diff is now read after saving, since a typed time is only moved onto the event's clock during validation. The update job skips posting when no change is one it describes, instead of sending Slack an empty message. A legacy row stays on UTC when an API client echoes back its unchanged instant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012JmwPzDWunz2cS7cuhGMiW
…ent's clock Scan point start and end times are typed, prefilled and listed on the event's clock in 24h, with legacy rows still on UTC. The scan history date filter and every "today" count use the event's calendar day rather than UTC's, so the unused Scan.today scope goes. Export filters read typed dates and times in the event's zone (ad hoc and saved templates), and their datetime inputs, server- or JS-built, get lang="en-GB". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012JmwPzDWunz2cS7cuhGMiW
Travel's non-flight times are read on the event's clock for every writer (admin travel page, onboarding, dashboard, guardian portal), so the columns keep one meaning, and every place that shows them, including the ticket PDF and CSV exports, shows them on the clock they were typed on. Legacy rows stay on UTC. Admin travel inputs, flight legs included, get lang="en-GB" and a zone note; participant-facing forms get neither. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012JmwPzDWunz2cS7cuhGMiW
leowilkin
force-pushed
the
leo/eloquent-hamilton-laj9io
branch
from
October 31, 2026 09:36
694dac7 to
da340e0
Compare
github-merge-queue
Bot
removed this pull request from the merge queue due to no response for status checks
Oct 31, 2026
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.
Problem
Admin
datetime-localfields submit a zone-less string like2026-07-12T09:30, and Rails casts it in the app zone, UTC. Event schedule times and scheduled messages already re-read that string on the event's clock, each with its own copy of the code. Scan point windows, incident times and train/bus/car travel times did not. A 09:30 check-in window at a Boston event was stored as 09:30 UTC (05:30 local), and readers that treat the value as an instant (the scanner API, the incident API) were off by the event's offset.Inputs also show 12- or 24-hour time depending on the browser.
Changes
EventLocalTimesconcern: a model declaresevent_local_times :attr, .... A typed wall-clock string is re-parsed in the event's zone at validation, after an event or timezone submitted in the same form has been assigned. A value with its own offset is left alone. Views uselocal_time(:attr),local_time_field_value(:attr)andtime_display_zone. Event and Message now use the concern instead of their own copies.scan_contexts,incidentsandtravelshold the typed wall-clock as UTC. A newtimes_in_event_zonecolumn marks them (false for existing rows; the model defaults new rows to true, so writes from an older deploy mid-rollout still read as legacy). They keep rendering on UTC exactly as before. The first time a legacy row's times are retyped through a form, all of its times are re-read as event-local and the flag flips, so a row never mixes the two readings. An unchanged instant echoed back by an API client does not flip it.datetime-localinput getslang="en-GB". Admin travel fields, flight legs and the JS-built leg and export filter inputs are included. Chrome and Safari take the format from the OS locale and ignorelang, so admins on a 12-hour system still see 12-hour inputs there.Scan.today(UTC day) had no callers left and is removed.langand the zone note. These times show on the clock they were typed on wherever they appear, including the ticket PDF and the CSV export. Flight legs keep their per-airport zones.saved_changesafter saving. Read before validation, an untouched time would count as an edit.SendIncidentUpdateToSlackJobskips the post when no change is one it describes. Before, it sent Slack an empty message and raised. That already happened on a time-only edit; re-saving a legacy incident made it easier to hit.Not changed
Testing
lang, the zone note, saving and legacy rows;bundle exec rspecexcludingspec/system: 3731 examples, 5 failures. All 5 are Passkit specs failing on a missingPASSKIT_APPLE_TEAM_IDENTIFIERin the test environment, and they fail the same way without these changes.bin/rubocopon the changed Ruby files: no offenses.Generated by Claude Code