anyproto/anytype-ts · issue #2208 · PR #2233 · branch fix/2208-date-format-picker-symmetric-dates
The settings *Date Format* picker rendered every preview by formatting now(). On 12 days a year where day equals month (Jan 1, Feb 2, …, Dec 12) the Short (d/m/Y) and ShortUS (m/d/Y) options produce the exact same string, `05.05.2026` for both, so the user can't tell which radio button is which. Five-line fix: pin the preview sample to a fixed asymmetric date (Jul 30, 2020, already the convention used in the DateFormat enum comments). Plus two regression-guard tests in `date.test.ts`.
Open Settings → Language & Region → Date Format on any day where day equals month (12 days a year), and the picker shows two options with the exact same text. The reporter's screenshots from May 5 (`05.05.2026`) show two radio buttons reading `05.05.2026` and `05.05.2026` with no way to distinguish them, one is `dd.mm.yyyy`, the other is `mm.dd.yyyy`, and picking the wrong one changes how every date in the app renders.
Every option label is built by formatting today's timestamp. On symmetric dates `dd == mm`, the two single-digit-padded slash formats collapse to the same string.
The DateFormat enum already documents its own canonical examples using Jul 30, 2020 (`Short = "30/07/2020"`, `ShortUS = "07/30/2020"`), chosen precisely because day ≠ month. The fix uses that same sample as the picker preview, so every option renders distinguishably year-round and the labels never depend on what day it is.
Added to src/ts/lib/util/date.test.ts, both pass locally under vitest.
PR open against develop (Anytype's default branch), GitHub-noreply identity from the start, vitest + tsc + biome all clean on the patched files.
Traced the picker to UtilMenu.dateFormatOptions, confirmed both Short (`d/m/Y`) and ShortUS (`m/d/Y`) use zero-padded numeric formats that collapse when day == month. Added two regression-guard tests covering positive (asymmetric sample → distinguishable) and negative (symmetric date → bug reproduced) cases, both pass locally.
Five lines of code change in menu.ts (one helper-comment block + one line move), 28 lines of new test coverage. TS clean (3 pre-existing errors in `dispatcher.ts` / `relation.ts` due to ungenerated proto files, unrelated). Biome lint clean on both patched files. Vitest run on the new tests: 2 passed.
PR body explains the root cause with an inline diff, lists the test commands, and includes the AI-assistance disclosure. Issue #2208 cross-commented so the reporter sees the fix without navigating to the PR list.
2026-05-27 21:43 CEST: @ra3orblade (Andrew Simachev, the area owner identified in Phase 4b) approved → merged into develop → closed #2208 as completed, all in 4 consecutive minutes. No review comments requested. Clean accept. Maintainer signal validated retroactively, the +35/-1 footprint, the deterministic test pair, and the alignment with the enum-comment convention (Jul 30, 2020 sample) all combined into a one-look merge.
The shipped fix is the proof. The follow-up, once it makes sense to send, given Anytype is a small team, rides the K-Perception stack overlap (closed-beta encrypted notes app with AES-256-GCM + Y.js CRDT collab on encrypted blobs), the same problem space Anytype solves at a much larger scale. Paid-conversation odds rise because the merge happened without any sales surface attached, which means the next outreach lands with track record rather than pitch.