block / block/buzz

Desktop: 12-hour/24-hour clock preference — should the default follow the OS, and how far should it reach?

Open
#3,737 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

Opening this as the discussion venue for #3736 (GitHub Discussions is turned off on this repo, so an issue seemed like the right place). The implementation is already up as a draft PR; the open questions below are design calls I'd rather have decided by maintainers than guessed at.

**Motivation**

Every time-of-day label in the desktop app is produced by an `Intl.DateTimeFormat` pinned to `en-US`, so the app always renders `2:34 PM`. Anyone who reads time on a 24-hour clock — most of Europe, and plenty of people elsewhere — has no way to change it. It shows up in message rows, inbox labels, agent transcripts, project panels, search results, and the moderation queue.

**Proposed solution**

A **Clock** row in Settings → Appearance with System / 12-hour / 24-hour, backed by a localStorage preference that follows the same `useSyncExternalStore` shape as the existing `threadViewModePreference`. Every hour-bearing formatter routes through one of two helpers so there's a single place that decides the hour cycle. Draft PR: #3736.

**Open questions**

1. **Should the default be `12-hour` or `System`?** The PR defaults to `12-hour` because that is byte-for-byte what installs render today: upgrading changes nothing until someone picks a clock, and unit/screenshot tests stay deterministic regardless of the host's locale. The counter-argument is that `System` is what most users would expect, and the app already reads the host locale elsewhere. It's a one-line change either way — I went with the conservative option, but I'd switch on request.

2. **Should `system` also relax the pinned `en-US` locale?** Right now it resolves only the *hour cycle* from the host locale and keeps `en-US` for month and weekday names, so choosing 24-hour doesn't half-translate the UI into a language Buzz isn't localized for. If broader locale support is on the roadmap, this preference should probably fold into that instead of standing alone.

3. **How far should a change reach into already-rendered views?** The channel timeline, thread panel, and Home inbox bake formatted strings into memoized rows, so they subscribe to the preference and repaint immediately. Surfaces that format during render (agent transcripts, search results, project panels, drafts, moderation queue) pick the new clock up on their next render — in practice when you leave Settings. Making those repaint instantly means having the individual row components subscribe; I left it out to keep the diff focused, and because `AppShell.tsx` sits at 999 of the 1000-line `check-file-sizes` budget so the blunt app-shell-wide subscription isn't available.

4. **Mobile.** The Flutter app has its own `DateFormat('h:mm a')` formatters under `mobile/lib/features/channels/` and its own Appearance section. Should that ship in the same change, or as a follow-up that mirrors whatever shape gets agreed here?

**Alternatives considered**

- A boolean "Use 24-hour time" toggle instead of three options — simpler, but then there's no way to say "follow my OS", and the toggle's default has the same question baked in.
- Deriving the clock purely from the host locale with no setting at all — no UI surface to argue about, but it takes away the choice from anyone whose OS locale disagrees with how they want to read chat, and it would silently change what existing installs display.

**Additional context**

Searched open and closed issues and PRs for "24-hour", "24h", "12-hour", "time format", "clock format", "AM/PM" and "timestamp" before starting — none found.

Verification on the PR branch: `pnpm typecheck` clean, `pnpm test` 3793 passing / 0 failing, `biome check` clean on all changed files, and the `check-file-sizes` / `check-px-text` / `check-pubkey-truncation` gates pass. No screenshots yet — developed on Windows, where the hermit toolchain doesn't bootstrap, so the Tauri app couldn't be launched to capture one.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.