Repository navigation
Description
Problem
Farm settings' "Date format" and "Time format" fields (web/src/routes/SettingsPage.tsx:544-552) are free-text inputs with a "Follow the locale" placeholder for empty. Unlike FirstDayOfWeek/UnitSystem in the same form, which are constrained to a fixed enum and presumably picked from a dropdown, these accept any string up to 32 chars.
This is deliberate to a point — they store a real .NET custom date/time format string (e.g. dd/MM/yyyy, MM-dd-yy HH:mm), and the space of formats farms might want is genuinely open-ended, not a short fixed list. But the server-side validation is weaker than it looks:
UpdateFarmSettingsValidator.cs:132-144 (BeAUsableFormat):
private static bool BeAUsableFormat(string? format)
{
if (string.IsNullOrWhiteSpace(format)) return true;
try
{
FormatProbe.ToString(format.Trim(), CultureInfo.InvariantCulture);
return true;
}
catch (FormatException)
{
return false;
}
}This only rejects a string that literally throws when used as a .NET custom format. .NET's custom date/time formatter treats most unrecognized letters as literal text rather than erroring — so something like "asdf" or "xyz123" passes this check and saves successfully, then renders as a garbled/nonsensical date everywhere in the app, rather than being rejected at entry. The check proves "won't crash," not "looks like a real date/time format."
Suggested fix
Two independent, additive improvements:
- SPA: offer a dropdown of common presets (e.g.
MM/DD/YYYY,DD/MM/YYYY,YYYY-MM-DDfor date;h:mm AM/PM,HH:mmfor time) with a "Custom…" option that reveals the existing free-text field — so most users never need to know format-pattern syntax at all, while power users retain the escape hatch. - Backend: tighten
BeAUsableFormatto also reject a format that round-trips to something implausible — e.g. render a fixed probeDateTimeOffsetwith the candidate format and confirm the output actually varies with the input differently per component (contains no digits, is identical regardless of the date fed in, etc.), or restrict accepted format specifiers to a known-safe allow-list of standard date/time custom-format characters (d,M,y,H,h,m,s,t, common separators) rather than accepting anything that merely fails to throw.
Either alone reduces the problem; both together close it — the dropdown keeps most users from typing anything at all, and the tightened validator protects the free-text escape hatch and the API directly (not just SPA users going through the form).
Docs
If implemented, update specs/product/GLOSSARY.md's farm-settings section and the SPA Help page/in-app glossary per AGENTS.md's doc-sync rule.
Activity
docs(web): stop overclaiming the custom format's validation guarantee